You are on page 1of 1436

Windchill® Customizer’s Guide

Windchill 9.1

Pro/INTRALINK® 9.1
Arbortext® Content Manager™
Windchill PDMLink®
Windchill ProjectLink™

September 2010
Copyright © 2009 Parametric Technology Corporation 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, Licensing, and Data Collection Information:


• For Windchill products, select About Windchill at the bottom of the product page.
• For CADDS 5, click the "i" button on the main menu.
• For InterComm products, on the Help main page, click the link for Copyright.
• For other products, click Help > About on the main menu of the product.
• For products with an Application button, click the button and then navigate to the product information.
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)
(OCT’95) or DFARS 227.7202-1(a) and 227.7202-3(a) (JUN’95), 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.227-7013 (OCT’88) or
Commercial Computer Software-Restricted Rights at FAR 52.227-19(c)(1)-(2) (JUN’87), as applicable. 09302009

Parametric Technology Corporation, 140 Kendrick Street, Needham, MA 02494 USA


Contents

Change Record ................................................................................................ xxvii

About This Guide............................................................................................ xxxiii


Related Documentation ........................................................................................................... xxxiii
Technical Support.................................................................................................................... xxxiv
Documentation for PTC Products............................................................................................ xxxiv
Comments ................................................................................................................................xxxv

I. Customization Overview Section


Customization Overview.................................................................................... 1-1
Configuration Options.................................................................................................................1-2
Properties and Preferences ................................................................................................. 1-2
Object Initialization Rules .................................................................................................... 1-3
Soft Typing........................................................................................................................... 1-4
Organization and Container Templates ............................................................................... 1-4
Customizations ...........................................................................................................................1-5
Data Model Customizations ................................................................................................. 1-5
Service Customizations ....................................................................................................... 1-5
User Interface Customizations............................................................................................. 1-6
Info*Engine .......................................................................................................................... 1-6
Custom Reports ................................................................................................................... 1-6
Windchill Customization Points ..................................................................................................1-8
Windchill Supported API ...................................................................................................... 1-8

The Windchill Development Environment........................................................ 2-1


Directory Structure......................................................................................................................2-2
The codebase Directory....................................................................................................... 2-5
The src Directory ................................................................................................................. 2-7
Artifact Management ..................................................................................................................2-8
Environment Variables ...............................................................................................................2-9
Class path ............................................................................................................................ 2-9
Path ..................................................................................................................................... 2-9
SQL path.............................................................................................................................. 2-9
Rational Rose virtual path map............................................................................................ 2-9

iii
Property Files........................................................................................................................... 2-10
wt.properties file ................................................................................................................ 2-11
service.properties file ........................................................................................................ 2-12
tools.properties file ............................................................................................................ 2-13
user.properties file............................................................................................................. 2-13
db.properties file................................................................................................................ 2-14
Properties and Property Files .................................................................................................. 2-15
Application Context Service/Resource Properties............................................................. 2-15

Getting Started With Windchill Customization ................................................3-1


An Overview of the Windchill Development Process ................................................................. 3-2
Verify The Development Environment................................................................................. 3-2
Model the Object in Rose .................................................................................................... 3-3
Generate Java Classes From Rose .................................................................................... 3-5
Create Database Tables ..................................................................................................... 3-5
Initialize the Object .............................................................................................................. 3-6
Design the GUI Layout ........................................................................................................ 3-6
Code the GUI ...................................................................................................................... 3-7
Run the Applet in Mozilla or Internet Explorer..................................................................... 3-8

Modeling Business Objects ...............................................................................4-1


Rational Rose and Windchill ...................................................................................................... 4-2
Windchill Modeling Heuristics .................................................................................................... 4-4
Windchill Foundation Abstractions ............................................................................................. 4-8
Windchill Foundation Interfaces .......................................................................................... 4-8
Windchill Foundation Classes ........................................................................................... 4-10

Managing Customizations .................................................................................5-1


Setting Up a Directory Structure for Managing Customized Files and Text Tailoring ................ 5-2
Directory Structure Diagram for Customized Files and Text Tailoring ................................ 5-2
PTC Script for Working with Customized Files.................................................................... 5-5
Using the Safe Area Directory Structure When Customizing Files ..................................... 5-7
Using the Safe Area Directory Structure When Installing the Windchill Service Pack ........ 5-8
Best Practices for Customizing Files Supplied by PTC ............................................................. 5-9
Changing Displayed Text Found in RBINFO Files .............................................................. 5-9
Managing codebase Property Files................................................................................... 5-11
Managing HTML Templates in the <Windchill>/codebase/templates/ Directory ............... 5-12
Managing the LogicalAttributes.xml File............................................................................ 5-12
Managing codebase/{wtcore,netmarkets,pdmlink} Files ................................................... 5-13
Managing Windchill Info*Engine Tasks ............................................................................. 5-13
INI Files for Workgroup Managers .................................................................................... 5-13

iv Windchill Customizer’s Guide


Managing Client JAR Files ................................................................................................ 5-14
Best Practices for Adding New Packages and Files.................................................................5-26
Modeling Recommendations ............................................................................................. 5-27
Adding a Custom Service Provider Property File .............................................................. 5-27
Modeled To Soft Type Conversion ...........................................................................................5-29
Assumptions of the Modeled To Soft Type Tool ................................................................ 5-29
Restrictions ........................................................................................................................ 5-29
What Happens When Converting a Class? ....................................................................... 5-30
The Tool............................................................................................................................. 5-31
Mapping File ...................................................................................................................... 5-32
Target Soft Type ................................................................................................................ 5-33
Column Query Names ....................................................................................................... 5-33

Windchill Utilities................................................................................................ 6-1


About the xconfmanager Utility...................................................................................................6-2
Formatting Property Value Guidelines ................................................................................. 6-4
About the windchill Command ....................................................................................................6-6
About the windchill shell .............................................................................................................6-8

Password Encryption......................................................................................... 7-1


Encrypted Passwords.................................................................................................................7-2
Objective .............................................................................................................................. 7-2
Solution ................................................................................................................................ 7-3
Customization Points ........................................................................................................... 7-9
Limitations.......................................................................................................................... 7-11
Sample Code ..................................................................................................................... 7-11
Additional Resources ......................................................................................................... 7-14

Customization Tutorial....................................................................................... 8-1


Tutorial Overview........................................................................................................................8-2
Goals ................................................................................................................................... 8-2
Assumptions ........................................................................................................................ 8-2
Outline ................................................................................................................................. 8-2
Create Administrator and User ...................................................................................................8-4
Create a Library and Document ...............................................................................................8-12
Create a New Attribute Definition and Add it to the Document Type........................................8-17
As the End User, Create a Document with the new Attribute...................................................8-22
Create a Document Soft Type ..................................................................................................8-25
Create an Instance of the New Document Soft Type ...............................................................8-27
Model a New Document Subclass............................................................................................8-28
Create an Instance of the New Document Subclass ................................................................8-38

Contents v
Verify the Customizations ........................................................................................................ 8-39
Summary.................................................................................................................................. 8-41

II. User Interface Customization Section


User Interface Technology Overview................................................................9-1
Windchill Client Architecture Overview ...................................................................................... 9-2
Basic Elements of a JSP page ............................................................................................ 9-2
Java Beans.......................................................................................................................... 9-3
Custom Tags and TagLibs .................................................................................................. 9-3
Java Services ...................................................................................................................... 9-3
Reusable Components........................................................................................................ 9-4
Adding Custom Code to all Windchill Client Architecture Pages ............................................... 9-8
Javascript and CSS files ..................................................................................................... 9-8
Maintenance Messaging ..................................................................................................... 9-8
Customization Points........................................................................................................... 9-8
Javascript Functions Overview .................................................................................................. 9-9
TableUtils – package........................................................................................................... 9-9
TreeHandler ...................................................................................................................... 9-10
asyncResponseHandler .................................................................................................... 9-11
rowHandler ........................................................................................................................ 9-11
requestHandler.................................................................................................................. 9-12
Other functions in main.js.................................................................................................. 9-12
Wizard.js functions ............................................................................................................ 9-13

Generic UI Customizations .............................................................................. 10-1


Handling Icons for Business Objects ....................................................................................... 10-2
Modeled Business Objects................................................................................................ 10-2
Customizing the Handling of Soft Attributes ............................................................................ 10-3
Format of AllClients.xml .................................................................................................... 10-3
Example ............................................................................................................................ 10-4
Customizing Role-Based UI Functions - Attribute Visibility...................................................... 10-5
Objective ........................................................................................................................... 10-5
Solution ............................................................................................................................. 10-7
Customization Points....................................................................................................... 10-10
Sample Code................................................................................................................... 10-13
Additional Resources ...................................................................................................... 10-13
Customizing Role-Based UI Functions - Action Visibility ....................................................... 10-14
Preferences............................................................................................................................ 10-15
Preference Macros .......................................................................................................... 10-15
Setting the Hierarchy....................................................................................................... 10-15

vi Windchill Customizer’s Guide


Getting Preferences ......................................................................................................... 10-16
Clearing a Preference ...................................................................................................... 10-16
Preference Registry ......................................................................................................... 10-17
Creating a Preference...................................................................................................... 10-17
Deleting a Preference ...................................................................................................... 10-20
Constructing URLs .................................................................................................................10-21
The URLFactory .............................................................................................................. 10-21
Using the URLFactory with JSP ...................................................................................... 10-21
Utilizing Windchill Gateways and Servlets with the URLFactory ..................................... 10-21
Utilizing relative links in the URLFactory ......................................................................... 10-21
Setting the URLFactory to Output Fully Qualified HREFs ............................................... 10-22
Writing a Mapping File ..................................................................................................... 10-22
Capturing Errors From the URLFactory ........................................................................... 10-23
Character Encoding in the URLFactory ........................................................................... 10-23
Offline Package Customization ..............................................................................................10-24
Objective .......................................................................................................................... 10-24
Solution ............................................................................................................................ 10-24
Customization Points ....................................................................................................... 10-26
Limitations........................................................................................................................ 10-26
Offline Package View Supported Icons ........................................................................... 10-26
Sample Code ................................................................................................................... 10-28
System Banner Alert Message ...............................................................................................10-29
Turning on the alert banner feature ................................................................................. 10-29
Displaying the alert message on the top of Windchill UI pages ....................................... 10-29

Customizing HTML Clients Using the Windchill JSP Framework................ 11-1


Customizing Generic Aspects of JSP Pages............................................................................11-2
Customizing UI Branding..........................................................................................................11-2
Customizing the UI with Ajax....................................................................................................11-4
Objective ............................................................................................................................ 11-4
Solution .............................................................................................................................. 11-4
Sample Code ..................................................................................................................... 11-6
Checkin/Checkout ....................................................................................................................11-8
Objective ............................................................................................................................ 11-8
Solution .............................................................................................................................. 11-9
Sample Code ................................................................................................................... 11-10
Component Access Control....................................................................................................11-11
Objective .......................................................................................................................... 11-11
Solution ............................................................................................................................ 11-12
Customization Points ....................................................................................................... 11-13

Contents vii
Sample Code................................................................................................................... 11-14
Attachments ........................................................................................................................... 11-16
Objective ......................................................................................................................... 11-16
Customization Points....................................................................................................... 11-22
Limitations ....................................................................................................................... 11-23
Sample Code................................................................................................................... 11-24
Property Panel ....................................................................................................................... 11-26
Objective ......................................................................................................................... 11-26
Solution ........................................................................................................................... 11-26
Customization Points....................................................................................................... 11-28
Sample Code................................................................................................................... 11-30
Customizing Access Control For Packages ........................................................................... 11-33
Objective ......................................................................................................................... 11-33
Solution ........................................................................................................................... 11-33
Limitations ....................................................................................................................... 11-34
Sample Code................................................................................................................... 11-35
Additional Resources ...................................................................................................... 11-36
Generating HTML Tags for ProductView Visualization Within a JSP Page ........................... 11-37
Tools Overview ...................................................................................................................... 11-40
Available Attributes Report.............................................................................................. 11-40
Debugging ....................................................................................................................... 11-41
Taglib documentation ...................................................................................................... 11-42
Action Report................................................................................................................... 11-43
Action Model Report........................................................................................................ 11-47
Adding Validation Logic for Actions and Properties ............................................................... 11-51
Objective ......................................................................................................................... 11-51
Applicability ..................................................................................................................... 11-51
Structure.......................................................................................................................... 11-51
Participants...................................................................................................................... 11-51
Collaborations ................................................................................................................. 11-52
Consequences ................................................................................................................ 11-53
Implementation................................................................................................................ 11-53
Sample Code................................................................................................................... 11-60

Adding Actions and Hooking Them Up in the UI ........................................... 12-1


Windchill Client Architecture Action Framework Overview ...................................................... 12-2
Objective ........................................................................................................................... 12-2
Solutions............................................................................................................................ 12-2
Customization Points....................................................................................................... 12-14
Sample Code................................................................................................................... 12-15

viii Windchill Customizer’s Guide


Tab Models.............................................................................................................................12-17
Objective .......................................................................................................................... 12-17
Customizing Role-based Visibility ..........................................................................................12-28
Objective .......................................................................................................................... 12-28
Solution ............................................................................................................................ 12-30
Customization Points ....................................................................................................... 12-33
Sample Code ................................................................................................................... 12-36
Additional Resources ....................................................................................................... 12-36
Navigation Stickiness .............................................................................................................12-37
Objective .......................................................................................................................... 12-37
Solution ............................................................................................................................ 12-37
Prerequisite knowledge ................................................................................................... 12-37
Additional Resources: ...................................................................................................... 12-39

Gathering the Data for the UI........................................................................... 13-1


Data Acquisition Configuration Properties................................................................................13-2
Objective ............................................................................................................................ 13-2
Solution .............................................................................................................................. 13-2
Customization Points ......................................................................................................... 13-8
Sample Code ..................................................................................................................... 13-8
Acquiring Data via Info*Engine.................................................................................................13-9
Objective ............................................................................................................................ 13-9
Solution .............................................................................................................................. 13-9
Customization Points ....................................................................................................... 13-11
Limitations........................................................................................................................ 13-12
Sample Code ................................................................................................................... 13-13
Additional Resources ....................................................................................................... 13-14
NmObject Utilities ...................................................................................................................13-15
Objective .......................................................................................................................... 13-15
Solution ............................................................................................................................ 13-15
NmCommandBean .......................................................................................................... 13-17
NmAction ......................................................................................................................... 13-18
NmOid.............................................................................................................................. 13-18
NmSimpleOid................................................................................................................... 13-18
NmContext ....................................................................................................................... 13-18

Presenting Information in the UI ..................................................................... 14-1


Attribute Handling .....................................................................................................................14-2
Objective ............................................................................................................................ 14-2
Solution .............................................................................................................................. 14-4
Customization Points ....................................................................................................... 14-12

Contents ix
Additional Resources ...................................................................................................... 14-20
Soft Attributes and SCAs ....................................................................................................... 14-21
Constructing and Rendering a Table Using the JSP Framework .......................................... 14-23
Objective ......................................................................................................................... 14-23
Solution ........................................................................................................................... 14-25
Customization Points....................................................................................................... 14-28
Limitations ....................................................................................................................... 14-61
Sample Code................................................................................................................... 14-62
Other Resources ............................................................................................................. 14-63
Windchill Client Architecture Tree .......................................................................................... 14-64
Objective ......................................................................................................................... 14-64
Solution ........................................................................................................................... 14-66
Customization Points....................................................................................................... 14-72
Sample Code................................................................................................................... 14-90
Adding Custom Modeled Attributes to all Table Views .......................................................... 14-91
Attribute Tables...................................................................................................................... 14-92
Objective ......................................................................................................................... 14-92
Solution ........................................................................................................................... 14-92
Sample Code................................................................................................................... 14-95
Generating the Name Attribute Server................................................................................... 14-97
Objective ......................................................................................................................... 14-97
Solution ........................................................................................................................... 14-97
Customization Points..................................................................................................... 14-100
Limitations ..................................................................................................................... 14-100
Sample Code................................................................................................................. 14-101
Additional Resources .................................................................................................... 14-101
Partial Activation of JSCA .................................................................................................... 14-102
Icon Delegates ..................................................................................................................... 14-103
Objective ....................................................................................................................... 14-103
Solution ......................................................................................................................... 14-103
UI Validation......................................................................................................................... 14-109
Objective ....................................................................................................................... 14-109
Solutions........................................................................................................................ 14-110
Customizing the Find Number Field..................................................................................... 14-152

Constructing Wizards....................................................................................... 15-1


Windchill Client Architecture Wizard ........................................................................................ 15-2
Objective ........................................................................................................................... 15-2
Solution ............................................................................................................................. 15-4
Customization Points......................................................................................................... 15-7

x Windchill Customizer’s Guide


Limitations........................................................................................................................ 15-15
Sample Code ................................................................................................................... 15-18
Wizard Processing..................................................................................................................15-19
Objective .......................................................................................................................... 15-19
Solution ............................................................................................................................ 15-20
Limitations........................................................................................................................ 15-37
Additional Resouces ........................................................................................................ 15-37
Building Wizards to Create a Single Object............................................................................15-38
Objective .......................................................................................................................... 15-38
Solution ............................................................................................................................ 15-41
Customization Points ....................................................................................................... 15-82
Sample Code ................................................................................................................... 15-84
Additional Resources ....................................................................................................... 15-89
Building Wizards to Edit a Single Object ................................................................................15-90
Objective .......................................................................................................................... 15-90
Solution ............................................................................................................................ 15-92
Sample Code ................................................................................................................. 15-107
Additional Resources ..................................................................................................... 15-113

Information Pages ............................................................................................ 16-1


Information Pages ....................................................................................................................16-2
Objective ............................................................................................................................ 16-2
Solution .............................................................................................................................. 16-2
Structure ............................................................................................................................ 16-3
Design Elements................................................................................................................ 16-3
Collaborations .................................................................................................................... 16-4
Consequences ................................................................................................................... 16-4
Implementation .................................................................................................................. 16-4
Create a jsp for your object type ........................................................................................ 16-6
Setup ............................................................................................................................... 16-12
Sample Code ................................................................................................................... 16-12
Known Uses..................................................................................................................... 16-14

Incorporating Pickers in JSP Clients.............................................................. 17-1


Picker Interaction......................................................................................................................17-2
Objective ............................................................................................................................ 17-2
Solution .............................................................................................................................. 17-3
Customization Points ......................................................................................................... 17-9
Sample Code ................................................................................................................... 17-10
Common Picker Configuration Options ..................................................................................17-14
Objective .......................................................................................................................... 17-14

Contents xi
Solution ........................................................................................................................... 17-14
Sample Code................................................................................................................... 17-16
Configuring a Context Picker ................................................................................................. 17-18
Objective ......................................................................................................................... 17-18
Solution ........................................................................................................................... 17-19
Customization Points....................................................................................................... 17-21
Configuring an Item Picker..................................................................................................... 17-24
Objective ......................................................................................................................... 17-24
Solution ........................................................................................................................... 17-25
Customization Points....................................................................................................... 17-27
Configuring an Organization Picker ....................................................................................... 17-31
Objective ......................................................................................................................... 17-31
Solution ........................................................................................................................... 17-32
Customization Points....................................................................................................... 17-34
Configuring a Type Picker...................................................................................................... 17-37
How to Use Type Picker.................................................................................................. 17-37
Overview ......................................................................................................................... 17-41
Customization Points....................................................................................................... 17-43
Attributes and Parameters supported by Type Picker..................................................... 17-44
Source code location....................................................................................................... 17-47
Configuring a User Picker ...................................................................................................... 17-50
Objective ......................................................................................................................... 17-50
Solution ........................................................................................................................... 17-51
Customization Points....................................................................................................... 17-53
Configuring a Participant Picker............................................................................................. 17-57
Objective ......................................................................................................................... 17-57
Solution ........................................................................................................................... 17-57
Customization Points....................................................................................................... 17-61
Sample Code................................................................................................................... 17-63

JSP Customization Scenarios ......................................................................... 18-1


Configuring a Picker to Offer Only Specific Soft Types Based on User-specified Criteria including
Restricted Life Cycle States ..................................................................................................... 18-2
Building a Picker that Enables Users to Select Projects from an External Project DB ............ 18-8
Pickers from table toolbar ...................................................................................................... 18-13
Objective ......................................................................................................................... 18-13
Solution ........................................................................................................................... 18-13
Customization Points....................................................................................................... 18-14
Generating HTML Tags for ProductView Visualization Within a JSP Page ........................... 18-16

Customizing the Product Structure Explorer (PSE) ...................................... 19-1

xii Windchill Customizer’s Guide


Customizing PSE Menus, Toolbars and Popup Menus............................................................19-2
Objective ............................................................................................................................ 19-2
Solution .............................................................................................................................. 19-3
Customization Points ......................................................................................................... 19-6
Limitations.......................................................................................................................... 19-6
Other Resources................................................................................................................ 19-7
Customizing PSE Table Display...............................................................................................19-8
Objective ............................................................................................................................ 19-8
Solution .............................................................................................................................. 19-9
Other Resources.............................................................................................................. 19-12
Customizing PSE for Soft Types ............................................................................................19-13
Objective .......................................................................................................................... 19-13
Solution ............................................................................................................................ 19-16
Customization Points ....................................................................................................... 19-22
Other Resources.............................................................................................................. 19-23
Customizing PSE to Handle Modeled Subclasses .................................................................19-24
Objective .......................................................................................................................... 19-24
Solution ............................................................................................................................ 19-24
Customization Points ....................................................................................................... 19-29
Other Resources.............................................................................................................. 19-30
Customizing PSE Structure Queries ......................................................................................19-31
Objective .......................................................................................................................... 19-31
Solution ............................................................................................................................ 19-32
Other Resources.............................................................................................................. 19-34
Customizing Attribute Displays within Section Headings .......................................................19-35
Customizing the Display of Attributes in Groups ............................................................. 19-35
Expanding/Collapsing the Display Groupings.................................................................. 19-40
Customizing the Number of Columns to Display ............................................................. 19-41
Customizing Tabs - Configure Existing Tabs with Subtabs....................................................19-43
Allow Additional Steps During New Object Creation ..............................................................19-45
Type Picker Display Customization ........................................................................................19-47
Disabling Actions by Object Type...........................................................................................19-49
Validator isValidTypeValidator ......................................................................................... 19-50
Creating a Requirements Tab ................................................................................................19-51
Updating the <TabSet> element to include the Requirements tab .................................. 19-51
Define a <Tab> element for the Requirements tab.......................................................... 19-52
Define the <AssociationTable> element for the Requirements tab ................................. 19-53
Define the <StructureAuthorDefinition> element for the association table ...................... 19-53
Define the <StructureDefinitionSimple> element for the part to requirement association 19-54

Contents xiii
Define the <Table> element for the Requirement type ................................................... 19-54
Define the menus for the Requirements tab.................................................................... 19-56
Define the labels, tool tips and mnemonics for the Requirements tab ............................ 19-59
Define <ActionDefinition> elements referred to in the <MenuItem> elements ................ 19-60
Implement an 'enabled decider' class to control when the tab is enabled....................... 19-62
Configurable Link Tables ....................................................................................................... 19-67
Configurable Links Example............................................................................................ 19-67
Installing the Configurable Links Example ...................................................................... 19-67
Uninstalling the Configurable Links Example .................................................................. 19-68
Customizing Configurable Link Tables............................................................................ 19-69
Defining Access Control Policy Rules for Configurable Links ......................................... 19-73

Customizing Windchill MPMLink.....................................................................20-1


Customizing Windchill MPMLink Overview .............................................................................. 20-2
XML Configuration Files .................................................................................................... 20-3
General Windchill MPMLink Customizations ........................................................................... 20-5
Changing the Availability of Windchill MPMLink Explorers ............................................... 20-5
Changing Default Units of Measure .................................................................................. 20-5
Customizing the Process Plan Explorer................................................................................... 20-7
Creating Custom Formulas ............................................................................................... 20-7
Changing Units of Measure for Cumulated Time and Cost............................................. 20-12
Customizing Work Instructions........................................................................................ 20-12
Customizing a Windchill MPMLink Explorer.................................................................... 20-20
Changing Operation Numbering...................................................................................... 20-22
Customizing the Manufacturing Product Structure Explorer .................................................. 20-23
Customizing the Transforming of an eBOM into an mBOM ............................................ 20-23

Customizing Search Functionality .................................................................. 21-1


Customizing Index Search Capabilities ................................................................................... 21-2
Input Parameters to the Index-Search Webject ................................................................ 21-2
Sorting IndexSearch Search Results ................................................................................ 21-4
Customizing Indexing Behavior ............................................................................................... 21-6
IndexSearch Fields............................................................................................................ 21-6
Creating a Custom InstreamIndexDelegate ...................................................................... 21-7
Windchill Client Architecture Search Customization .............................................................. 21-11
Search customization Scenarios ..................................................................................... 21-11
Objective ......................................................................................................................... 21-11
Solution ........................................................................................................................... 21-13
Sample Code................................................................................................................... 21-15
Search Elements and Associated JSPs................................................................................. 21-17
Search element and their associated JSP for Simple Search Page ............................... 21-17

xiv Windchill Customizer’s Guide


Search element and their associated JSP for Advanced Search Page ........................... 21-18

III. Business Logic Customization Section


Customizing Business Logic .......................................................................... 22-1
Identified Business Classes......................................................................................................22-2
Identity Attributes ............................................................................................................... 22-2
How Identity Is Assigned and Managed ............................................................................ 22-2
When to Use the IdentityService ....................................................................................... 22-5
How to Use the IdentityService.......................................................................................... 22-6
How to Implement System-Managed Identity .................................................................. 22-15
Customizing Iteration and Version Identifiers .........................................................................22-17
Customizing a Bill of Materials ...............................................................................................22-19
Overview .......................................................................................................................... 22-19
Customization .................................................................................................................. 22-19
Current Implementation of Visitors .................................................................................. 22-22
Customizing User Preferences...............................................................................................22-24
Preference Definition ....................................................................................................... 22-24
Visibility ............................................................................................................................ 22-24
Value Handler (type) ........................................................................................................ 22-25
Preference Instance......................................................................................................... 22-25
Preference Category........................................................................................................ 22-25
Preference Client ............................................................................................................. 22-25
The Preference Hierarchy................................................................................................ 22-25
Calling preference values ................................................................................................ 22-27
Adding Preferences ......................................................................................................... 22-27
Writing a Servlet Helper to Use URLFactory Functionality.....................................................22-30
Example URLFactory Usage/Instantiation ....................................................................... 22-31
Updating a Master Through an Iteration.................................................................................22-32
Introduction ...................................................................................................................... 22-32
Read-only and Queryable Master Attributes on the Iteration........................................... 22-33
Updating Master Attributes via the Iteration..................................................................... 22-33
Updating the Master and Iteration Separately ................................................................. 22-34

Customizing Change Management................................................................. 23-1


Change Management Delegates..............................................................................................23-2
ChooseLifeCycleDelegate ................................................................................................. 23-2
ChooseFolderDelegate ...................................................................................................... 23-2
ConcreteAssociationDelegate ........................................................................................... 23-3
DisplayIdentificationDelegate ............................................................................................ 23-4

Contents xv
Customizing Life Cycle Administration .......................................................... 24-1
Customizing the Display of Life Cycle Information................................................................... 24-2
Defining Customized Life Cycle Transitions ............................................................................ 24-3
Setting Up a Customized State-Based Versioning Scheme .................................................... 24-3
Adding The Series To StateBasedVersioning.xml And Loading The File ......................... 24-4
Making The Newly Added Version Schemes Available In The Lifecycle Administrator .... 24-5
Creating A Lifecycle Template Which Uses The New Version Series’.............................. 24-6
Setting Up The Object Initialisation Rules ......................................................................... 24-7
How The Revision Scheme Can Be Used......................................................................... 24-9

Customizing Workflow Administration........................................................... 25-1


Customizing Workflow HTML Templates ................................................................................. 25-2
Customizing Change Management Workflow Process Templates .......................................... 25-6
Sync on Change Request Submit ..................................................................................... 25-8
Sync on Multiple Object State Change............................................................................ 25-10
Installation and Upgrade ................................................................................................. 25-11
Code Impacted ................................................................................................................ 25-12
Customizing Promotion Request Workflow Processes .......................................................... 25-13
Promotion Request Approval Process ............................................................................ 25-13
Promotion Request Review Process............................................................................... 25-14
Key Customization Points ............................................................................................... 25-14
Customizing Workflow Events on an Object .......................................................................... 25-17
Creating a customized event on an object ...................................................................... 25-17
Emitting a customized event ........................................................................................... 25-18
Customizing Workflow Task Pages ....................................................................................... 25-19
Rendering custom workflow activity variables................................................................. 25-19
Rendering PBO UI Components ..................................................................................... 25-20
Auto Create Change Notice customization ..................................................................... 25-24
Implementing customized Task Page JSP...................................................................... 25-25
Use of Customized Tag Library and/or 3rd Party Tag Library......................................... 25-25
Refine and Review Workflow Transitions Best Practice ........................................................ 25-27
Objective ......................................................................................................................... 25-27
Solution ........................................................................................................................... 25-27

Customizing Workgroup Managers ................................................................ 26-1


Customizing and Administering Pro/ENGINEER Wildfire ........................................................ 26-2

Customizing Windchill Visualization Services............................................... 27-1


Custom Publishing ................................................................................................................... 27-2
Objective ........................................................................................................................... 27-2
Solution ............................................................................................................................. 27-2

xvi Windchill Customizer’s Guide


Limitations........................................................................................................................ 27-17
Additional Resources ....................................................................................................... 27-17

Report Generation ............................................................................................ 28-1


Overview...................................................................................................................................28-2
Basic Report Example ..............................................................................................................28-2
Query ................................................................................................................................. 28-2
Report Parameters ............................................................................................................ 28-7
Import and Export of Report Templates .................................................................................28-11
Customization Details.............................................................................................................28-15
Customizing the Query .................................................................................................... 28-15
Customizing the Report Format ....................................................................................... 28-16
Customizing the Report Generation Client ...................................................................... 28-30
Customizing the Report Generation URL ........................................................................ 28-33
Customizing Macros ........................................................................................................ 28-35
Customizing Query Builder Types ................................................................................... 28-37
Cognos Presentation Customization ......................................................................................28-38
Objective .......................................................................................................................... 28-38
Solution ............................................................................................................................ 28-39
Limitations........................................................................................................................ 28-42
Sample Code ................................................................................................................... 28-43
Reporting Info*Engine Task Data Source Customization.......................................................28-44
Intended Outcome ........................................................................................................... 28-44
Report Loading .......................................................................................................................28-50
ReportTemplate Data Source Customization .........................................................................28-59
Reporting Input Page Customization......................................................................................28-63
Objective .......................................................................................................................... 28-63
Solution ............................................................................................................................ 28-63
Customization Points ....................................................................................................... 28-65
Limitations........................................................................................................................ 28-66
Sample Code ................................................................................................................... 28-67
Report Localization Customization .........................................................................................28-68
Objective .......................................................................................................................... 28-68
Solution ............................................................................................................................ 28-69
Customization Points ....................................................................................................... 28-71
Limitations........................................................................................................................ 28-72
Sample Code ................................................................................................................... 28-72
Report Selection List Customization.......................................................................................28-74
Solution ............................................................................................................................ 28-74

Customizing Event Audits ............................................................................... 29-1

Contents xvii
Introduction .............................................................................................................................. 29-2
Overview of the Audit Event Framework.................................................................................. 29-3
ProjectAuditEvent Class.................................................................................................... 29-4
Audit Recorders................................................................................................................. 29-7
Windchill Auditing Framework Configuration..................................................................... 29-7
Capturing New Events ........................................................................................................... 29-10
Capturing default information about a new event............................................................ 29-10
Capturing new event-specific auditing information.......................................................... 29-11

Customizing Communication Tools................................................................ 30-1


Customizing Meetings.............................................................................................................. 30-2
Sample code for WebexUserInfoDelegate ........................................................................ 30-2
Customizing Action Items (Windchill ProjectLink Only) ........................................................... 30-3
Exposing or Hiding Customizable Attributes ..................................................................... 30-4
Reordering Customizable Attributes.................................................................................. 30-5
Designating Customizable Attributes as Required ............................................................ 30-5
Changing the Display Names of Customizable Attributes................................................. 30-5

IV. Services and Infrastructure Section


Windchill Services ............................................................................................ 31-1
Windchill Packages.................................................................................................................. 31-2
Engineering Factor Services .................................................................................................... 31-5
Handling CAD Models ....................................................................................................... 31-5
Handling Family Instances ................................................................................................ 31-7
Handling Model Structure.................................................................................................. 31-9
The Relationship Between CAD Models and WTParts ................................................... 31-11

System Generation ........................................................................................... 32-1


Overview of System Generation ............................................................................................. 32-2
How Rose UML Maps to Java Classes................................................................................... 32-3
Mapping Modeled Classes to Java ................................................................................... 32-4
Mapping Operations to Java ........................................................................................... 32-10
Mapping Attributes to Java.............................................................................................. 32-12
Mapping Associations to Java......................................................................................... 32-17
Implicit Persistable Associations Stored with Foreign ID References.................................... 32-21
Implementing Interfaces .................................................................................................. 32-28
Implementing the NetFactor Interface ............................................................................. 32-29
Implementing the ObjectMappable interface................................................................... 32-31
Implementing the Persistable interface ........................................................................... 32-33
Implementing the Externalizable interface ...................................................................... 32-33

xviii Windchill Customizer’s Guide


Extending the EnumeratedType class....................................................................................32-36
Stereotyping an interface as remote ................................................................................ 32-37
How Rose UML Maps to Info Objects ....................................................................................32-39
How Rose UML Maps to Database Schema ..........................................................................32-41
How Rose UML Maps to Localizable Resource Info Files......................................................32-47
Metadata Resource Info Header...................................................................................... 32-47
Resource Entry Format.................................................................................................... 32-48
Metadata Resource Entry Examples ............................................................................... 32-48
Building Runtime Resources ........................................................................................... 32-48
Using the Windchill System Generation Tool .........................................................................32-50
Registry Files ................................................................................................................... 32-50
Generating mData Files ................................................................................................... 32-51
Generating Java Code ..................................................................................................... 32-51
Generating Info Files ....................................................................................................... 32-52
Generating SQL Files ...................................................................................................... 32-52
Using Windchill System Generation in a Build Environment ..................................................32-54
Management of the mData File ....................................................................................... 32-54
Build Sequence................................................................................................................ 32-55
Command Line Utilities .................................................................................................... 32-55
Deploying Modeled Customizations .......................................................................................32-60
Objective .......................................................................................................................... 32-60
Solution ............................................................................................................................ 32-60

Customizing Modeled Elements ..................................................................... 33-1


Customizing Column Lengths...................................................................................................33-2

Enumerated Types ........................................................................................... 34-1


The EnumeratedType Class.....................................................................................................34-2
Creating an EnumeratedType Subclass...................................................................................34-3
Editing the Resource Info for an Enumerated Type .................................................................34-7
Enumerated Type Resource Info Header .......................................................................... 34-7
Resource Entry Format...................................................................................................... 34-7
Resource Entry Contents................................................................................................... 34-7
Building Runtime Resources ............................................................................................. 34-8
Localizing an Enumerated Type ...............................................................................................34-9
Extending an Enumerated Type .............................................................................................34-10
The Enumerated Type Customization Utility ..........................................................................34-11
Starting the Utility............................................................................................................. 34-12
GUI Usage of an Enumerated Type .......................................................................................34-12

Windchill Design Patterns ............................................................................... 35-1

Contents xix
The Object Reference Design Pattern ..................................................................................... 35-2
The Business Service Design Pattern ..................................................................................... 35-3
The Master-iteration Design Pattern ........................................................................................ 35-7

Developing Server Logic.................................................................................. 36-1


Overview .................................................................................................................................. 36-2
Service Management ............................................................................................................... 36-2
Automatic Service Startup................................................................................................. 36-2
Service Startup and Shutdown.......................................................................................... 36-3
Service Management ........................................................................................................ 36-4
Service Event Management..................................................................................................... 36-4
Service Event Registration ................................................................................................ 36-4
Service Event Subscription ............................................................................................... 36-5
Service Event Notification ................................................................................................. 36-6
Service Event Exception Handling .................................................................................... 36-7
Service Event Conventions ............................................................................................... 36-7
Implementing Business Data Types ........................................................................................ 36-8
Initializing Business Attributes........................................................................................... 36-8
Business Attribute Accessors............................................................................................ 36-8
Overriding Accessor Methods ........................................................................................... 36-9
Validating Business Attributes......................................................................................... 36-10
Implementing the checkAttribute Method ........................................................................ 36-12
Business Attribute Aggregation ....................................................................................... 36-12
Business Attribute Persistence........................................................................................ 36-13
Business Attribute Derivation .......................................................................................... 36-13
Implementing Business Services .................................................................................... 36-14
Initializing Business Services .......................................................................................... 36-14
Business Service Operations .......................................................................................... 36-15
Vetoing Business Service Events.................................................................................... 36-16
Business Service Rules................................................................................................... 36-16
Business Service Communication................................................................................... 36-17
Lightweight Services .............................................................................................................. 36-18
The Modeling Implementation ......................................................................................... 36-18
The Inner Class Implementation ..................................................................................... 36-19
Customizing service.properties .............................................................................................. 36-24
Windchill Multi-object Operations........................................................................................... 36-26

The Enterprise Layer ........................................................................................ 37-1


Enterprise Abstractions ............................................................................................................ 37-2
Simple Business Class...................................................................................................... 37-2
Folder Resident Business Class ....................................................................................... 37-4

xx Windchill Customizer’s Guide


Managed Business Class .................................................................................................. 37-5
Revision Controlled Business Class .................................................................................. 37-6
Iterated Folder Resident Business Class........................................................................... 37-8
Cabinet Managed Business Cclass ................................................................................... 37-9
Document Abstractions ..........................................................................................................37-10
Attributes Specific to Windchill Foundation & PDM ......................................................... 37-12
Part Abstractions ....................................................................................................................37-13
Design Overview.............................................................................................................. 37-13
Change Abstractions ..............................................................................................................37-21
Change Item Classes ...................................................................................................... 37-23
Associations with Product Information ............................................................................. 37-26
Change Item Modeling Approach .................................................................................... 37-29
Change Items Classes..................................................................................................... 37-30

Persistence Management ................................................................................ 38-1


Overview...................................................................................................................................38-2
Persistence Manager................................................................................................................38-2
Query........................................................................................................................................38-4
QuerySpec ......................................................................................................................... 38-4
SearchCondition ................................................................................................................ 38-5
QueryResult ....................................................................................................................... 38-5
Multiple Class Queries ....................................................................................................... 38-6
Transaction...............................................................................................................................38-8
Paging ......................................................................................................................................38-9
Referential Integrity ................................................................................................................38-12
Multi-object CRUD Persistence Manager APIs ......................................................................38-12
Batch (update where/delete from) Statement Capabilities .....................................................38-13
When to use..................................................................................................................... 38-13
Transaction Context and Listeners.........................................................................................38-14
Referential Integrity Association Validation During Object Delete..........................................38-15
Persistence Datastore Sequence Customization ...................................................................38-16
Objective .......................................................................................................................... 38-16
Solution ............................................................................................................................ 38-16
Customization Points ....................................................................................................... 38-18
Limitations........................................................................................................................ 38-19
Sample Code ................................................................................................................... 38-19

Advanced Query Capabilities.......................................................................... 39-1


QuerySpec................................................................................................................................39-2
Descendant Query Attribute .............................................................................................. 39-2
Single Column Expression in SELECT Clause.................................................................. 39-2

Contents xxi
Table Expression in FROM Clause ................................................................................... 39-4
Expression in WHERE Clause .......................................................................................... 39-4
Bind Parameters................................................................................................................ 39-8
Query Limit ........................................................................................................................ 39-8
SearchCondition ...................................................................................................................... 39-9
Compound Query ............................................................................................................ 39-10
Access Control Consideration ......................................................................................... 39-12
Sorting ............................................................................................................................. 39-13
Join Support .................................................................................................................... 39-14

Internationalization and Localization..............................................................40-1


Background .............................................................................................................................. 40-2
The Windchill Approach ........................................................................................................... 40-3
Localizing Text Visible to the User ........................................................................................... 40-5
Resource Info (.rbInfo) Files .................................................................................................... 40-8
wt.L10N.complete.............................................................................................................. 40-8
Resource Info Categories.................................................................................................. 40-8
General Resource Info File Usage Rules.......................................................................... 40-9
Resource Info File Descriptions by Category .................................................................. 40-10
Building Runtime Resource Bundles for Resource Info Files.......................................... 40-11

Customizing Archive, Purge, and Restore ..................................................... 41-1


Archiving Related Classes ....................................................................................................... 41-2
Enabling Archive/Purge/Restore for Custom Classes ............................................................. 41-4
Introduction........................................................................................................................ 41-4
Writing Handlers................................................................................................................ 41-4
Make entries in coreobjects.dtd , coreX05.xml.................................................................. 41-5
Make entries in RelationshipMap.xml................................................................................ 41-6
Limitations ......................................................................................................................... 41-7
Customizing Archive Upgrade ................................................................................................. 41-8
How customized archive upgrade works?......................................................................... 41-8
Writing upgrades ............................................................................................................... 41-9

Import Export Framework ................................................................................ 42-1


Overview .................................................................................................................................. 42-2
How to Write an IX Application ................................................................................................ 42-3
Exporter Class................................................................................................................... 42-4
Using the Exporter to Export Objects ................................................................................ 42-8
How Import Works............................................................................................................. 42-9
Importer class.................................................................................................................. 42-12
Use Importer to import object from XML files .................................................................. 42-14

xxii Windchill Customizer’s Guide


How to Write Exp/Imp Handlers .............................................................................................42-17
Writing Export Handlers for the Export Process .............................................................. 42-17
How to Write Handlers for the Import Process ................................................................ 42-20
Navigating Through an Object’s Structure with ObjectSet Application...................................42-26
Object Collection.............................................................................................................. 42-26
Navigating Rules.............................................................................................................. 42-26
List of Existing Generators and Filters ............................................................................. 42-31
Examples ......................................................................................................................... 42-32
Simple Export Handler Code: .......................................................................................... 42-38
Simple Import Handler Code: .......................................................................................... 42-43
Product Design eXchange (PDX) Support for Export.............................................................42-46
Customization Points ....................................................................................................... 42-47
Supported APIs................................................................................................................ 42-47
Sample Program .............................................................................................................. 42-51

Evolvable Classes ............................................................................................ 43-1


Background Information ...........................................................................................................43-3
General Externalization Guidelines ..........................................................................................43-4
Hand-coded Externalization Guidelines ...................................................................................43-4
Migration Guidelines for Classes with Hand-coded Externalization .........................................43-5
Examples of Generated Externalization Code for Evolvable Classes ......................................43-6
Example of Version/UID Mapping Table............................................................................ 43-6
Example of Generated Constants...................................................................................... 43-6
Example of a writeExternal Method ................................................................................... 43-6
Example of a readVersion Method .................................................................................... 43-7
Example of a readVersion<EXTERNALIZATION_VERSION_UID> Method..................... 43-7
Example of a readOldVersion Method ............................................................................... 43-9

Creating Large Objects (LOBs) ....................................................................... 44-1


Creating Large Objects (LOBs) ................................................................................................44-2
Modeling Large Objects ..................................................................................................... 44-2
DDL Generation ................................................................................................................. 44-2
Reading and Writing LOBs ................................................................................................ 44-2
Small BLOBs ..................................................................................................................... 44-3
Inline BLOBs ...................................................................................................................... 44-3
Example ............................................................................................................................. 44-4

Customizing Data Formats .............................................................................. 45-1


Adding and Updating Data Formats for Content Holders .........................................................45-2
Adding Data Formats ......................................................................................................... 45-2
Updating Data Formats...................................................................................................... 45-3

Contents xxiii
Listing Available Data Formats.......................................................................................... 45-3
Renaming a Data Format .................................................................................................. 45-3
Deleting a Data Format ..................................................................................................... 45-4

V. Customization Appendices Section


Extendable Classes in the Windchill Supported API...................................... A-1
PDM Business Information Classes...........................................................................................A-2
Enterprise Business Information Classes ..................................................................................A-2
Windchill Services ......................................................................................................................A-2
Foundation Classes ...................................................................................................................A-3
PDM Auxiliary Business Information Classes ............................................................................A-3
Business Logic Classes .............................................................................................................A-3
Server Development Classes ....................................................................................................A-4
Client Development Classes ......................................................................................................A-5

Multi-Object Conversion Guidelines ................................................................ B-1


Conversion Overview .................................................................................................................B-2
Objectives............................................................................................................................ B-2
Considerations .................................................................................................................... B-2
API Guidelines ...........................................................................................................................B-3
Multi-Object vs. Multi-Multi-Object APIs .............................................................................. B-3
Converting Boolean Operations .......................................................................................... B-4
Retaining Single-Object Operations .................................................................................... B-4
WTCollection vs. WTSet/WTList and WTHashSet/WTArrayList ......................................... B-4
Empty collections ................................................................................................................ B-5
Memory considerations ....................................................................................................... B-6
Collections Guidelines ...............................................................................................................B-7
Inflating................................................................................................................................ B-7
Using connect() ................................................................................................................... B-7
WTKeyedMap vs.WTValuedMap ........................................................................................ B-7
OBJECT_IDENTIFIER vs.VERSION_FOREIGN_KEY collections ..................................... B-7
Modifying collections ........................................................................................................... B-8
Event Dispatch Guidelines .........................................................................................................B-9
Cleanup ............................................................................................................................... B-9
Use of collections ................................................................................................................ B-9
Single-and multi-object listeners? ....................................................................................... B-9
KeyedEvent's getEventTarget()API................................................................................... B-10
Multi-Object Delegation Guidelines..........................................................................................B-10
Converting to wt.services.ac.DefaultServices ................................................................... B-10
Multi-Object Exceptions Guidelines .........................................................................................B-11

xxiv Windchill Customizer’s Guide


Basic expectations ............................................................................................................ B-11
Pre-flight checks ............................................................................................................... B-11
Multi-object Exceptions and Single-Object APIs............................................................... B-12
Multi-Object CRUD API Guidelines ......................................................................................... B-13
Internal Dependency Issues ............................................................................................. B-13
Batch Update/Delete Guidelines ............................................................................................. B-13
When to Use? ................................................................................................................... B-13
Transaction Context/Listener Guidelines................................................................................. B-14
Transaction Context vs.Method Context........................................................................... B-14
Single-object contexts....................................................................................................... B-14
Deferred validation/work with transaction listeners........................................................... B-14
Neat Tips and Tricks................................................................................................................ B-15
Inflating references ........................................................................................................... B-15
Persisting interdependent data ......................................................................................... B-15

Creating Non-Modeled Services for Listening.................................................C-1


Overview.................................................................................................................................... C-2
Create a Service Interface......................................................................................................... C-2
Create a Standard Service Class .............................................................................................. C-3
Compile ..................................................................................................................................... C-5
Register the New Service .......................................................................................................... C-6
Restart the Method Server ........................................................................................................ C-6

Windchill Profiler ................................................................................................D-1


Overview.................................................................................................................................... D-2
Profiler Features ........................................................................................................................ D-2
Profiler Operation ...................................................................................................................... D-2

Additional Topics - Client Customization ........................................................ E-1


Defining Non-JSP Actions to be Executed From a JSP Page................................................... E-2
Default Assignment of URL ................................................................................................ E-2
Assignment of URL When renderType="GENERAL" or "GENERAL_WITH_CONTEXT" .. E-3
Assignment of URL When renderType="PDM" .................................................................. E-3
actions.xml Elements .......................................................................................................... E-4
URLFactory in the JSP Environment......................................................................................... E-5
Creating an URLFactory ..................................................................................................... E-6
Setting the JSP Reference Point ........................................................................................ E-6
Generating Links on the Page ............................................................................................ E-8
Internationalizing JSP Pages in Windchill........................................................................... E-9
Using File-Handling Applets in Non-JSP Clients ..................................................................... E-14
The Three Applets ............................................................................................................ E-14

Contents xxv
Advantages and Disadvantages........................................................................................ E-14
The File Selection Applet .................................................................................................. E-15
The Upload Applet............................................................................................................. E-22
The Download Applet ........................................................................................................ E-41

Index

xxvi Windchill Customizer’s Guide


Change Record

This section details the major changes in this guide.


Table 1 Changes for 9.1

Chapter Description

Chapter 7, Password Encryption New chapter for release 9.1 MR050

Chapter 9, User Interface Technology Added the Adding Custom Code to all
Overview Windchill Client Architecture Pages
section to this chapter

Chapter 10, Generic UI • Added the Offline Package


Customizations Customization section to this
chapter
• Added the System Banner Alert
Message section to this chapter
• Removed the "Customizing
Online Help" section from this
chapter.
• Removed the "Defining
Localizable Text for the UI"
section from this chapter.
(MR060)

xxvii
Chapter Description

Chapter 11, Customizing HTML • Updated the Action Report


Clients Using the Windchill JSP section.
Framework
• Removed the "Customizing
Online Help for a JSP
Component" section.
• Added the Component Access
Control section to this chapter.
• Added the Customizing Access
Control For Packages section to
this chapter.
• Updated the Action Report
section.
• Updated the Action Model Report
section.
• Added the Debugging section to
this chapter. (MR010)

Chapter 12, Adding Actions and • Updated the Windchill Client


Hooking Them Up in the UI Architecture Action Framework
Overview section. Added section
on defining an action image
directory.
• Added the Navigation Stickiness
section to this chapter.

xxviii Windchill Customizer’s Guide


Chapter Description

Chapter 14, Presenting Information in • Updated the Constructing and


the UI Rendering a Table Using the JSP
Framework section
• Updated the Windchill Client
Architecture Tree section
• Added the Adding Custom
Modeled Attributes to all Table
Views section
• Added the Generating the Name
Attribute Server section
• Added the Partial Activation of
JSCA section
• Added the Icon Delegates section
• Added the UI Validation section
• Added the Customizing the Find
Number Field section

Chapter 15, Constructing Wizards • Updated the Windchill Client


Architecture Wizard section with
information on clerks
• Updated the Windchill Client
Architecture Wizard section to
remove the Adding the Help Icon
section
• Updated the Wizard Processing
section
• Updated the Building Wizards to
Create a Single Object section

Change Record xxix


Chapter Description

Chapter 19, Customizing the Product • Added Customizing Attribute


Structure Explorer (PSE) Displays within Section Headings
to this chapter
• Added Customizing Tabs -
Configure Existing Tabs with
Subtabs to this chapter
• Added Allow Additional Steps
During New Object Creation to
this chapter
• Added Type Picker Display
Customization to this chapter
• Added Disabling Actions by
Object Type to this chapter
• Added Creating a Requirements
Tab to this chapter
• Added Configurable Link Tables
to this chapter

Chapter 20, Customizing Windchill • New chapter for release 9.1.


MPMLink
• Updated chapter for MR020.
• Added the Creating Custom
Formulas topic. (MR030)

xxx Windchill Customizer’s Guide


Chapter Description

Chapter 21, Customizing Search Updated the following section:


Functionality
• Search Elements and Associated
JSPs
Removed the following obsolete
sections:
• Adding a Search Component
• Searching for Soft Types and
Attributes
• Adding Attributes to the Search
Pages
• SearchableAttributes.properties
File
• Adding Actions to the Search
Results Table
• Changing the Layout of the
Search Page
• Adding a New Type to the Search
User Interface
• Customizing the Layout of the
Search Results Page
• Adding Different Formats for
Exporting Search Results
• Loading an OOTB Saved Query

Chapter 22, Customizing Business Updated the Customizing a Bill of


Logic Materials section

Chapter 25, Customizing Workflow Added the Refine and Review


Administration Workflow Transitions Best Practice
section. (MR070)

Chapter 27, Customizing Windchill New chapter.


Visualization Services

Chapter 28, Report Generation Added Report Selection List


Customization to this chapter.

Change Record xxxi


Chapter Description

Chapter 38, Persistence Management Updated the Persistence Datastore


Sequence Customization section with
information on how to manually create
a sequence (i.e. not requirng
InfoModeler) in sqlserver. (MR040)

xxxii Windchill Customizer’s Guide


About This Guide

The Windchill Customizer's 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 provides customization information for the following Windchill
solutions:
• Windchill PDM Link
• Windchill ProjectLink
• Pro/INTRALINK 9.1
• Arbortext Content Manager
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.
Some code examples in this guide have been reformatted for presentation
purposes and, therefore, may contain 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
The following documentation may be helpful:
• What's New for Windchill Release 9.1
• Windchill Installation and Configuration Guide
• Windchill Upgrade Guide
• Windchill Data Loading Reference and Best Practices Guide
• Windchill System Administrator's Guide
• Windchill Business Administrator’s Guide
• Windchill Performance Tuning Guide

xxxiii
• Windchill User's Guide
• Workgroup Manager Customization Guide
If books are not installed on your system, see your system administrator.

Technical Support
Contact PTC Technical Support via the PTC Web site, phone, fax, or e-mail if you
encounter problems using <product name> or the product documentation.
For complete details, refer to Contacting Technical Support in the PTC Customer
Service Guide. This guide can be found under the Self Help section of the PTC
Web site at:
http://www.ptc.com/support/support.htm
The PTC Web site also provides a search facility for technical documentation of
particular interest. To access this page, use the following URL:
http://www.ptc.com/support/support.htm
You must have a Service Contract Number (SCN) before you can receive
technical support. If you do not have an SCN, contact PTC Maintenance
Department using the instructions found in your PTC Customer Service Guide
under Contacting Your Maintenance Support Representative.

Documentation for PTC Products


You can access PTC documentation using the following resources:
• Windchill Help Page--The Windchill Help Center is an online
knowledgebase that includes a universal index of all Windchill
documentation; you can access it by clicking a help icon or the Help link in
any Windchill page header. You can browse the entire Windchill
documentation set, or use the advanced search capability to customize your
keyword search.
• Reference Documents Web Site--All books are available from the Reference
Documents link of the PTC Web site at the following URL:
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 Web site. For more
information on SCNs, see Technical Support:
http://www.ptc.com/support/support.htm

xxxiv Windchill Customizer’s Guide


Comments
PTC welcomes your suggestions and comments on its documentation. Send
comments to the following address:
documentation@ptc.com
Please include the name of the application and its release number with your
comments. For online books, provide the book title.

About This Guide xxxv


xxxvi Windchill Customizer’s Guide
I
Customization Overview
Section

Chapter Page
Customization Overview........................................................................ 1-1
The Windchill Development Environment ............................................ 2-1
Getting Started With Windchill Customization ..................................... 3-1
Modeling Business Objects.................................................................... 4-1
Managing Customizations...................................................................... 5-1
Windchill Utilities.................................................................................. 6-1
Password Encryption.............................................................................. 7-1
Customization Tutorial .......................................................................... 8-1
1
Customization Overview

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.

Topic Page
Configuration Options.........................................................................................1-2
Customizations ....................................................................................................1-5
Windchill Customization Points..........................................................................1-8

1-1
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 the Property Files section of the The Windchill Development Environment
chapter on page 2-10 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
organization’s or an application container’s (e.g. Product, Library), or a specific
user’s setup.
See the Preferences section of the Generic UI Customizations chapter on page
10-15 for some additional information on preferences.
The table below provides just a few of the available preferences:

Preference Description

Change Notice without Change Allows creating a change notice without a


Request change request.

Enable Structure Propagation Enables propagation of effectivity statements


down a product structure.

1. For legacy reasons, some Properties also control application behavior.

1-2 Windchill Customizer’s Guide


Preference Description

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 according to the
administrator-setup schedule.

Display Thumbnails 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 company’s 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 Customizing Workflow
Administration chapter on page 25-1.

Customization Overview 1-3


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

1-4 Windchill Customizer’s 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 in conjunction with Rational Rose to customize your Windchill
environment. Information Modeler contains the Windchill modeling files and
source code that you will use to develop your customizations. Rational Rose is a
design and analysis tool to model business objects. Rational Rose allows you to
create a graphical representation of an application, its components, their
interfaces, and their relationships. 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 then 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 Rational Rose see Rational Rose and Windchill on page
4-2.

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)
• 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 part’s
details, get the cost of the part from the ERP system and display it in the same
UI)

Customization Overview 1-5


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

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 more information on Info*Engine see Managing Windchill Info*Engine
Tasks on page 5-13.

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 Windchill-
integrated 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 9.1 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
drill-down reports, use the optional third-party reporting authoring tool. This
optional authoring tool also allows you to modify out-of-the-box reports. Using

1-6 Windchill Customizer’s Guide


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

Customization Overview 1-7


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/doc/pds_calendar.pdf
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.
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

1-8 Windchill Customizer’s Guide


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 1-9


1-10 Windchill Customizer’s Guide
2
The Windchill Development
Environment

This chapter describes the Windchill development environment.

Topic Page
Directory Structure ..............................................................................................2-2
Artifact Management...........................................................................................2-8
Environment Variables........................................................................................2-9
Property Files ....................................................................................................2-10
Properties and Property Files ............................................................................2-15

2-1
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.
cgi-bin
Contains the Windchill common gateway interface wrappers.

2-2 Windchill Customizer’s Guide


codebase
Contains the runtime environment files.
conf
Configuration files for Apache, InfoEngine 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 clients.
installer
Contains files used by, or created by, the installation process, including
installation logs.
installlib
Library of code used by Windchill installers and related utilities.
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.
prog_examples
Contains Info*Engine programming examples.
src
Contains files for modeling customizations, and rbInfo files for text
srclib
Contains module jar files.
step
Contains STEP application related files.
taskeditor
Contains the I*E task editor startup scripts, help files reside and is the runtime
directory for the task editor.

The Windchill Development Environment 2-3


tasks
Contains Info*Engine tasks.
temp
Temporary files used by Windchill.
Upgrade
Contains files to facilitate the upgrade process.
vaults
Default file vault location.
WHC
Contains the Windchill Help Center which consists of the online help and the
pdf manuals.
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.

2-4 Windchill Customizer’s 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.1

The codebase Directory

Most of these directories contain third party product class files.


The html directory contains templates that are used to generate HTML
dynamically.

1. To allow presentation in manual format, many subdirectories in the wt


directory are not included in this figure.

The Windchill Development Environment 2-5


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 created by the Windchill code generation tool for every business object
modeled in Rose.
Files in the form <object> .ClassInfo.ser are also code-generated and contain
metadata needed by the runtime environment. They are all described in more
detail in the System Generation chapter on page 32-1.
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 wtx directory contains EPM-related files and directories.

2-6 Windchill Customizer’s Guide


The src Directory
In general, the src directory contains the source files needed for application
development. It holds the files necessary to create new models in Rose and
generate code. The src directory can be expanded to show the following
directories.

The src Directory

The customization directory contains programming examples of customizations,


which are described in more detail in either this guide or the readme file that is in
the 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:
• Rose model components: model files with the suffix .mdl and package files
with the suffix .cat. (The .cat file is described later in this chapter.)
• Code generation files: files with the suffix mData, which are intermediate
files created by the code generation tool and used to create Java classes, Info
classes, and SQL files (for more information, see the System Generation
chapter on page 32-1).
• Localizable ResourceInfo (.rbInfo) files, which contain customizable display
text for EnumeratedTypes and modeled elements.

The Windchill Development Environment 2-7


Artifact Management
In Rational Rose, you can optionally separate a model into controlled units as a
way of sharing code. Controlled units are source files with a .cat extension that
can be checked in and out of your source code control system.
Control units are created at the package level. In Rational Rose, right-click on a
package in the Browser window, select Units, select Control...; <package>,
select the filename for the controlled unit. The menu item is only selectable for
packages that are not controlled.
This action produces a file with the extension .cat. You can then check in and
check out these .cat files to whatever source code management system you use.
The directory structure used in the source code management system must match
the package structure used in Rose.
You can change a control unit that is read-only to write by selecting the
WriteEnable<package> item. This is useful if you want to manipulate the model
in some way (for example, temporarily changing its appearance before printing
it). Be aware that this action does write enable the file at the file system level, so if
you don’t want it left writable, select the Write Protect <package> item. These
are menu items are both available from the same Units menu item mentioned
above.

2-8 Windchill Customizer’s Guide


Environment Variables
When you install the Windchill Information Modeler, the settings required for
business modeling and code generation are set automatically. You should have to
do nothing more. But, if you have problems, the following sections give
information about required settings.

Class path
We recommend that you not make any modifications to your CLASSPATH after
installation. In particular, do not add the codebase directory. Doing so can cause
Netscape Navigator to incorrectly assume a security violation. (See the Windchill
Installation Guide for further information.)

Path
Your PATH variable should contain <Windchill> \bin and JDK\bin. <Windchill>
contains batch scripts, such as ToolsSetup.bat, required to use the Information
Modeler. (See the Windchill Installation and Configuration Guide for further
information.)

SQL path
You must create (or add to) your SQLPATH variable and set it to the location
where the SQL scripts that create the necessary tables will be written. When you
are in a SQL*Plus session, SQL*Plus searches these directories for SQL scripts.
By default, this value is c:\ptc\windchill\db\sql.

Rational Rose virtual path map


Rose provides a virtual path map mechanism to support parallel development by
teams. The virtual path map enables Rose to create model files whose embedded
path names are relative to a user-defined symbol. Thus, Rose can work with
models moved or copied among workspaces and archives by redefining the actual
directory associated with the user-defined symbol.
The virtual path map contains a list of entries, each of which represents a mapping
between a virtual path symbol and an actual path name. To use this capability with
Windchill, include the following virtual path map entries:
• WT_EXTENSIONS, which specifies the directory that contains the Windchill
extensions to Rational Rose.
• WT_STD_PACKAGES, which specifies the directory where the packages for
Java reside.
• WT_WORK, which specifies the top level directory where .mData files and
.cat files are located. Every wt package modeled in Rose has a corresponding
.cat file in the c:\ptc\windchill\src\wt directory.

The Windchill Development Environment 2-9


• Module specific path maps will also be created automatically, based on
information stored in moduleRegistry.properties and moduleDir.properties.
For example, wnc/CommonCore is the path map for the CommonCore
module of the wnc assembly.

Note: See the Windchill Installation and Configuration Guide for further
information.

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.
• debug.properties
Contains properties used by Windchill code to control debug info capturing.
(See the wt.util package entry in your installed Windchill Javadoc for more
information)
• user.properties
Contains user overrides used by Rational Rose and the Windchill code
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 Windchill’s database connection layer to access
the database.
The System Generation jars (SystemGeneration.jar, WindchillUtil.jar &
CommonCore.jar) contain:
• tools.properties

2-10 Windchill Customizer’s Guide


Contains properties used by Rational Rose and the Windchill code 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
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 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

The Windchill Development Environment 2-11


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 fully-
qualified 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
InetAddress.getLocalHost() method, which may return a name that is not
known to remote clients. We recommend that this property be set to the fully-
qualified 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 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

2-12 Windchill Customizer’s Guide


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.
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 file
The tools.properties file contains properties that are used by the System
Generation tools. The following properties within tools.properties are of interest:
• wt.generation.bin.dir, which specifies where .ClassInfo.ser files (serialized
info objects) will be generated, following the package structure.
• wt.generation.source.dir, which specifies where .mData files are expected to
be found and where .java files will be generated, following the package
structure.

Note: Because the source.dir entry informs the code generator of the location of
mData files and, in Rose, the WT_WORK variable informs the model information
export tools of the location of mData files, they must point to the same location.

• wt.generation.sql.dir, which specifies where SQL scripts will be generated.


• wt.generation.sql.xxxTablesSize, which sets default sizes for tables.
• wt.classRegistry.search.path, which specifies the path to search for files
representing classes to be registered.
• wt.classRegistry.search.pattern, which specifies the file pattern to consider as
representing classes to be registered.

Note: Because tools.properties is contained within the SystemGeneration.jar,


user overrides to these properties are placed in codebase\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.

The Windchill Development Environment 2-13


db.properties file
The db.properties file contains properties that are used by Windchill’s 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.

2-14 Windchill Customizer’s Guide


Properties and Property Files
As you have read in the previous sections, template processing relies heavily on
the use of properties contained in properties files to locate the template, processor
and other resources for an HTML client.
In general, properties for Windchill Foundation PDM out-of-the-box clients are
grouped as follows:
codebase/service.properties – properties specifying the TemplateProcessor,
ActionDelegate, URLActionDelegate, and FormTaskDelegate to use for a given
action/object type
codebase/htmltemplate.properties – properties specifying the HTML template
to use for a given action/object type
codebase/htmlcomponent.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 the About the
xconfmanager Utility section of the Windchill Utilities chapter on page 6-2.
See the section Properties and Property Files on page 2-15 for more information
on the property files used in Windchill.

Application Context 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 2-15


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 of 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.
To be loaded correctly at runtime, files containing application context service
properties must be listed for one of the following properties in wt.properties:

2-16 Windchill Customizer’s Guide


wt.services.applicationcontext.WTServiceProviderFromProperties.
defaultPropertyFiles

wt.services.applicationcontext.WTServiceProviderFromPrope
rties.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 the Managing
Customizations chapter on page 5-1 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 the Managing Customizations chapter on
page 5-1.

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.TypeBasedServiceProviderFromProperties.defaul
tPropertyFiles
• wt.services.applicationcontext.TypeBasedServiceProviderFromProperties.custo
mPropertyFiles.
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

The Windchill Development Environment 2-17


TypeBasedServiceProviderFromProperties.CustomPropertyFiles using the
xconfmanager utility. This procedure is described in the Managing
Customizations chapter on page 5-1.

2-18 Windchill Customizer’s Guide


3
Getting Started With Windchill
Customization

The remainder of this manual describes how to create applications using the
Windchill product and how to customize existing Windchill applications. You are
assumed to be familiar with the third party components used with Windchill: Java,
Rational Rose, Oracle, and the IDE (integrated development environment) of your
choice. Windchill supports any Java IDE customers choose to use. This manual
does not address how to use these products in general, but how to use them as they
relate to Windchill.
This chapter gives you a brief overview of the Windchill development process and
shows how to create a simple application using Windchill. By following this
example, you will perform the major steps in developing an application and verify
that the development environment (as described in the The Windchill
Development Environment chapter on page 2-1) is set up correctly.

Topic Page
An Overview of the Windchill Development Process ........................................3-2

3-1
An Overview of the Windchill Development Process
The process of developing Windchill applications is iterative and model-driven.
You start with Rational Rose, an object-oriented analysis and design tool. Rose
gives you the capability to create a graphic representation — that is, a model — of
an application, its components, their interfaces, and their relationships. Windchill
provides foundation classes that can be loaded into Rose so you can include in the
applications any of the functionality already developed (for example, version
control and the ability to lock objects). In Rose, you can create your own classes
and extend those provided by Windchill.
When you finish the initial modeling phase, you use the Windchill code
generation tool to create Java code from the Rose model. This generated code is
already optimized to take advantage of Windchill’s architecture. You can then
implement in this code the server business logic and the client task logic. A Java
IDE, such as Jbuilder, NetBeans, or Eclipse, is useful for building the client-side
presentation portions of applications that include HTML and Java applets.
Windchill supports any Java IDE customers chooses to use.
Following testing, you can return to the model, make modifications, and repeat
the process without losing work you have already done. This iterative, model-
driven process allows you to create or customize an application, get portions of it
running as quickly as possible, and continually improve it.

Verify The Development Environment


This section identifies the environment you need to run this example. It discusses
only a subset of the information in the The Windchill Development Environment
chapter on page 2-1. See that chapter for more detailed information on setting up
the development environment.
We assume that Windchill and all required third party products are installed. If
you did not install Windchill yourself, you will need to know where it is installed.
These steps assume installation in the c:\ptc\windchill directory. You will also
need to know your Oracle user name, password, and host name.
1. Verify the following environment variables:
– PATH
Ensure that the PATH variable includes the Oracle path. An example
follows:
% [ ]SystemRoot% [ ]\system32;% [ ]SystemRoot% [ ];
C:\ORANT\BIN;c:\jdk1.1.6\bin

– SQLPATH
The SQLPATH specifies the directory in which sql scripts are generated.
It must match the value specified in the tools properties1 file entry named
wt.generation.sql.dir. By default, this value is (wt.home)\db\sql. For
example,

3-2 Windchill Customizer’s Guide


c:\ptc\windchill\db\sql

2. Verify the contents of the following property files:


– wt.properties
Set the following entry in the <Windchill>/codebase/wt.properties file:
java.rmi.server.hostname =<hostname >
For example,
java.rmi.server.hostname=Smith.windchill.com

– db.properties
In the windchill\db\db.properties file, ensure your Oracle user name,
password, and service name are entered in this file.
wt.pom.dbUser =<username >
wt.pom.dbPassword =<password >
3. Start the Windchill servers. Open a new console window.
– Start the server manager and a method server by entering the following
command:
java wt.manager.ServerLauncher

A window will be started for each but they will be minimized.


– Initialize the administrator tables by entering the following command in a
console window:
java wt.load.Demo

This command loads the database with administrative information.


Respond "yes" to all prompts. When prompted for a user name/password,
enter the same user name and password you use to access your computer.
4. Establish your Rose model directory.
In the c:\ptc\windchill\src directory, create the subdirectory helloWorld. This
directory will contain files for the helloWorld package.

Model the Object in Rose


1. Start Rational Rose and check the virtual path map. From the File menu,
select Edit Path Map and ensure the following values are set:
WT_WORK = c:\ptc\windchill\src
WT_EXTENSIONS = c:\ptc\windchill\RoseAddIn

1. See the tools.properties file and user.properties file descriptions in the The Windchill
Development Environment chapter.

Getting Started With Windchill Customization 3-3


WT_STD_PACKAGES = $WT_EXTENSIONS\Standard Packages
2. Establish the initial Rose model by performing the following steps:
a. From the File menu, select Open, browse to c:\ptc\windchill\src\wt, and
load the model WTDesigner.mdl.
b. When asked whether to load subunits, press the Yes button.
c. Save the model as c:\ptc\windchill\src\helloWorld\HelloWorld.mdl.
d. When asked whether to save subunits, press the No button.
3. Model the person class by performing the following steps:
a. In the Logical View/Main class diagram, drop in a Package icon and label
it helloWorld.
b. Use the dependency tool to draw dependencies from helloWorld to the wt
and java packages.
c. Go to the Main diagram of the helloWorld package.
d. Drop on a class icon and give the class the name Item (the parent for
Person). Attributes and operations for Item automatically appear. Change
the diagram to suppress attributes and operations of Item. Ensure that the
Show Visibility option is on for Item (so you can see in the diagram that it
comes from the fc package).
e. Drop on another class icon and give it the name Person.
f. Make Person a subclass of Item. (Use the generalization icon/tool to draw
a line from Person to Item.)
g. Insert the attributes name, age, title, and id. Name, title, and id should be
strings (String) and age should be an integer (int). Use lowercase or a mix
of upper- and lowercase letters for these attributes; do not use all
uppercase letters.2 Right click to start the specification dialog. Make all
the attributes public and change the Windchill property of each to
constrain=false. Click the Apply button for each change and, when you
are done, click the OK button.
h. Select the menu option Browse > Units. Select the HelloWorld package
and press the Control button. Save the unit to c:\ptc\windchill\src\
helloWorld\helloWorld.cat. With the helloWorld package selected, press
the Save button.

2. For every attribute modeled, a corresponding constant is generated using all


uppercase letters. For example, if you model an attribute of employeeName, a
constant of EMPLOYEE_NAME is generated. Modeling an attribute of
EMPLOYEE_NAME would cause the generated constant to conflict with the
attribute name. Therefore, unless the attribute being modeled is itself a
constant, do not name modeled attributes using all uppercase letters.

3-4 Windchill Customizer’s Guide


i. Save the Rose model file. When asked whether to save subunits, click the
No button.

Tip:

From this point on, saving the model is a two-step process:


1. Select the menu option Browse > Units to initiate the Units dialog. In the
Units dialog box, select the package you defined earlier and select Save.
When asked whether to save subunits, click the Yes button. Close the Units
dialog box.
2. Select the menu option File > Save. When asked whether to save subunits,
click the No button.

Generate Java Classes From Rose


1. Go to the parent package of the Person class (by selecting the Logical
View/Main diagram from the class browser, then selecting the helloWorld
package).
2. From the Tools menu, select Windchill > System Generation.
3. From the popup window, select Java Source Code, WT Introspector Support,
and Database Support, then click the OK button. The code generator creates
several files:
– An mData file (helloWorld.mData) and a Java file (Person.java), which
are put in the directory c:\ptc\windchill\src\helloWorld that you created
earlier in this example. (The generated mData file and java file go to the
named package in the source directory based on the value specified in the
tools properties entry named wt.generation.source.dir which, in this case,
is c:\ptc\windchill\src.)
– A ClassInfo file (Person.ClassInfo.ser), which is put in the directory c:\
ptc\windchill\codebase\helloWorld (this directory is created by the code
generator). (The location of this file is based on the value specified in the
wt.generation.bin.dir entry which, in this case, is c:\ptc\windchill\
codebase.)
– SQL scripts that create the tables which store the Person class, and a
directory named helloWorld in c:\ptc\windchill\db\sql which contains all
the scripts.
You can verify this step by finding these files in the directories.

Create Database Tables


In Oracle SQL*Plus, create the tables by running the following command:
@helloWorld\make_helloWorld

Getting Started With Windchill Customization 3-5


This script creates a Person table and a PersonPk package. You may see a
message the first time you run this script because the Person table does not yet
exist; you can ignore this message.

Note: Establish the project using the IDE of your choice.

Initialize the Object


This step overrides a default initialize() method in order to set the person’s id
attribute.
1. Edit the Person.java file to add the following code for the initialize() method
at the end of the file in the user.operations block:
protected void initialize() throws WTException
{
Date today = new Date();

super.initialize();
System.out.println("Person - initialize executing!");
String s = String.valueOf(today.toLocaleString());
setId(s);
}

2. Add the following import statement in the user imports block:


import java.util.Date;

3. From the File menu, select Save All and, from the Project menu, select
Rebuild All.

Design the GUI Layout


1. From the Project menu, select the Object tab and double click on
CreatePerson class.
2. Using the FormDesigner, add labels for Name:, Title:, Age:, and Id:. Use the
Text property of the Label to set the label value.
3. Add TextFields for the three fields you just added, plus a TextField for the
message area. The TextFields for Id and MessageArea should be set to
enabled=false and edittable=false. Name the fields nameField, titleField,
ageField, idField, and messageField. messageField should span the width of
the applet.
4. Add a button between the idField and the messageField. The button name
should be saveButton, and its label text should be Save.
5. Save all your work.

3-6 Windchill Customizer’s Guide


Code the GUI
To make the applet function, you must associate an action event with the
saveButton. The method that executes will construct a new Person object, set its
values based on the input fields, and invoke the PersistenceHelper to save it in the
database. After the object is saved, the method will update the id field on the GUI
and put a status message in the messageField.
1. Edit the source of CreatePerson.java.
2. From the form designer, click the right mouse button on the Save button and
select Bind Event. Select the actionPerformed event and press the Edit button.
3. Change the contents of the method to the following:
void saveButton_ActionPerformed(java.awt.event.ActionEvent event)
{
Person p;
int age;
try
{
age = Integer.parseInt(ageField.getText());
}
catch (NumberFormatException nfe)
{
messageField.setText("Must supply number for age");
return;
}
try
{
p = Person.newPerson();
p.setName(nameField.getText());
p.setTitle(titleField.getText());
p.setAge(age);
p = (Person) PersistenceHelper.manager.save(p);
}
catch (Exception wte)
{
wte.printStackTrace();
messageField.setText("Exception: " + wte.toString() );
return;
}
idField.setText( p.getId());
messageField.setText("HelloWorld!");
return;

4. Add the following import statements:


import wt.util.WTException;
import wt.util.WTContext;
import wt.fc.PersistenceHelper;
import java.lang.Integer;
import java.lang.NumberFormatException;

5. Insert the following statement as the first line of the init() method in the
CreatePerson.java file:

Getting Started With Windchill Customization 3-7


WTContext.init(this);

Also delete the automatically generated line:


symantec.itools.lang.Context.setApplet(this);

6. Compile the whole applet by selecting Execute from the Project menu.

Run the Applet in Mozilla or Internet Explorer


1. Create a JSP file with the following content and save it as
<Windchill>/codebase/wtcore/jsp/CreatePerson.jsp:
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/util"
prefix="util"%>
<jsp:useBean id="wtcontext" class="wt.httpgw.WTContextBean"
scope="request"/>
<jsp:setProperty name="wtcontext" property="request"
value="<%=request%>"/>
<util:locale/>
<html>
<body>
<util:plugin
code="helloWorld/CreatePerson.class"
codebase="../.."
archive="wt/security/security.jar"
width="590" height="600">
<util:params>
<util:param name="cache_option" value="Plugin"/>
<util:param name="cache_archive" value="wtApplet.jar"/>
<util:param name="wt.context.locale"
value="<%=locale%>"/>
</util:params>
</util:plugin>
</body>
</html>

Note: wtApplet.jar is used simply to get this example working. For


guidelines on managing client JARs, see Managing Client JAR Files in the
Getting Started With Windchill Customization chapter on page 5-14.

2. Ensure your web server, servlet engine, and method server are running. Refer
to the instructions given earlier in Verify The Development Environment (see
page 3-2) if they are not.
3. Open http://<hostname>/<web-app>/wtcore/jsp/CreatePerson.jsp in Mozilla
or Internet Explorer.
4. Enter the name, title, and age (where age must be a number) and press the
Save button.
5. The method server should start up automatically, if it is not already started.
You should see in the output your message about the Person initialize()
method.

3-8 Windchill Customizer’s Guide


6. In your applet, you should see the generated ID (that is, the system time) and
the message “HelloWorld” in the messageField.

Getting Started With Windchill Customization 3-9


3-10 Windchill Customizer’s Guide
4
Modeling Business Objects

This chapter explains how to model business objects.

Topic Page
Rational Rose and Windchill...............................................................................4-2
Windchill Modeling Heuristics ...........................................................................4-4
Windchill Foundation Abstractions.....................................................................4-8

4-1
Rational Rose and Windchill
The Windchill development environment uses the Rational Rose design and
analysis tool to model business objects. Rose allows you to create a graphical
representation of an application, its components, their interfaces, and their
relationships. Windchill then uses this model to generate code that is used in
server and client development.
You are assumed to be familiar with Rose or learning to use it. This section does
not describe how to use Rose, but how Windchill interacts with it.
Rose offers several kinds of diagrams (as shown in the following figure) intended
to help you analyze your model.

Rose Analysis Diagrams

On the left side are some of the various analysis diagrams available in Rose. From
top to bottom, they are: a use case diagram, a sequence diagram, and a state
transition diagram. The right side shows two class diagrams.
The class diagram is the only type of diagram used by Windchill for code
generation. Although we recommend that you use analysis diagrams, that choice
is up to you. Windchill requires only the class diagrams plus some system
specifications that you set within Rose to generate code.

4-2 Windchill Customizer’s Guide


The following figure shows a class diagram for sample business information
objects (Customer, Product, and IncidentReport) and the relationships between
them. The annotation in bold points out UML (Unified Modeling Language)
concepts and notation.

Sample Class Diagram

Address is a structured attribute class associated with the Customer class. The
composite aggregation notation indicates that Address is considered a part of the
Customer class. The Address object depends on the existence of the Customer
object. For example, if the Customer class is deleted, the Address class is also
deleted.
An association class allows you to add attributes, operations, and other features to
associations. Because customers register for products, an attributed association is
modeled between Customer and Product. IncidentReportCustomer and
IncidentReportProduct are also link classes, but they have no attributes. You need
not give them a class box.
If any of these concepts or notations are unfamiliar, you should learn more about
UML and Rose before proceeding. Many of the Windchill concepts are explained
using class diagrams.

Modeling Business Objects 4-3


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.

4-4 Windchill Customizer’s Guide


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.
Business managers are intended to implement small portions of functionality. The
knower/doer separation approach allows you to choose which business managers,
the doers, to implement for your business information, the knowers.
Windchill provides you with a number of managers (described in more detail in
the Developing Server Logic chapter on page 36-1) from which you can choose as

Modeling Business Objects 4-5


much functionality as you want, or design your own managers to meet your
specific business needs.
The following is an example of one of the managers Windchill provides, the
LockService. (In naming classes, managers are sometimes also called services.)

LockService Example

In this example, the knower is MyItem, which extends Item (a foundation class
provided by Windchill). Thus, MyItem inherits all the attributes and behavior of
Item. In addition, MyItem implements the Lockable interface.
The notation <<Interface>> is a stereotype. It is a cue to the code generator to add
an Interface modifier to your generated class. This indicates that you must provide
the code for this method in an implementation class. (In Java, an interface is a
collection of operations and final fields without implementation methods which
form an abstract type. A Java class conforms to an abstract type when it
implements an interface. When a Java class implements a Java interface, the class
or one of its subclasses must provide an implementation method for each
operation in the interface.)
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.)
StandardLockService is the actual implementation of the lock service
functionality and it implements the LockService remote interface.

4-6 Windchill Customizer’s Guide


<<RemoteInterface>> is another stereotype. It is a cue to the code generator to
create a forwarder class (described in the System Generation chapter on page
32-1). The remote interface must be available on the client.
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.
StandardLockService expects a lockable object. It can accept MyItem because
MyItem implemented the Lockable interface. Likewise, it 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.

Modeling Business Objects 4-7


Windchill Foundation Abstractions
At an infrastructure layer of Windchill’s 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 modeled
constructors are generated as factories (for example, newMyItem), along with
supporting initialization methods if none matching the same signature are found in
the classes ancestry.

4-8 Windchill Customizer’s Guide


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
Serializable, which gives an object the ability to use RMI for travel between the
client and server. Also, every abstract or concrete descendent must implement the
externalizable methods writeExternal and readExternal specified in
ObjectMappable. These methods provide custom serialization code to decompose
and recompose objects to and from a stream.
When ObjectMappable is implemented, the code generator generates a
readExternal and a writeExternal method. The writeExternal method takes the
attributes of an object and writes them into the database. The readExternal method
takes a result set from the database and turns it into attributes in an object. For an
attribute to have a column in the database, it must implement ObjectMappable.
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. It can be used as a primary key, secondary key, or a foreign key. The
WTReference interface specifies an indirect addressing mechanism in which it
persists one key that, when used in a query, results in finding an object. If none or
more than one object is found, this results in an exception. The object itself is
transient and thus not persisted.

Modeling Business Objects 4-9


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

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.

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 chapter on
page 37-1, 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.

4-10 Windchill Customizer’s Guide


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

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 4-11


4-12 Windchill Customizer’s Guide
5
Managing Customizations

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.

Topic Page
Setting Up a Directory Structure for Managing Customized Files and Text
Tailoring ..............................................................................................................5-2
Best Practices for Customizing Files Supplied by PTC ......................................5-9
Best Practices for Adding New Packages and Files..........................................5-26
Modeled To Soft Type Conversion ...................................................................5-29

5-1
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. The ability to change resource bundles requires that you install the
text tailoring option which is selected through the Custom installation type of
Windchill Services, Windchill PDMLink, Windchill ProjectLink, or
Pro/INTRALINK 9.1.

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 site-
modified (i.e., customized) files and corresponding current versions and original

5-2 Windchill Customizer’s Guide


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

Managing Customizations 5-3


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 versions 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 section on
page 5-5.
As described in the PTC Script for Working with Customized Files
section on page 5-5 there 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.
• 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.

5-4 Windchill Customizer’s Guide


– 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 the Using the Safe Area Directory Structure When Installing the
Windchill Service Pack section, later in this section (page 5-8).

Text Tailoring Directory Structure


Store your updates to PTC-supplied RBINFO files in the wtCustom directory
shown in the Directory Structure Diagram for Customized Files and Text
Tailoring section diagram on page 5-2. You can update text in RBINFO files only
if you have installed the Text Tailoring option through a custom installation of
Windchill Services, Windchill PDMLink, Windchill ProjectLink, or
Pro/INTRALINK 9.1. The details on which files can be updated and how to do the
updates are in the Changing Displayed Text Found in RBINFO Files section on
page 5-9.

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

Managing Customizations 5-5


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.

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

5-6 Windchill Customizer’s Guide


installSiteChanges. This target option is also run when you run the
swmaint.xml script with the listSiteModExclusions target option.
• make_jar.config_jars -- rebuilds all client JAR files that are based on
codebase/*.jar.config files. This covers the workgroup managers and Optegra
Gateway products as well as any new *.jar.config JAR files defined by the
site. (Client JAR files handled by jarContents and jarManifest specifications
are built separately.) See Managing Client JAR Files on page 5-14.
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

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 the Directory Structure Diagram for
Customized Files and Text Tailoring section on page 5-2.

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

Managing Customizations 5-7


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 either the Changed Files
Only or Updates for Site-Modified Files to Safe Area installation types.
Using either of these options 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 5-5 may be helpful in completing this step and later
steps.
3. Update each file 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.

5-8 Windchill Customizer’s 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 the Setting Up a Directory Structure for Managing Customized
Files and Text Tailoring on page 5-2 section 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:
• In order to change displayed text, you must have installed the Displayed Text
Tailoring capability. This is a Custom installation type of the Windchill
Services, Windchill PDMLink, Windchill ProjectLink, or Pro/INTRALINK
9.1 installers.
• 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 the Managing Client
JAR Files section on page 5-14.

Managing Customizations 5-9


• The Windchill Service Pack and temporary patch installers automatically re-
compile these resources so maintenance updates and your site changes are re-
combined.
The following sections provide additional details on text tailoring and updating
client JAR files. For general information about the enumCustomize tool, see the
The Enumerated Type Customization Utility in the Enumerated Types chapter on
page 34-11. That chapter, as well as the Internationalization and Localization
chapter on page 40-1, includes further discussions about RBINFO files.
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 5-26.

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, labels, and
messages (StringResourceInfo) 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.
• 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.

5-10 Windchill Customizer’s Guide


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 temporary 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 5-14 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 the Managing Client
JAR Files section on page 5-14.

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

Managing Customizations 5-11


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
classRegistry.properties
descendentRegistry.properties
modelRegistry.properties
moduleRegistry.properties
moduleDir.properties
debug.properties
This is because these properties are manipulated by Rose Modeling tools or
otherwise 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 5-27.

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.xconf and site.xconf files are both
manipulated by the xconfmanager Utility. See About the xconfmanager Utility in
the Windchill Utilities chapter on page 6-2 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 5-2.

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

5-12 Windchill Customizer’s Guide


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

Managing codebase/{wtcore,netmarkets,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 5-2.

Managing Windchill Info*Engine Tasks


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 the Setting Up a Directory Structure for Managing
Customized Files and Text Tailoring section on page 5-2. 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 Managers


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:
proefileadaptor.ini
newdocument.ini
proeworkspaceconfig.ini
registryclient.ini
The Workgroup Manager for CATIA V4 has the following INI files:
catiafileadaptor.ini
newcatiadocument.ini
catiaworkspaceconfig.ini

Managing Customizations 5-13


registryserver.ini
registryclient.ini
The Workgroup Manager for CADDS has the following INI files:
cadds5workspaceconfig.ini
registryclient.ini
newdocument.ini

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

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

5-14 Windchill Customizer’s Guide


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 5-18 for more information.

Overview of Client JAR Deployment Approach


To effectively manage your client JAR customizations, you need to understand
Windchill’s 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 top-
level 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.

Managing Customizations 5-15


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.

5-16 Windchill Customizer’s Guide


These logical JARs are further described in the following table.

Logical JAR Description

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

wtApplet 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. [Note that the intermediate JARs
wtPolicy, wtQB, and wtWork also serve to consolidate duplicates between themselves
and JARs above them.]

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

wtPolicy The JAR for the Policy Administrator and domain browser/selector applets.

wtQB The JAR for the QueryBuilder and Report Manager applets.

wtWork The JAR for the Workflow, Life Cycle, and Team-related Applets (Workflow
Administrator, Team Administrator, Lifecycle Administrator, Initiate Process, Process
Manager, and Setup Participants).

wtFVault The JAR for the External and Remote File Vault Administrator applets.

wtExp 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.
Note: This JAR is obsolete in release 9.0.

wtCal The Calendar applet JAR.

wtESig The electronic signature / identity applet JAR.

wtIXB The JAR to support import / export and bulk-loading applets.

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

wtTypeAdm The JAR for the Attribute Administrator, Type Manager, CSM, and Re-Use Manager
applets.

wtLogin The JAR for the login / reauthentication applet (i.e. that accessed via Login.jsp).

Managing Customizations 5-17


Logical JAR Description

ptcAnnotator, The JARs for the Product Structure Explorer (PSE) applet. There are no customizable
ptcCore or inheritable classes in these JARs.
(not shown)

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.

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
-DdoDeepBuild=true

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.

5-18 Windchill Customizer’s Guide


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

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.

Managing Customizations 5-19


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.

Note: To use the utility, you must be using the Apache 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 a browser window, access the following page:
<local_host_name>/<Web_app_name>/wtcore/jsp/wt/sysadm/HttpRequestLogUtilStart.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.

5-20 Windchill Customizer’s 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:
<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.

Managing Customizations 5-21


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

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

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=

5-22 Windchill Customizer’s Guide


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


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 5-20.
5. Update your new JAR’s contents as described in Using the HTTP Request
Log Utility on page 5-20.
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

Managing Customizations 5-23


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 only steps omitted by dsuUpdate for the Foundation resources and jars are:
– 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.
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.

5-24 Windchill Customizer’s Guide


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.

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

Managing Customizations 5-25


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.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,
XCONF files, and new files created as a result of modeling with Rational Rose.
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 new template processing
class under <Windchill>/src/com/mycompany/part, you could compile it to
<Windchill>/codebase/com/mycompany/part.
• HTML template files must be installed under
<Windchill>/codebase/templates at runtime. For example, if you create some
new templates in the directory
<Windchill>/src/com/mycompany/part/htmltmpl, you could copy them to
<Windchill>/codebase/templates/com/mycompany/part at runtime.
• 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

5-26 Windchill Customizer’s Guide


• Property files maintained in a custom directory like
<Windchill>/src/com/mycompany must be copied to a directory in
<Windchill>/codebase at runtime.
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 the Rational Rose modeling tool 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
The Customizing service.properties section (beginning on page 36-24) 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.

Managing Customizations 5-27


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

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.customPropertFiles"/>
</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.customPropertyFiles

This property is in the codebase/wt.properties file.


Store a copy of new XCONF files in your source directories as described in the
Best Practices for Adding New Packages and Files section on page 5-26.
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.

5-28 Windchill Customizer’s Guide


Modeled To Soft Type Conversion
There is a tool to help you eliminate custom modeled types from your system,
converting instances into to soft type instances on PTC-supplied modeled classes.
For instance, if you have extended WTDocument to create your own
AcmeDocument that adds a few simple attributes, it may be simpler for you, in the
long run to eliminate the need to maintain a Rose model and generate source code
by converting their AcmeDocument to a soft type based on WTDocument.

Assumptions of the Modeled To Soft Type Tool


• When converting a modeled class to a soft type, it must extend a class that
implements the Typed interface
– The class implementing Typed has to still be in the model after all classes
have been converted
• If a modeled class is converted, all of it's subclasses must also be converted
• The user has created the attribute type definitions and type definitions to
which they want to convert their modeled class instances and replaced any
custom UI and other customizations to know how to work with their type via
soft type APIs. The tool will not create the type definitions, nor will it do
anything to help eliminate customizations.
• No policies and rules of the following types can be present in the system prior
to running the tool. The tool will update their type selector columns to change
references to the modeled class to now refer to the soft type.
– AccessPolicyRule
– FvPolicyItem
– FvPolicyRule
– IndexPolicyRule
– NotificationRule
• The tool will delete records from these tables that have selectors referencing
the modeled class that's being converted to a soft type
– IndexPolicyList
– NotificationList
– PolicyAcl

Restrictions
• The tool can will only be able to preserve the following types of attributes that
have been modeled on the class(es) being converted to modeled soft types.
Any other attribute type cannot be converted and the customer will have to

Managing Customizations 5-29


decide to discard the data or change the way it is represented prior to
converting to a soft type
– boolean
– float / double
– integer / long
– String
– Date or Timestamp
• The tool will not attempt to preserve ObjectMappables in any way. Typically
an ObjectMappable class defines several attributes that should remain
together (for instance a WTReference is a class name and a numeric id). If the
customer is converting a class that used an ObjectMappable property to add
multiple columns, the customer is responsible for specifying what to do with
each distinct column.

What Happens When Converting a Class?


When a modeled class is converted to a soft type the tool does the following
things:
1. copies fields that the class has in common with it's parent, from columns on
the modeled subclass's table to the parent class's table
2. assigns the type definition fields on the new parent table rows to point at the
propert WTTypeDefinition iteration
3. for fields that were modeled on the subclass, creates soft attribute values for
each instance, associates them with the type instance in the parent class's table
(class name+id) and the attribute definition
– the customer is expected to specify the mapping for each modeled field to
each attribute definition
– the customer can opt to discard fields that aren't used or which have no
correlating representation in the soft type model
4. all "surface level" references (columns for WTReference ObjectMappables
which have a String classname column) in the database are updated to replace
references to the modeled classname that is being removed with it's parent
class name
5. all type definition based Selector columns contain external type definition
references in the database are updated to replace the modeled class name with
the external type definition string (this will update objects like access policies
and notification rules)
6. a regular expression mapping is installed in the site.xconf that will tell the
Java code-based object reference factories to convert occurrences of the

5-30 Windchill Customizer’s Guide


converted classname into the parent's class name when handling object
references found in BLOBs or outside the system (e.g. in browser bookmarks)
7. the class name is removed from the various registry properties files in the
$(wt.home)/codebase directory (e.g. classRegistry.properties,
modelRegistry.properties, associationRegistry.properties,
descendantRegistry.properties, ...)
8. the .class file for the modeled class and it's inner classes as well as the
.ClassInfo.ser file is removed from codebase as well as any jar files in
$(wt.home)/srclib, $(wt.home)/lib, $(wt.home)/codebase/WEB-INF/lib
9. the client jars downloaded by client applets are rebuilt
10. the Background Blob Rewriter process is scheduled to be restarted to find and
fix references to the removed class that may be inside BLOBBED objects
11. the customer is reminded that they have to manually remove their converted
class(es) from the Rose model and regenerate

Note: Semantic keys including the modeled class are not presently rebuilt.

The Tool
The tool is run by executing ModeledToSoftType (.sh or .bat) which can be found
in the bin directory for the Windchill installation.
ModeledToSoftType [-help] [-debug|-trace] [ [-skipdb] [-skipfs]
| -checkonly ] MappingFile.xml

-debug | -trace Will describe in more detail each action being performed.

-trace Will include much more detail such as the SQL statements being
executed.

-skipdb Don't perform any of the work that modifies the database.

-skipfs Don't perform any of the work that modifies the Windchill
installation's files.

-checkonly Equivalent to -skipdb -skipfs. Just performs validation of the


mapping file.

The tool will output to STDOUT. It will also append it's output with more details
including timestamps to a timestamped log file named ModeledToSoftType.log
in the $(wt.logs.dir) directory.

Managing Customizations 5-31


Mapping File
The mapping file is an XML file that looks like the following example:
<Mappings>
<Convert class="ext.acme.MyDoc"
softTypeLogicalIdentifier="com.acme.MySoftDoc">
<MapColumnToSoftAttribute columnQueryName="cached"
attributeDefinitionName="org.acme.DataHasBeenCached"/> <!--
boolean -->
<MapColumnToSoftAttribute columnQueryName="numberOfChanges"
attributeDefinitionName="org.acme.NumberOfChanges"/> <!--
long -->
<MapColumnToSoftAttribute columnQueryName="urlToSourceCode"
attributeDefinitionName="org.acme.SourceCodeUrlString"/><!--
String -->
<MapColumnToSoftAttribute columnQueryName="revokeDate"
attributeDefinitionName="org.acme.RevocationDate"/> <!--
Timestamp -->
</Convert>
<Convert class="ext.acme.MySignedDoc"
softTypeLogicalIdentifier="com.acme.MySoftSignedDoc">
<DiscardColumn columnQueryName="signatureImage"/> <!-- byte[]
blobbed up -->
</Convert>
</Mappings>

In this example, imagine the customer has two modeled classes that they want to
make soft types of WTDocument.
package ext.acme;

class MyDoc extends wt.doc.WTDocument {


boolean cached;
long numberOfChanges;
String urlToSourceCode;
Date revokeDate;
...
}

package ext.acme;

class MySignedDoc extends MyDoc {


Object signatureImage; // treated as an Image
...
}

The mapping file specifies that both classes are to be converted.


For the MySignedDoc class, there is no corresponding soft attribute type object
that the mapping tool supports. But let's imagine that the customer decided, for the
sake of the example, to not keep the signatures. So they simply declare that the
column should be discarded.
For the MyDoc class, they used the type and attribute administrator to defined an
attribute type for each of the four columns that were modeled on the class. For
each one they specify the column query name and the name of the attribute

5-32 Windchill Customizer’s Guide


definition. The name of the attribute definition corresponds to the logical
identifier for the attribute definition that you specify when creating the attribute
definition.

Target Soft Type


For each class being converted, a soft type definition must be specified using the
attribute softTypeLogicalIdentifier on the element Convert. As is mentioned
earlier in the assumptions, this type definition must have already been created by
the customer . The ModeledToSoftType tool does not create type definitions of
attribute definitions.
This attribute value is used to locate the latest iteration of WTTypeDefinition that
is not deleted and not in work which has the logical identifier specified. When
table data for the converted classes is copied into the table of its parent Typed
class, the typedefintitionreference will be set to this latest WTTypeDefinition
iteration.

Column Query Names


A column query name is a logical id that uniquely identifies the column but might
not actually match the generated column name. This can happen for a variety of
reasons. To figure out the query name for a column, run InfoReport on your class.
For example:
getBaseTableInfo().getColumnDescriptors() :

This will generate a text file in $(wt.temp) named something like


doc.WTDocument.out. Open it, then scroll down to the section that starts
getBaseTableInfo().getColumnDescriptors() :

Under that, you'll see information about column descriptors similar to this:
getName() : checkoutInfo.derivedFrom.key.id
getColumnName() : idA3A2checkoutInfo
getJavaType() : long
getSQLType() : java.sql.Types.BIGINT
getLength() : 0
getTableSpaceName() : null
getTableSize() : SMALL

The text to the right of getName() : is the query name. The actual columnname in
the database is on the line right below. The mapping files for the
ModeledToSoftType tool expect to see the query name, not the column
name.(Note: prior to X-12 M050, the tool used the column name to locate the
column descriptor instead of the query name).

Managing Customizations 5-33


5-34 Windchill Customizer’s Guide
6
Windchill Utilities

This chapter contains information about the xconfmanager and windchill utilities.

Topic Page
About the xconfmanager Utility..........................................................................6-2
About the windchill Command ...........................................................................6-6
About the windchill shell ....................................................................................6-8

6-1
About the xconfmanager Utility
The xconfmanager is a command-line utility that is used to add, remove, and
modify the properties in the Windchill property files. You should use the
xconfmanager (or the System Configurator) to manipulate properties; you should
not manually edit property files.
There are property files that should not be modified using the xconfmanager. The
following registry files are managed by Windchill Information Modeler and they
also should not be edited manually or using the xconfmanager:
associationRegistry.properties
classRegistry.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 those changes. The site.xconf file
contains changes made to Windchill property files, starting with installation and
continuing with each use of the xconfmanager utility or the System Configurator.
The xconfmanager utility is located in the <Windchill>/bin directory.
This chapter describes only the information and instructions necessary to modify
specific Windchill properties. A full description of the xconfmanager utility and
management of the Windchill property files is documented in the Windchill
System Administrator’s Guide in the Administering Runtime Services chapter.
Anyone with write access to the XCONF files and the property files under the
Windchill installation directory can successfully run the xconfmanager utility.
The xconfmanager is executed from the command line from within a windchill
shell. See the About the windchill Command section on page 6-6 for more
information about the windchill shell.
The syntax of xconfmanager command with only commonly used parameters is as
follows:
xconfmanager {-h} {-r <product_root>} {-s <property_pair>}
{-t <property_file>} {--add <property_pair>}
{--remove <property_pair>} {--reset <property_names>}
{--undefine <property_names>} {-d <property_names>} {-p}

For the purposes of modifying Windchill properties, you will primarily use the -s,
-t, and -p parameters as follows:
• Use the -s (--set) parameter to identify the relevant property and specify the
new property value. See the Formatting Property Value Guidelines section
(below) for information about formatting the <property_pair) value.
• Use the -t (--targetfile) parameter to specify the directory location of the
property file. If the file name or path contains spaces, you must enclose the

6-2 Windchill Customizer’s Guide


<property_file> value in double quotes (" "). It is recommended to use a fully
qualified file name to ensure an accurate reference to the file is made.
• Use the -p (--propagate) parameter to propagate the changes made to the
XCONF files into the property files being modified in order to keep the
XCONF and the property files in sync with one another.
• Use the -h (--help) parameter to view the help for xconfmanager. The help
describes all xconfmanager parameters.
Additionally, you can add and remove property values from properties that are
declared as a multi-valued properties using the following parameters:
• Use the --add parameter to add the value specified at the end of the set of
ordered values already defined in the property.
• Use the --remove parameter to remove the value specified from the set of
ordered values already defined in the property.

Tip: If you are unsure as to whether 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.

Some examples of using the xconfmanager utility are as follows:


• xconfmanager is run from the windchill shell. To open a windchill shell,
execute the following command at a command prompt:
windchill shell

• To display xconfmanager help, execute the following command from the


windchill shell:
xconfmanager -h

• To display the current settings for a property, execute the following command
from the windchill shell:
xconfmanager -d <property_names>

<property_names> is a comma-separated list of property names. This means


that you can display the current settings for multiple properties by executing
one command.
• To change a property value, execute the following command from the
windchill shell:
xconfmanager -s <property_name>=<property_value>
-t <property_file> -p

Tip: Use the fully qualified name of the property file to ensure an accurate
reference. If you are sure that there is only one property file that is known to
xconfmanager containing the property, you can omit the -t parameter. When
setting a value for a new property not in a property file, you must include the
-t parameter to name the property file to which the property is added.

Windchill Utilities 6-3


• To add a new classpath entry to the Windchill 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 will be 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.

Tip: The previous example command did not include the target file in the -t
parameter since the property is known to be in only wt.properties.

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 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
shell’s 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 interpret 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

6-4 Windchill Customizer’s Guide


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.

Windchill Utilities 6-5


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

Arguments (optional) Description

-h, --help Displays help and exits.

-v, --[no]verbose Explains what is being done when a com-


mand is executed.
Default is noverbose.

6-6 Windchill Customizer’s Guide


Arguments (optional) Description

-w, --wthome=DIR Sets the Windchill home directory.


Default is the parent directory containing
the windchill script.

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.

--java=JAVA_EXE The Java executable.


Default is the wt.java.cmd variable value
specified in the $WT_HOME/code-
base/wt.properties file.

-cp, --classpath=PATH Java classpath.


Default is the wt.java.classpath variable
value specified in the $WT_HOME/code-
base/wt.properties file.

--javaargs=JAVAARGS Java command line arguments.

Windchill Utilities 6-7


windchill Actions

Action Description

shell Sets up a Windchill environment in a new instance of the


currently running shell.

start Starts the Windchill server.

stop Stops the Windchill server.

status Retrieves the status of the Windchill server.

version Displays the Windchill installation version.

properties Displays the properties as seen by Windchill for the given re-
<resource> source with substitution and other actions executed. It can be
[,...][?key[&key2]...] limited to a given set of keys.
For example:
windchill properties wt.properties — lists all wt.properties
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 — with no arguments generates the help
report

CLASS Run a Windchill class with optional class arguments. For ex-
[CLASS_ARGS] ample:
windchill wt.load.Developer -UAOps

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.

6-8 Windchill Customizer’s Guide


7
Password Encryption

This chapter contains information about encrypting passwords.

Topic Page
Encrypted Passwords...........................................................................................7-2

7-1
Encrypted Passwords

Objective
You want to encrypt a password currently stored as plain text in a file.

Background
Prior to release 9.1 MR050, Windchill 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 the 9.1 MR050 release of Windchill, you have the option to
encrypt these passwords so the plain-text value can 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 be created 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 "Encrypting System
Passwords" section of the Windchill System Administrator’s Guide.

Scope/Applicability/Assumptions
• Assume you have code that adds a new .xconf property for Windchill use
whose value contains sensitive information. For information on adding
properties see the About the xconfmanager Utility section on page 6-2.
• Assume you have code that adds a property which is not 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:

7-2 Windchill Customizer’s Guide


<Property name="wt.pom.dbPassword" overridable="true"
targetFile="db/db.properties"

value="my_password"/>

In the underlying <wt_home>/db/db.properties file, this value appears as:


wt.pom.dbPassword=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"/>
wt.pom.dbPassword=encrypted.wt.pom.dbPassword

The encrypted values appear in the form of: “encrypted.<property_name>”.

Solution
Use the Windchill encryption mechanism to provide a secure means to store
sensitive property value information.
Indeally, properties which require encryption should be managed through the
xconfmanager. Doing so will ensure that password encryption will be handled by
a standard practice. However, there may be design considerations or architecture
issues which prevent the property from being xconf managed. Such
considerations may be that 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 Elements

Element Type Description

WTKeyStore Java Class 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.

Password Encryption 7-3


Element Type Description

WTKeyStoreUtil Java Class 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.

validProperties.list List File <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.
This file is how Windchill’s 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.

validIEProperties.list List File <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.

EncryptPasswords.xml XML File <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 targets.
These targets rely on WTKeyStoreUtil methods to encrypt
properties that are not xconf managed but still rely on securing the
property values using Windchill’s encryption mechanism.

WTKeyStoreUtilWVS Java Class 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.

Solution Context
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

7-4 Windchill Customizer’s Guide


property. If the property is not managed by .xconf files then a secondary means to
encrypt the property needs to coded.
In both situations, code needs specifically decrypt the property prior to its use
otherwise the value will likely result in errors and/or failures as the value is
encrypted.

Procedures – Encrypting/Decrypting Static.xconf Managed Single-Valued 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.

Encrypting a Property Value


This procedure 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 you’ll 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-
of-the-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>.

Note: For additional details see the "Encrypting System Passwords" section
of the Windchill System Administrator’s Guide.

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

Password Encryption 7-5


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.

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(pr
operty,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.

Procedures - Encrypting/Decrypting Dynamic .xconf Managed Single-Valued


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

7-6 Windchill Customizer’s Guide


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.

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 token to a new line below the last file entry. This tells the
encryption mechanism that this property token will be used to encrypt
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.java's implementation by extended
the
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)

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

Password Encryption 7-7


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.federation.defaultAuthorization.machine123.subnet
.net";

final String property =


"wt.federation.defaultAuthorization.machine123.subnet.net";

final String PATH = "D:\ptc\Windchill\";

String decrypted =
com.ptc.windchill.keystore.WTKeyStoreUtil.decryptProperty(property,encry
pted_value, PATH);
The string decrypted now contains the decrypted value and can be used
properly elsewhere in the code where it is relied on.

Procedures – Encrypting/Decrypting 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.

7-8 Windchill Customizer’s 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(pr
operty,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
second 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 API: public WTKeyStore (final String product_root)

Parameter Default Value Possible Values Req? Description

product_root None String Yes A String that is the fully qualified


path to the home location, either
<wt_home> or <adapater_home>

Password Encryption 7-9


WTKeyStore.java API: public String get(final String key)

Parameter Default Value Possible Values Req? Description

key None String Yes A String that is the key used to


retrieve a value from the Java
keystore

WTKeyStore.java API: public put(final String key, final String value)

Parameter Default Value Possible Values Req? Description

key None String Yes A String that is the key used to


retrieve a value from the Java
keystore

value None String Yes A String that is the value to place in


the Java keystore

WTKeyStore.java API: public String remove(final String key)

Parameter Default Value Possible Values Req? Description

key None String Yes A String that is the key for a value
to remove from the Java keystore

WTKeyStoreUtil.java API: public static String decryptProperty(final String


property_value, final String product_root)

Parameter Default Value Possible Values Req? Description

property_value None String Yes A String that is a value which may


need decryption

product_root None String Yes A String that is the fully qualified


path to the home location, either
<wt_home> or <adapater_home>

WTKeyStoreUtil.java API: public static String decryptProperty(final String


property_name, final String property_value, final String product_root)

Parameter Default Value Possible Values Req? Description

property_name None String Yes A String that is a property name

property_value None String Yes A String that is a value which may


need decryption

product_root None String Yes A String that is the fully qualified


path to the home location, either
<wt_home> or <adapater_home>

7-10 Windchill Customizer’s Guide


WTKeyStoreUtil.java API: private static String
getEncryptionPropertiesRegExList(final String product_root)

Parameter Default Value Possible Values Req? Description

product_root None String Yes A String that is the fully qualified


path to the home location, either
<wt_home> or <adapater_home>

EncryptPasswords.xml API: run Ant –f EncryptPasswords.xml –projecthelp to


see the full list of available commands and usage.

Parameter Default Value Possible Values Req? Description

wt.home env.WT_HOME String No A String that is the fully qualified


path to the home location, either
env.wt_home
<wt_home> or <adapater_home>.
../../../.

The value
defaults to
environment
variable
WT_HOME,
then wt_home,
and finally the
canonical path
../../../.

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.

Sample Code

Creating a Java keystore for Windchill to encrypt values


try
{
WTKeyStore keyStore = new
WTKeyStore(WTProperties.getLocalProperties().getProperty("wt.ho
me"));

}catch(IOException e){

Password Encryption 7-11


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

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

Additional method to decrypt a value


String value = “encrypted.wt.pom.dbPassword”;
try
{
WTKeyStore keyStore = new
WTKeyStore(WTProperties.getLocalProperties().getProperty("wt.ho
me"));

// decrypt encrypted values


String ks_value = keyStore.get(value);
if(ks_value != null)
{
value = ks_value;
}

7-12 Windchill Customizer’s Guide


}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. For more
information, see Procedures - Encrypting/Decrypting Dynamic .xconf Managed
Single-Valued Properties on page 7-6.

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 - This Java class
implements a means to encrypt properties that are not .xconf file managed
properties.

Password Encryption 7-13


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

Additional Resources

Related Package/Class Javadoc


• The com.ptc.windchill.keystore.* -package contains encryption and
decryption APIs and accompanying Javadoc.

Other Related Windchill Documentation


• Windchill System Administrator’s Guide - "Encrypting System Passwords"
section

7-14 Windchill Customizer’s Guide


8
Customization Tutorial

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

Topic Page
Tutorial Overview ...............................................................................................8-2
Create Administrator and User............................................................................8-4
Create a Library and Document ........................................................................8-12
Create a New Attribute Definition and Add it to the Document Type..............8-17
As the End User, Create a Document with the new Attribute...........................8-22
Create a Document Soft Type ...........................................................................8-25
Create an Instance of the New Document Soft Type ........................................8-27
Model a New Document Subclass.....................................................................8-28
Create an Instance of the New Document Subclass ..........................................8-38
Verify the Customizations.................................................................................8-39
Summary ...........................................................................................................8-41

8-1
Tutorial Overview
This tutorial illustrates a minimal configuration to create an environment in which
you can create administrative objects (users, 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
Performing these tasks will:
• confirm that their development environment is properly configured
• shows that UIs adapt to new type and attribute definitions

Assumptions
• Windchill PDMLink standalone or Integral Windchill PDMLink and
Windchill ProjectLink.
• 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. As the Organization Administrator create a soft attribute definition and add it
to the standard document type.
4. As the end user, create a document instance which will include the new
attribute.

8-2 Windchill Customizer’s Guide


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

Customization Tutorial 8-3


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

2. From the first level navigation tabs, select Site.


3. From the second level navigation tabs, select Utilities.
4. Under Business Administration select Principal Administrator.
5. Select New User.

6. Create an Organization Administrator with the following values:


– User Name (login ID)
– Full Name
– E-mail Address

8-4 Windchill Customizer’s Guide


– Password

– Organization

Customization Tutorial 8-5


Click Search to search for the organization. Choose the default
Organization created for your system (this was specified when the system
was installed).

7. Select the Groups tab.


8. Select the black ‘+’ icon to add groups to the table.
9. In the Search for Parent Groups dialog select Search (leave the search field
blank), and then select the three check boxes for Administrators, Attribute
Administrators and Type Administrators, then select OK.

Note: For any other organization you would not need to select
Administrators. But because this is the default site organization, the

8-6 Windchill Customizer’s Guide


organization administrator must also be a site administrator in order to
manage types and attributes.

10. Select OK.

11. Select New User.

Customization Tutorial 8-7


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

8-8 Windchill Customizer’s Guide


13. Close the principal admin window.

14. Now you must declare the Organization Administrator user as an


Organization Administrator. Select the Organization tab from the first level
navigation tabs.

15. Select your organization from the Organizations drop down list on the
second level navigation. If there is a table of displayed organizations, it may
also be there.
16. Select the Administrators tab from second level navigation tabs.
17. Select the Add Users… icon.

Customization Tutorial 8-9


18. In the Add Organization Administrators dialog select Find Users, leaving
the Search field blank. Select the user you created to be the Organization
Administrator, and then select Add >> and OK.

19. With the Organization tab still selected, select the Creators sub tab. In the
Current View dropdown select Library Creators.

8-10 Windchill Customizer’s Guide


20. Select your end user and add them to the Library Creators Group using the
Add >> button.

Verify that your end user is now part of the Library Creators group.

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 8-11


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) by navigating to the
Home:Overview page. There you will see the user name displayed.

3. As the End User, create a new Library. Select the Library tab and select the
New Library icon.

8-12 Windchill Customizer’s Guide


4. Create a new library.

5. The complete library details display.

Customization Tutorial 8-13


6. Select the Folders subtab and then the Add a New Document… icon.

7. In the Type drop down select Document. Click Next.

8-14 Windchill Customizer’s Guide


8. Set the document attributes.

9. Select Finish. You will not be setting attachments during this process.

Customization Tutorial 8-15


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.

8-16 Windchill Customizer’s Guide


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 Manager, select Organization > Utilities >
Type and Attribute Manager.

Customization Tutorial 8-17


4. Select Attribute Definition Manager > New Organizer to create a new
Attribute Organizer.

5. Specify a name for your new Attribute Organizer, and select OK.

6. Select Save.
7. Select the New Attribute icon.

8-18 Windchill Customizer’s Guide


8. Specify a new Integer attribute called “sizeA”.

9. Select OK and your new attribute will be displayed in the attribute hierarchy:
10. Before Saving, change the Display Name of the attribute to “Size A”. Note
that the display name can be localized in resource bundles.

Customization Tutorial 8-19


11. Select the Type Manager tab, and expand the hierarchy under Document to
see its subtypes.

12. With Document selected, select the Edit icon. Then select the Template tab.
Within the Template tab, select Attribute Root to enable the Add
Attributes button.

13. Select Add Attribute and from the dialog find and select the sizeA attribute
you created. In the Template tab, select the value cell for sizeA and enter the
default value of 1.
14. Select Save and then select the Check In icon.

8-20 Windchill Customizer’s Guide


15. You have just added the sizeA attribute to the Document type and all of its
subtypes.

16. Close the Type and Attribute Manager window.

Customization Tutorial 8-21


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:

8-22 Windchill Customizer’s Guide


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

Customization Tutorial 8-23


3. Select More Attributes to see the soft attribute and value that you added.

4. 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, it only applies to instances created after the attribute
existed on the type.

8-24 Windchill Customizer’s 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 Organizations > Utilities > Type and Attribute Manager.
3. In the Type and Attribute Manager window, select Document and then the
“New” icon.
4. Specify the new document type.

5. Select the Attribute Definition Manager tab, and create another Integer
attribute type as a peer to sizeA called “sizeB”. Save it.

6. Add attribute sizeB to your new document type with default value “2”.

Customization Tutorial 8-25


7. Your document type now has two attributes:

8. Select the General tab. With the type checked out, select the edit icon and
change the Icon to “wtcore/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.
9. Save and check in your type.

8-26 Windchill Customizer’s Guide


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.
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 - the repair_failure.gif file that
you selected in the previous step).

Customization Tutorial 8-27


Model a New Document Subclass
Now you will start Rational Rose (Information Modeler) and create a document
subclass with a new integer attribute.
1. From the Windows Start menu open a Windchill Shell and execute "start
rose":

2. Within Rose you will first be presented with a Create New Model dialog.
Cancel that dialog for now.
3. Select File > Edit Path Map… and verify that the path map values are
referencing your Windchill installation.
4. Close the Path Map window.
5. Select File > Open, and navigate to, and open the model file:
…\Windchill\src\wt\WTdesigner.mdl

6. When prompted to Load subunits… select Yes.

8-28 Windchill Customizer’s Guide


7. Wait until the load is complete, at which point the screen will update and look
something like this:

8. In the browser pane, expand the Logical View. Right click Logical View and
select New > Class Diagram. Name the new diagram "com Packages".
Double click on the "com Packages" icon to open the empty diagram.

Customization Tutorial 8-29


9. Select the Package icon then click in the diagram pane. Name the new
package "com":

10. Right click the "com" package in the browser and select New > Package.
Name the new package "acme".
11. Right click the "acme" package in the browser and select New-> Class
Diagram. Name the new diagram "Documents".
12. Double click the Documents diagram icon to open the new empty diagram.
13. Select the Class icon and click in the diagram window. Name the new class
"WTDocument" (it must be this name, as it refers to an existing Windchill
class that you will inherit from). When prompted to "Delete NewClass from
the Model?" select "Yes".

8-30 Windchill Customizer’s Guide


14. Select the Class icon again and click in the diagram window below
WTDocument. Name the new class "AcmeModeledDoc". Select the
Generalization icon and draw an arrow from "AcmeModeledDoc" to
"WTDocument".

15. Double-click "AcmeModeledDoc" in the Class Diagram to open the


Specification Dialog. Select the Attributes tab.

Customization Tutorial 8-31


All of the existing attributes are inherited from WTDocument and its parent
classes. Right click on the list of attributes and select "Insert". Name the new
attribute "sizeC".

16. Double-click on the new attribute to open the Class Attribute Specification
window.
17. Set the following values:
– Type = Integer
– Initial Value = 3

8-32 Windchill Customizer’s Guide


– Export Control = Public

18. Select OK to close the Class Attribute window.


19. Now open the Windchill tab within the Class Specification window. Change
the StandardIcon to "wtcore/images/stop.gif".

Customization Tutorial 8-33


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.

20. Select OK to close the Class Specification window.

21. Now you will generate the Java source file, SQL scripts and other artifacts for
your new document class.

8-34 Windchill Customizer’s Guide


22. Select AcmeModeledDoc in the class diagram. Select Tools > Windchill >
System Generation.
Accept the default selections, select OK.

23. After a minute or so the generation will be complete.


– You will find the generated java file here:
..Windchill\src\com\acme\AcmeModeledDoc.java

– You will find the generated SQL file (to create the new database table)
here:
..Windchill\db\sql\com\acme\create_AcmeModeledDoc_Table.sql

– You will find the generated ClassInfo.ser file (that contains meta data
about the new class) here:
..\Windchill\codebase\com\acme\AcmeModeledDoc.ClassInfo.ser

24. You can inspect the java and sql files to see what was generated (the
ClassInfo.ser file is a binary instance of the ClassInfo java class, so you
cannot inspect it directly).
25. Now you will compile the java file.
26. Open a Windchill Shell. CD to the directory (<Windchill>/src/com/acme) of
the java source file.
27. Compile the java file.

Customization Tutorial 8-35


javac -d <Windchill>\codebase AcmeModeledDoc.java

You'll find the compiled class file in the same directory as the ClassInfo.ser
file.
28. 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

..\Windchill\db\sql\com\Make_pkg_com_Index.sql

29. From the Windchill Shell, login to sqlplus.


sqlplus <db_user>/<db_user_pw>@<sid>

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

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

32. Now restart the method server

8-36 Windchill Customizer’s Guide


33. As the Organization Administrator, open the Type and Attribute Manager.
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.

Customization Tutorial 8-37


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 More Attributes page for Document 103 and note that the
sizeA and sizeC attributes have the correct values.
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

8-38 Windchill Customizer’s Guide


Verify the Customizations
To verify what you have done, search for instances of your documents.
1. Now click "Search:" in the top right corner of the browser.
2. The Search Page opens. In the "Name" field enter "Document 1*":

3. Now select "Search" button in the bottom right. Four results will be displayed:
the four documents you created.

Customization Tutorial 8-39


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.

8-40 Windchill Customizer’s Guide


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 Rose
• Verified what you have done, by searching for instances of your documents.

Customization Tutorial 8-41


8-42 Windchill Customizer’s Guide
III
User Interface Customization
Section

Chapter Page
User Interface Technology Overview .................................................... 9-1
Generic UI Customizations.................................................................. 10-1
Customizing HTML Clients Using the Windchill JSP Framework..... 11-1
Adding Actions and Hooking Them Up in the UI ............................... 12-1
Gathering the Data for the UI .............................................................. 13-1
Presenting Information in the UI ......................................................... 14-1
Constructing Wizards........................................................................... 15-1
Information Pages ................................................................................ 16-1
Incorporating Pickers in JSP Clients.................................................... 17-1
JSP Customization Scenarios............................................................... 18-1
Customizing the Product Structure Explorer (PSE)............................. 19-1
Customizing Windchill MPMLink ...................................................... 20-1
Customizing Search Functionality ....................................................... 21-1
9
User Interface Technology
Overview

This chapter explains and give 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).

Topic Page
Windchill Client Architecture Overview ............................................................9-2
Adding Custom Code to all Windchill Client Architecture Pages......................9-8
Javascript Functions Overview ...........................................................................9-9

9-1
Windchill Client Architecture Overview
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 framework is largely a jsp-based system and is composed of these items:
• JSP Pages/Fragments
• Java Beans
• Custom Tags/Taglibs
• Java Services
• JavaScript functions and 3rd party javascript libraries
• Reusable Components
The internal code to the jsp will contain the necessary data to describe and
configure the sub-components that are used.

Basic Elements of a JSP page


You will need to be aware of a few important jsp fragment files.

begin.jspf
The first and most important is the begin.jspf. This files exists in
codebase/netmarkets/jsp/util/. This file is included in most view jsp pages. The
purpose of this jspf is to:
• Include a tag for rendering the header, and 1st and 2nd level navigation.

• Take care of housekeeping like:


– instantiation of beans (context, clipboard, session)
– including standard .js and .css files
– including common HTML pieces like <html>…<body>…etc)
– creating an HTML form for submitting data (called mainform)
– providing support for closing pop ups and refreshing the main page

9-2 Windchill Customizer’s Guide


end.jspf
Another jspf that is included on most pages 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 (for
example, switching the 3rd level navigation content without refreshing the
page
• display the footer

• catch exceptions and handles them if they occur within the page

beginWizard.jspf
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, however, it will not include the
rendering of the header for the 1st and 2nd level navigation.

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 NmObject Utilities in the Gathering the Data for the UI chapter on page 12-15
for more information.

Custom Tags and TagLibs


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.
Refer to the taglib javadoc at the following location:
http://www.ptc.com/view?im_dbkey=77892

Java Services

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

User Interface Technology Overview 9-3


directly. See the Adding Actions and Hooking Them Up in the UI chapter the
page 11-1 for more information.

Validation Service
Validation of actions, properties, and wizard steps 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, properties, or wizard steps
should be displayed, disabled, or hidden. The service will invoke the appropriate
delegates to gather the requested status for that action, property, or wizard step.
As a customization point, you can write a delegate that is mapped to a specific
action, property, or wizard step, 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 soft
attributes created via the type manager, not modeled attributes. That validation
service will actually call the role based service as a first pass of validation. If the
action, property, or wizard step is valid for the user based on role, the service will
then invoke the appropriate delegate.
The Validation Service is also used to validate the data entered by the user in
wizards.
• For more information on the Role Based UI framework see Customizing
Role-Based UI Functions - Attribute Visibility on page 9-8.
• For more information on the Validation Service see Adding Validation Logic
for Actions and Properties on page 10-46.

Javascript Functions and 3rd Party Javascript Libraries


Also installed with Windchill are 3rd party javascript libraries including
Prototype, script.aculo.us, and Dojo libraries.

Reusable Components
There is a broad set of components that are built using the framework that can be
reused in customizing your pages.
The basic steps to render many components (table, tree, property panel, etc.) are:
• Describe the component (describe* tags)
• Acquire the necessary data (get* tags)
• Render the component (render* tags)

9-4 Windchill Customizer’s Guide


The configuration of these phases begins with the tag handler 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"%>

This section will gloss over what the details of most of the columns and properties
in the tags mean for now, and focus on the overall flow of the page.

Component Description
This part of the lifecycle is used to define the columns/properties that the
component will display. This happens first 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 do
display. The core 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>

Variations on the describeTable tag are the describePropertyPanel tag, which


presents object attributes in label-value rows, and the describeAttributesTable tag,
which also presents attributes in label-value rows but in tabular format.

Structure of the tag


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 aren’t exposed as attributes of the parent tag itself. This gives the
infrastructure and the developer some flexibility about the metadata they’d
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.

User Interface Technology Overview 9-5


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

Data Acquisition
The second phase gets the model data based on the description from the first
phase. 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. The developer does this with one of client
infrastructures “get” tags. The most typical usage of the tag 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>

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 do not interact with the ComponentModel object produced
by the get tags. Instead, the developer provides information on some lower-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.

9-6 Windchill Customizer’s Guide


Server processing: data utilities
The construction of a ComponentModel doesn't happen in the servlet container,
but instead in the method server. During the execution of the get tags, the flow of
execution leaves the servlet container and jumps over to the method server. On the
method server, the client infrastructure runs through several phases to create the
ComponentModel. The step of most interest to developers is the invocation of
Data Utilities, which are delegates that allow developers to post-process and/or
augment the data returned by the low-level data acquisition API.

Rendering
This phase produces HTML and JavaScript based on the model data. Rendering is
usually the simplest phase for the developer to set up. The client infrastructure
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}"/>

What is it doing?
In this case, the table renderer is taking an input ComponentModel assigned to the
scoped variable "tableModel", and rendering it as a table.

User Interface Technology Overview 9-7


Adding Custom Code to all Windchill Client Architecture
Pages
This section explains how to add custom code to all Windchill Client Architecture
pages.

Javascript and CSS files


To add any custom javascript, or css scripts to all the pages, modify the
codebase/netmarkets/jsp/util/begin_custom.jspf to add the necessary html to get
the js or css files included.

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.
The message will appear at the top of the page before the Windchill header is
displayed.

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

9-8 Windchill Customizer’s Guide


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 Purpose

getTableRows (parentNode) Return array of Nmcontexts for each


row in a table given the outer DIV
DOM node.

getTableRowsByID (tableID Return array of Nmcontexts for each


row in a table given a table id

getTreeRows (parentNode) Return array of Nmcontexts for each


row in a table given the outer DIV
DOM node.

findTableID (node) Given some DOM Element, walk up


the DOM tree to figure out which table
this is in.

findParentTableNodeId (node) Given some DOM Element, walk up


the DOM tree to find the table DOM
Node.

getAddedRows (tableid) Gets the hidden input field that


contains the added rows of a table id.
Returns String that can be tokenized.

getRemovedRows (tableid) Gets the hidden input field that


contains the removed rows of a table
id. Returns String that can be
tokenized

getParentTR (node) Walk up the Dom tree finding the first


<tr> tag

removeParentRow (oid, node, tableid) Remove a row from a table/tree

isTableCheckBox (node) returns true/false if the dom NODE is


a row in the table with the class
JCA_tablerow
@param node - checkbox dom node

User Interface Technology Overview 9-9


Name Purpose

deSelectOtherTableRows (table id) Invoked when a checkbox is clicked


and it changes the row css so that it
appears as highlighted.

getFormNodes (node) Get all the form nodes within the given
parent node. If parentNode is
unspecified, the entire document is
searched.

disableRow (tr) Disable all form inputs in the given


row

updateHeader (tableid) Updates row Count in Title bar.

getUnformattedTableId (tableid) turns the outer div node id into a


normal table id defined by the jsp tags
table__jca.sometable__TABLE ->
jca.sometable

getFormattedTableId (id) turns a div table id into the simple


table id used as in the jsp tags
table__jca.sometable__TABLE ->
jca.sometable

updateFooterCount (tableid, count, Updates Count of selected rows in


changeValue) footer.

disableSelectAllChBox Disables the select all checbox given a


table id

enableSelectAllChBox enables the select all checbox given a


table id

TreeHandler
Name Purpose

toggle (…) 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.

9-10 Windchill Customizer’s Guide


Name Purpose

collapseFolders (oid, action, list) 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

asyncResponseHandler
Name Purpose

handleResponse (responseText, Parses actions from an asynchronous


responseObject) response. Generic high level method
that will delegate to all the types of
responses.

stripText (text, Gets rid of unwanted text from the


response. Substrings out antying not
divID,
inbetween the html comment.
skipScriptEval,
Can execute javascript blocks
start, conditionally.
end) Start/end are the html comment strings
to use to find the response in.

rowHandler
Name Purpose

addRows (oidList, Add rows to a table.


table_id, oidList is an array of oids to add as
rows.
tableRows,
Tablerows is an array of all current
params)
rows to improve performance of the
api
Params is extra params to add to the
ajax request.

removeRowsFromParentTable

User Interface Technology Overview 9-11


Name Purpose

removeRows ( rows, table_id, Remove rows from the table, rows is


visually_remove ) an array of oids.

requestHandler
Name Purpose

handleRequest (table_id, params) Refreshes a table given the params

doRequest (url, options) 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 Purpose

getElementsByClassNameAndTag Returns all the children of the


(className, parentElement , tag parentElement that match the given
name) 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, Similar to Prototype’s updater,


doAsynch, url) performs an Ajax call (appears to
ignore divID).

addRows( list, tableId, refresh, Modifies the hidden form fields of


doAjaxUpdate, preventDuplicates ) tables 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 Refreshes the parent window.


refreshOpenerOnly()

getClipboardItems() Family of methods for getting contents


of the Clipboard as a comma delimited
list.

9-12 Windchill Customizer’s Guide


Wizard.js functions
Name Purpose

handleRequest (table_id, Refreshes a table given the params


params)

doRequest (url, options) Make the ajax request for the table.
Used by the above method to change
the url with the options set.

parseAnonymousParams (startIndex, Add request params to the options


params, result) based on the params list passed in.

getParamString Adds all this form params to the ajax


request including the params passed
in.

updateStepImage Updates the wizard step indicator


images for all steps based on the
current state.

updateEmbeddedText Updates the embedded help based on


the current step.

getNextStep Gets the next step id.

setNextStepDirty Sets the next step in the wizard to be


refreshed when displayed.

goBack Make the wizard go back one step

goNext Make the wizard go to the next step

setActiveStep (stepId, wizardAction) 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.

findStepIndex Find the index of a step id

setNextStep Override what the next step id is

setStepDirty Set a step to need a refresh should it


display again

setStepClean Set a step to NOT need a refresh


should it display again

User Interface Technology Overview 9-13


Name Purpose

setStepIncomplete Set a step to need to be vistited again


as it needs more info

setStepComplete Set a step to NOT need to be vistited


again as it does not needs more info

setStepRequired Make a user visit a step before the


wizard can be completed

setStepOptional Make a user able to complete the


wizard WITHOUT visiting the
specified step id

removeStep Remove a step from the list of steps

insertStep Add a new step to the list of steps


based on what has already happened -
dynamic steps

resetOkButton Sets the ok button to be displayed or


not based on the current state.

resetNextBackButton Sets the next/back button to be


displayed or not based on the current
state.

disableOkButton Force the finish and apply buttons to


be disabled

enableOkButton Force the finish and apply buttons to


be enabled

getCurrentStep Gets the current active step id

refreshCurrentStep Refreshes the current wizard step

refreshStep Refreshes the speicified wizard step

getAbsoluteUrl This function takes a url and turns it


into an absolute URL.

goProgress Turns on the progress indicator

stopProgress Turns off the progress indicator

onSubmitMain Finish the wizard by executing it on


the server

9-14 Windchill Customizer’s Guide


Name Purpose

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

onClickValidation (evt, key) To do Ajax validation when an action


is clicked.
The event object.
The key to use in validation code

checkRequired (skipErrorMsg) 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

User Interface Technology Overview 9-15


9-16 Windchill Customizer’s Guide
10
Generic UI Customizations

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

Topic Page
Handling Icons for Business Objects ................................................................10-2
Customizing the Handling of Soft Attributes....................................................10-3
Customizing Role-Based UI Functions - Attribute Visibility ...........................10-5
Customizing Role-Based UI Functions - Action Visibility.............................10-14
Preferences ......................................................................................................10-15
Constructing URLs..........................................................................................10-21
Offline Package Customization.......................................................................10-24
System Banner Alert Message ........................................................................10-29

10-1
Handling Icons for Business Objects

Modeled Business Objects


The icons for a class are modeled into Rose. For the modeled class, select the
WT_UI tab and set the StandardIcon and OpenIcon accordingly.

These paths must be fully qualified from the Windchill codebase. The location for
all .gif images at this time is wt/clients/image.
The gif image specified must be 16 by 16 pixels.
Class inheritance determines what glyphs are overlaid on an object:
• Subclasses of wt.doc.Document are displayed based on their primary format
and will also inherit the overlays of RevisionControlled.
wt.clients.util.IconCache is the class that clients use to access icons. An example
of its usage follows:
IconCache icons = new IconCache( someWTContextObj );
Image img = icons.getStandardIcon( someWTObject );
Image img2 = icons.getOpenIcon( someWTObject );

Any subclass of wt.fc.WTObject is accepted as an argument. See this class entry


in your installed Windchill Javadoc for more information.

10-2 Windchill Customizer’s Guide


Customizing the Handling of Soft Attributes
Windchill PDMLink and Windchill ProjectLink provide a means to customize the
way soft attributes are displayed and processed in HTML Create and Update
clients. By editing a XML file you may do the following:
1. Turn off display of the Use Default button. (This also affects the Product
Structure Explorer.)
2. Specify whether a string soft attribute should be displayed as a single-line or
multi-line input field. This directive overrides the
StringLengthThresholdForMultilineInput preference.
The path of the XML file is:
WT_HOME/codebase/config/logicrepository/xml/AllClients.xml. The file is
described by the following DTDs:
• <Windchill>/codebase/config/dtd/LogicRepository.dtd
• <Windchill>/codebase/config/dtd/AllClients.dtd

Format of AllClients.xml
The format of elements in AllClients.xml is as follows:
<LogicRepository>
<ElementGroup>
<LogicContext dataType="<object type>"/>
<ObjectAttributes id="ObjectAttributes">
<AttributeEditField
id="IBA|<attribute logical form name>"
showDefaultValue="true|false"
inputFieldType="singleLine|multiLine"/>
...
</ObjectAttributes>
</ElementGroup>
...
</LogicRepository>

Multiple ElementGroup tags may be included in AllClients.xml. All


ElementGroup tags must be placed between the beginning and ending
LogicRepository tags in this file. Each ElementGroup tag includes a
LogicContext tag and an ObjectAttributes tag.
The LogicContext tag indicates the object type of an ElementGroup. The
behavior of all the attributes included in the ElementGroup applies to this object
type. The dataType attribute of the LogicContext tag may refer to a soft type or a
modeled type. To refer to a soft type use the hierarchical path name for the type,
with each element separated by a '|' character. For example, to configure attributes
for the soft type "com.MyCompany.www.MyPart" that is derived from WTPart
you would specify:
<LogicContext dataType="wt.part.WTPart|com.MyCompany.www.MyPart"/>

Generic UI Customizations 10-3


To refer to a soft type "com.MyCompany.www.ABCPart" that is derived from
"MyPart" you might specify:
<LogicContext
dataType="wt.part.WTPart|com.MyCompany.www.MyPart|com.MyCompany.www.ABCPart"/>

An example reference for a custom modeled subclass of WTPart called


ext.part.MyModeledPart is:
<LogicContext dataType="ext.part.MyModeledPart"/>

Note: The LogicContext tag, as defined by LogicRepository.dtd, also includes an


optional application attribute. The application attribute is not used for elements in
AllClients.xml.

The ObjectAttributes tag may include multiple AttributeEditField tags. Include


an AttributeEditField tag for each attribute you wish to configure. These tags are
described in <Windchill>/codebase/config/dtd/AllClients.dtd. In the id attribute
of the AttributeEditField element, modeled attributes are identified by the prefix
"MBA" and soft attributes by the prefix "IBA". An AttributeEditField tag may
include either a showDefaultValue attribute or an inputFieldType attribute or
both. The inputFieldType attribute will be ignored if the attribute is not a string.
If no AttributeEditField tag is provided for an attribute its presentation is as
follows:
1. Use Default Button - Will be presented if the attribute has a default or initial
value, is editable, and has not yet been set in the database.
2. Input Field Type - Will be determined according to the value of the
StringLengthThresholdForMultilineInput preference.

Example
An example ElementGroup to configure three soft attributes for the modeled base
type wt.part.WTPart is as follows:
<ElementGroup>
<LogicContext dataType="wt.part.WTPart"/>
<ObjectAttributes id="ObjectAttributes">
<AttributeEditField id="IBA|MyBooleanAttribute" showDefaultValue="false" />
<AttributeEditField id="IBA|MyStringAttribute"
showDefaultValue="false"
inputFieldType="singleLine"/>
<AttributeEditField id="IBA|MyStringAttribute2" inputFieldType="multiLine"/>
</ObjectAttributes>
</ElementGroup>

10-4 Windchill Customizer’s Guide


Customizing 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 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 the Windchill Business Administrator’s Guide for more details about profile
and role-based visibility administration.

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

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:

Generic UI Customizations 10-5


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

10-6 Windchill Customizer’s Guide


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

Generic UI Customizations 10-7


• 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 Type Description

*actionModels.xml XML 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
<Windchill>/codebase; other *actionmodels.xml files are
generally in <Windchill>/codebase/config/actions

*actions.xml XML 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.

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

10-8 Windchill Customizer’s Guide


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 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” guestEnabled=”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:

Generic UI Customizations 10-9


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

uic Element
Each UIC in roleaccessprefs.xml represents a UIComponent or action to be
controlled.

Possible
Parameter Default Value Values Req? Description

name n/a string Y 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.

order n/a Integer N The position of this UI component in the


wizard. UI components with lower
numbers are placed before those with
higher numbers.

10-10 Windchill Customizer’s Guide


Possible
Parameter Default Value Values Req? Description

enabled true true | false N Whether or not this uicomponent will be


shown in the wizard and utilized by the
system.

defaultAll true true | false N The default visibility value for All
Members.

defaultManager true true | false N The default visibility value for Project
Managers.
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.

defaultGuest true true | false N 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.

managerEnabled true true | false N 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.

guestEnabled true true | false N 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.

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

Generic UI Customizations 10-11


<uic name=”CUSTOMIZED_TAB” order=”190” enabled=”true”
defaultAll=”true”/>

2. Associate the appropriate actions in actions.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 Customized Tab

40.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 the Procedure – Making an Action Available
to Visibility Administration section on page 10-9 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.

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 Folders – My New Label

31.constant=PROJECT_CREATE_FOLDERS

10-12 Windchill Customizer’s Guide


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


• Windchill Customizer’s Guide – Managing Customizations

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 10-13


Customizing Role-Based UI Functions - Action Visibility
Role-based action visibility in Windchill is implemented only in JSP pages. See
the Customizing Role-based Visibility section in the Adding Actions and Hooking
Them Up in the UI chapter on page 12-28 for more information.

10-14 Windchill Customizer’s Guide


Preferences
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

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

Generic UI Customizations 10-15


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 don’t 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" );

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

10-16 Windchill Customizer’s Guide


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

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 Manager UI.
– Display name: This is the Name column in the Preference Manager UI –
string in the form <RBINFO>:< RBINFO key>

Generic UI Customizations 10-17


– Description: This is the Description column in the Preference Manager UI
– 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 handler
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/mycompany/MyNewPreference
MyNewPreference.description.value=Description of preference
/com/mycompany/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">

10-18 Windchill Customizer’s Guide


<NmLoader>

<csvPreferenceCategory
handler="wt.preference.LoadPreference.createPreferenceCategory"
>
<csvname>CUSTOM_PREFERENCE_CATEGORY</csvname>
<csvparentName></csvparentName>
<csvdisplayName>
com.mycompany.pref.mycompanyPreferenceResource:MyNewPreferenceC
ategory.displayName
</csvdisplayName>
<csvdescription>
com.mycompany.pref.mycompanyPreferenceResource:MyNewPreferenceC
ategory.description
</csvdescription>
</csvPreferenceCategory>

<csvPreferenceDefinition
handler="wt.preference.LoadPreference.createPreferenceDefinitio
n">
<csvname>/com/mycompany/MyNewPreference</csvname>
<csvvisibility>USER</csvvisibility>

<csvcategoryName>CUSTOM_PREFERENCE_CATEGORY</csvcategoryName>

<csvdisplayName>com.mycompany.pref.mycompanyPreferenceResource:
MyNewPreference.displayName</csvdisplayName>

<csvdescription>com.mycompany.pref.mycompanyPreferenceResource:
MyNewPreference.description</csvdescription>

<csvlongDescription>com.mycompany.pref.mycompanyPreferenceResou
rce:MyNewPreference.longDescription</csvlongDescription>
<csvdefaultValue>Default Value</csvdefaultValue>

<csvhandler>com.ptc.windchill.enterprise.preference.handler.Str
ingPreferenceValueHandler:4000</csvhandler>
</csvPreferenceDefinition>

<csvLinkPreferenceClientDefinition
handler="wt.preference.LoadPreference.setClientDefinitionLink">
<csvname>/com/mycompany/MyNewPreference</csvname>
<csvclientName>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

Generic UI Customizations 10-19


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 10-17, 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.deletePreferenceDefinitio
n">
<csvname>/com/mycompany/MyNewPreference</csvname>
</csvDeletePreferenceDefinition>

</NmLoader>

2. Delete the preference definition using the following command:


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

10-20 Windchill Customizer’s Guide


Constructing URLs

The URLFactory
The URLFactory is a utility class provided to generate relative HREFs and
support the Windchill Single-Point-Of-Contact (SPOC) environment. The
URLFactory has been designed to take in a web-resource at a particular state in
the Windchill system (from a certain request, host etc.) and generate an
appropriate String HREF or URL object corresponding to that resource.
The URLFactory was introduced in Release 6.0 to replace the functionality
provided by GatewayURL, as GatewayURL has a number of significant
limitations in its implementation.
The URLFactory is an instance-based toolkit which may be used in either Java
code directly, JSP Pages or HTML templates. For Java code directly, there are
two constructors defined as can be seen in the Javadoc. The most commonly
utilized one will be:
URLFactory aURLFactory = new URLFactory( );

This will utilize the current server’s codebase and properties for HREF
construction.

Using the URLFactory with JSP


See URLFactory in the JSP Environment in the Additional Topics - Client
Customization appendix on page E-5, for details on how to setup a JSP page to
utilize the URLFactory.

Utilizing Windchill Gateways and Servlets with the URLFactory


In order to utilize the gateways and servlets with URLFactory a Helper class
needs to be written like the wt.httpgw.GatewayServletHelper class. These helper
classes will provide a series of methods to build properly formed links through the
gateway or servlet. For example, using the GatewayServletHelper class a call to
buildAuthenticatedHREF( ) will return a HREF utilizing the URLFactory with a
call similar to the one below (for JSP)
wt.httpgw.GatewayServletHelper.buildAuthenticatedHREF
(url_factory,"wt.httpgw.HTTPServer","echo","");

If writing a helper class, the GatewayServletHelper provides a good basis for


developing further helper classes. Helper classes should not be extended but
implemented on a package or servlet specific level and if possible should be
declared final for JIT (just-in-time) compilation and optimization.

Utilizing relative links in the URLFactory


URLFactory is simply a processor for taking a resource from an arbitrary location
under the codebase and determining if several techniques such as relative links

Generic UI Customizations 10-21


may be utilized for the desired resource. Relative links will automatically be
returned if the RequestURI is set, and the desired resource can be resolved into a
relative link (for example an external link to another site will always be returned
as an external link).

Setting the URLFactory to Output Fully Qualified HREFs


In order to generate fully qualified HREFs, the easiest method is to set the request
URI to null. For example,
URLFactory aFactory = new URLFactory( );
aFactory.setRequestURI( null );
String aHREF =
aFactory.getHREF("wt/clients/login/login.html");

Would return the HREF:


"http://<hostname>/<web-app>/wt/clients/login/login.html"

Writing a Mapping File


A mapping file is basically a flat-text property file. Empty lines, or lines starting
with a # are ignored. The mapping filename for Windchill is urlmap.properties
and should be located in the Windchill codebase. The URLFactory is smart
enough to find it and utilize it automatically. The mappings should be key/value
pairs and following the mapping schemes defined below.

Valid Mapping Schemes


There are many different mapping schemes and formats that may be used. Please
see the Javadoc for wt.httpgw.URLFactory mappings. Following are three
common mappings that may be used, however altogether there are over twenty
such mappings.
# Will map the folder wt/clients to a folder on newhost.com,
# in the Windchill6 codebase
wt/clients/=http://newhost.com/Windchill6/wt/clients/

# Will map the wt/clients folder to another folder


wt/clients/=wt/customization/clients/

# will map the resource index.html to the same protocol on a


# new host and codebase
wt/clients/index.html=
://newhost.com/Windchill6/wt/clients/index.html

Mapping a Particular File Type


Currently there is no functionality in the mapping scheme to map a particular file
type to an alternate location/hostname. In future releases of Windchill this may be
addressed if there is a need for this capability.

10-22 Windchill Customizer’s Guide


Mapping Components of Core Windchill
For Windchill Development, the mapping scheme should NOT be used to map
any components of the core Windchill. This capability has been added to support
multiple customer requirements, and should not be utilized as a way to make
classes/documents of Windchill re-direct to other classes/documents. The
mapping file may be used during development to remap to a new prototype or
program, however proper HREFs should be implemented in any relevant files
before the program is placed into production. There is a performance decrease
using the URLFactory, and it should only be used to support customizations.

Capturing Errors From the URLFactory


Currently the only exceptions thrown by the URLFactory are at URLFactory
instantiation. A WTException will be thrown by URLFactory if there is a problem
reading the urlmap.properties file at construction.

Character Encoding in the URLFactory


Character encoding in the URLFactory will be handled internally by the
URLFactory. All HREFs and URLs will be properly encoded before being
returned to the calling program. As well, any passed in parameters are assumed to
be in their decoded form and stored in the appropriate HashMap. See the
parseFormData or parseQueryString class entry in your installed Windchill
Javadoc for more information.

Generic UI Customizations 10-23


Offline Package Customization

Objective
You want offline packages exported from Windchill 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 company’s brand identity.

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

10-24 Windchill Customizer’s Guide


Solution Elements

Element Type Description

resources.zip Zip file 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.

wpofflinestyles.css CSS Style Sheet Contained within the resources.zip file, this CSS
style sheet contains the rules which control the look
and feel of the offline view.

head.html HTML File The HTML file which is loaded at the top of every
page.

header.gif GIF graphics file The background image of the header

logoWC.gif GIF graphics file Transparent GIF of the Windchill logo.

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 section on page 10-26.
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 10-25


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 Default Value Description

.pageHeader Dark teal background with Defines the border, background image
Windchill background and color of the header.
image (header.gif) and a
dark green bottom border.

.wncApplLogo logoWC.gif Defines logo graphics file.

.applLogo Height: 55 pixels. Defines the height of the logo div,


normally shown in the upper left corner of
the page.

.pageHeaderActions White text links. Defines the style of links and text
(CSS rule in normally in the upper right corner of the
wpofflinestyles.css) page.

pageHeaderActions Delivered empty Links can be added to this div.


(div in head.html)

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

Offline Package View Supported Icons


The following icons are supported in the offline view of a package. Only these
icons are capable of being represented. If an object of an unsupported type is
included in a package, the offline view attempts to determine which icon is closest
in the object hierarchy using the external type id string. If none if found, a generic
icon is used.
• WPBaseline
• WTPart

10-26 Windchill Customizer’s Guide


• WorkPackage
• CDRLPackage
Documents
• WTDocument
• Plan
• Agenda
• Presentation
• General
• ReferenceDocument
• Minutes
CAD Documents
• EPMDocument
• DynamicDocument
• Note
• Deviation
• BurstConfiguration
• CADASSEMBLY
Change Objects
• WTVariance
• WTChangeRequest2
• WTAnalysisActivity
• WTChangeInvestigation
• WTChangeProposal
• PromotionNotice
• WTChangeActivity2
• WTChangeDirective
• WTChangeIssue
• WTChangeOrder2
• ChangeAction
• AuthorizationAgreement

Generic UI Customizations 10-27


• VariantSpec
• WTProductInstance2
• folderLink

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

10-28 Windchill Customizer’s Guide


System Banner Alert Message
You can create a sytem 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
<%@ 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: windchill_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>

Removing the alert message from Windchill UI page


Set windchill_home\codebase\netmarkets\jsp\util\banner.txt as empty file.

Generic UI Customizations 10-29


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

10-30 Windchill Customizer’s Guide


11
Customizing HTML Clients
Using the Windchill JSP
Framework

This chapter explains and give 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).

Topic Page
Customizing Generic Aspects of JSP Pages......................................................11-2
Customizing UI Branding .................................................................................11-2
Customizing the UI with Ajax...........................................................................11-4
Checkin/Checkout .............................................................................................11-8
Component Access Control.............................................................................11-11
Attachments.....................................................................................................11-16
Property Panel .................................................................................................11-26
Customizing Access Control For Packages.....................................................11-33
Generating HTML Tags for ProductView Visualization Within a JSP Page .11-37
Tools Overview ...............................................................................................11-40
Adding Validation Logic for Actions and Properties......................................11-51

11-1
Customizing Generic Aspects of JSP Pages
This section contains the following topics:
• Customizing UI Branding (page 11-2)
• Customizing the UI with Ajax (page 11-4)

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 section in the
Internationalization and Localization on page 40-8.

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/windchill/index.htm>Windchill</a>
<sup>&reg;</sup>
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>
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:

11-2 Windchill Customizer’s Guide


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 11-3


Customizing the UI with Ajax

Objective
Explain and give examples of how to implement an Ajax UI component. Also
gives detailed explanation of Ajax capabilities and overview to the Ajax
infrastructure
Problem: You would like to make an action to be ajax based to make the action
faster and more usable.
Problem: You would like a portion of the page to dynamically refresh when some
event occurs.

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 update the majority of the page like most of the rows of a
table.
Ajax actions only update the row of the table, or refresh the whole table, that the
action was invoked on. The rest of the page and table are unchanged when the
action is complete.

Scope/Applicability/Assumptions
Assume you have an action that updates an object and refreshes the parent page
when complete and an action that updates all the rows of a table.

Intended Outcome
The result of applying this pattern is that instead of the page refreshing, the row is
updated in-line and highlighted in yellow in the first case, and the second case the
table fades out and refreshes itself without refreshing the rest of the tables and
navigation on the page.

Solution
Specify some Ajax based configuration and code in the action to allow the Ajax
refresh to work.

11-4 Windchill Customizer’s Guide


Solution Elements
Element Type Description

<your actions>.xml XML Xml file that contains the action definitions

<your>formProcessor.java Java Delegate that performs the db transaction

<your wizard step>.jsp Jsp Jsp to partially refresh in a wizard

Refresh a row in a table


In the <your actions>.xml, specify the ajax attribute to have value of “row”
<action name="<your action>" ajax="row">
<command class="……”…> </action>

In the <your>formProcessor.java file, 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(di);
result.setNextAction(FormResultAction.REFRESH_OPENER);
return result;
}

Many examples exist, search actions.xml for ajax=”row” or the processors for the
addDynamicrefreshInfo.

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>

Third Level Navigation


To get the whole Third level navigation section to refresh when the action
completes, specify the ajax type to be thirdLevelNav.
<action name="<your action>" ajax=" thirdLevelNav">
<command class="……”…> </action>

Refresh a partial page, typically in a wizard step


This can be done with a javascript call to refreshDivTag that will bind an ajax
call to the on change event of a field. The jsp needs to have a <div> tag wrapped
around it and it should include begin.jspf and end.jspf.

Customizing HTML Clients Using the Windchill JSP Framework 11-5


Finally you should have this javascript block in your JSP that need to be
refreshed.
<script type=”text/javascript”>

refreshDivTag ('id of div tag', 'id of object to listen to event


on', 'url to the page');

</script>

Example:
refreshDivTag ('sourceContextDropDown', 'myContextPicker',
'/netmarkets/jsp/folder/sourceFoldersDropDown.jsp');

Examples: codebase\netmarkets\jsp\folder\sourceFoldersDropDown.jsp

Sample Code
Examples of usage in out-of-the-box code.

Packaged samples

Picture of part 1 of the interaction when a popup action dynamically updates the
page. The popup action is completed and calls to refresh the opener window.

11-6 Windchill Customizer’s Guide


Picture of interaction when a popup action dynamically updates the page when a
dynamic popup action completes.

Customizing HTML Clients Using the Windchill JSP Framework 11-7


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/Assumptions
• The object implements either the Workable interface.
• Familiarity with the actions framework
• Familiarity with the basic concepts of checkin/checkout

Intended Outcome
By following these procedures you should be able to add or modify the checkin
and checkout actions.
• Checkout action (no wizard involved)

11-8 Windchill Customizer’s Guide


• Checkout status icon after the object is checked out

• 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 11-9


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" type="wip"/>
<action name="checkout" type="object"/>
<action name="checkout_and_download" type="wip"/>
<action name="undocheckout" type="object"/>
<action name="replace_content" type="wip"/>
<action name=" checkoutAndEdit " type="YOUR TYPE FROM
YOUR TYPE’S ACTIONS XML"/>

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 then 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\DocumentManagement-
actionmodels.xml)
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)

11-10 Windchill Customizer’s Guide


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/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 object’s action model.
• The Access Control Component can be included as a step in the object’s
Create wizard.

Intended Outcome

Manage Security Action


When the Manage Security action is included in an object’s action model, the
action will available in the object’s action list.

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.

Customizing HTML Clients Using the Windchill JSP Framework 11-11


Create Wizard
When the component is included in an object’s 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 Type Description

actionmodels.xml XML Windchill\codebase\actionmodels.xml


The actionmodels file defines the
actions available in named action
models.

Create<myObject>.jsp JSP The outer jsp file defining a create


wizard

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

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

11-12 Windchill Customizer’s Guide


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\
DevModules\Foundation\src\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</csvdi
splayName>

<csvdescription>com.ptc.core.security.securityResource:READ</csvde
scription>

<csvlongDescription>com.ptc.core.security.securityResource:READ</c
svlongDescription>
<csvdefaultValue>UPDATE</csvdefaultValue>

<csvhandler>com.ptc.windchill.enterprise.preference.handler.Choice
MultiPreferenceValueHandler:readPermission:HIDE,com.ptc.core.secur
ity.securityResource,HIDE:VIEW,com.ptc.core.security.securityResou
rce,VIEW:UPDATE,com.ptc.core.security.securityResource,UPDATE</csv
handler>
</csvPreferenceDefinition>

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

Customizing HTML Clients Using the Windchill JSP Framework 11-13


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 name="ManageSecurity" 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>

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

11-14 Windchill Customizer’s Guide


<%@ 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:wizardStep action="setAccessControlWizStep"
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\DevModules\Security\src_web\config\actions\Security-actions.xml
defines
<action name="setAccessControlWizStep"
id="setAccessControlWizStep" preloadWizardPage="false">

<command
class="com.ptc.core.security.forms.UpdatePermissionsFormDelegate"
method="" windowType="wizard_step"/>
</action>

Customizing HTML Clients Using the Windchill JSP Framework 11-15


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

11-16 Windchill Customizer’s Guide


Primary content component in a wizard (object must be a FormatContentHolder)

Secondary attachments component in a wizard (object must be a ContentHolder)

Customizing HTML Clients Using the Windchill JSP Framework 11-17


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 table in a details page (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

11-18 Windchill Customizer’s Guide


Solution Elements
Element Type Description

attachments.tld Java tag definition Defines any common component


tags you will need to use the
attachments common
components.
Runtime location:
codebase\WEB-INF\tlds\
attachments.tld

AttachmentsDown Java file Servlet that redirects download to


loadAppletServlet. the appropriate file for the object.
class
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar

AttachmentsValid Java file Supporting methods for


ationHelper.class validating various attachments
related actions.
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar

AbstractAttachme Java file General form processing delegate


ntsSubFormProces that provides shared attachments
sor.class functionality to the primary and
secondary form processors.
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar

PrimayAttachment Java file Form processing delegate that


SubFormProcessor attaches primary attachments to
.class the object.
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar

Customizing HTML Clients Using the Windchill JSP Framework 11-19


Element Type Description

SecondaryAttachm Java file Form processing delegate that


entsSubFormProce attaches secondary attachments
ssor.class to the object.
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar

AttachmentsDataU Java file Supporting methods for


tilityHelper.class displaying attachments data in a
data 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/>

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.

11-20 Windchill Customizer’s Guide


<%@taglib prefix="attachments"
uri="http://www.ptc.com/windchill/taglib/attachments" %>

<attachments:fileSelectionAndUploadApplet/>

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 nav 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" type="wip"/>

<action name="replace_content" type="wip"/>

Customizing HTML Clients Using the Windchill JSP Framework 11-21


Customization Points

<primaryAttachment> tag attributes


Parameter Default Value Possible Values Req? Description

allowFile true True/False no Allows the Local File


option to be displayed.

allowUrl true True/False no Allows the URL Link


option to be displayed.

allowExternal true True/False no Allows the External


Storage option to be
displayed.

allowRemoveP true True/False no Allows existing primary


rimaryContent content to be removed.

showAttachme false True/False no Displays the optional


ntComments Comments field.

showDistributa false True/False no Displays the optional


ble Externally Distributable
checkbox.

showOptionalF false True/False no Displays the optional file


ileAttributes version, tool version and
tool name fields.

showAuthoring false True/False no Displays the optional


Information Authored By and Last
Authored fields.

fixedFilePath null Valid file path no 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
fileSelectionAndUploadA
pplet tag are both set this
can be used to force the
specified file to be
uploaded and attached to
the object.

11-22 Windchill Customizer’s Guide


<fileSelectionAndUploadApplet> tag attributes
Parameter Default Value Possible Values Req? Description

forceApplet False True/False no Determines if we should


force the applet to be
rendered regardless of the
upload mechanism
preference

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, jsp’s,
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).

Additional notes about documents:


For documents only (not other FormatContentHolders) you will find similar
entries in the wizard jsp’s 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.

Customizing HTML Clients Using the Windchill JSP Framework 11-23


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.

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"


/>

...

11-24 Windchill Customizer’s Guide


</jca:wizard>

.<attachments:fileSelectionAndUploadApplet/>

Attributes Step JSP


<%@taglib prefix="attachments"
uri="http://www.ptc.com/windchill/taglib/attachments" %>

...

<attachments:primaryAttachment>

...

Customizing HTML Clients Using the Windchill JSP Framework 11-25


Property Panel

Objective
You want to display the attributes of some object as label value pairs. You want
the colons to align and the HTML to be section 508 compliant.

Scope/Applicability/Assumptions
This document assumes you are familiar with the configuring and acquiring the
data for a JCA table.

Solution
Use the property panel component to display label/value pairs (or label/input field
pairs) for an object.
Examples:

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving HTML, JSP, JavaScript and Custom taglibs.
• Overview of JCA tags.
• JCA Table

11-26 Windchill Customizer’s Guide


• Configuring Data Acquisition, Data Utilities and GUI components

Solution Elements
Element Type Description

<your_page>.jsp jsp Your JCA Property Panel implementation


jsp file.

<your>service.properties properties Data utilities and services are defined


here.
Run time Location: <Windchill>\
codebase

components.tld tld Tags can be defined here.


Run time Location: <Windchill>\
codebase\WEB-INF\tlds\

Procedure – Using the Property Panel Common Component


Using the JCA property panel is similar to using a JCA table, it just has different
tags. For the property panel there are describePropertyPanel, describeProperty and
renderPropertyPanel tags that are analogous to the describeTable,
describeColumn and renderTable tags respectively. This is used in both Create
and View.
These tags are defined in components.tld, to use them your jsp should include that
taglib:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>

Describe the property panel


To describe the property panel use the describePropertyPanel and
describeProperty tags. For example:
<jca:describePropertyPanel var="<name of the descriptor>">
<jca:describeProperty id="name" />
<jca:describeProperty id="number" />
<jca:describeProperty id="<attribute name | data utility id |
logical form>" />
</jca:describePropertyPanel>

The value for <name of the descriptor> can be any name you wish to assign to
your panel.
The reporting tool that gives details about what properties are available can be
accessed here:
http://<HOSTNAME>/<WEBAPP>/netmarkets/jsp/property/propertyReport.
jsp

Customizing HTML Clients Using the Windchill JSP Framework 11-27


Acquire the Data for the property panel
To acquire data use the either the getModel or getIeModel tag. 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 data.
The value for <name of the descriptor> should be that used in your
describePropertyPanel tag.

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.
To see more code examples of using the renderPropertyPanel tag look at:
<WT_HOME>/codebase/netmarkets/jsp/carambola/propertyPanel/examples
.jsp

To see how the above jsp looks on your system go here:


http://<HOSTNAME>/<WEBAPP>/netmarkets/jsp/carambola/propertyPanel/
examples.jsp

Customization Points

describePropertyPanel tag attributes


describePropertyPanel describes a Property Panel common component that can be
plugged in to JCA getModel or getIeModel tags. Its tag class is
com.ptc.core.components.tags.components.DescribePropertyPanelTag and the
body content is “scriptless”.

Parameter Default Value Possible Values Req? Description

var - Any.String value Yes Name of the exported scoped


variable for the property panel
descriptor. The type of the variable is
com.ptc.core.components.descriptor.
ComponentDescriptor.

11-28 Windchill Customizer’s Guide


Parameter Default Value Possible Values Req? Description

scope page Can be: 'page', No The name of the scope to export the
'request', 'session' or var attribute to.
'application'
(case-insensitive)

mode VIEW String form of No Sets the ComponentMode that will be


com.ptc.core.ui.resou used for validation and for data
rces.ComponentType utilities to determine what kind of
enum: GUI component to return.
VIEW, CREATE,
EDIT, SEARCH

componentT TABLE String form of No Sets the ComponentType that will be


ype com.ptc.core.ui.resou used for validation and for data
rces.ComponentType utilities to determine what kind of
enum: GUI component to return.
TABLE, WIZARD,
WIZARD_TABLE,
INFO_ATTRIBUTE
S_TABLE, SIMPLE,
INFO, PICKER,
SEARCH

describeProperty tag attributes


The describeProperty tags are nested as children of the describePropertyPanel tag.
Its tag class is com.ptc.core.components.tags.components.DescribePropertyTag
and the body content is “scriptless”. Below are some of the attributes that can be
set. For more information see the components.tld.

Parameter Default Value Possible Values Req? Description

id - name of an Yes The identifier for this property


attribute, data descriptor. This is used to look up
utility id or logical default properties for the column. If the
attribute parent table supports configurable
views, then this id is used to look up the
view configurations.

var - Any String value Yes Name of the exported scoped variable
for the property panel descriptor.The
type of the variable is
com.ptc.core.components.descriptor.C
omponentDescriptor.

Customizing HTML Clients Using the Windchill JSP Framework 11-29


Parameter Default Value Possible Values Req? Description

label - Any String value No A localized display label for this


property. If the label isn’t specified,
then the infrastructure will attempt to
look up a label

scope page Can be: "page" , No The name of the scope to export the var
"request", "session" attribute to.
or "application"
(case-insensitive).

mode value inherited String form of No Sets the ComponentMode that will be
from com.ptc.core.ui.res used for validation and for data utilities
describePropert ources.Component to determine what kind of GUI
yPanel tag Mode enum: component to return.
VIEW, CREATE,
EDIT, SEARCH

renderPropertyPanel tag attributes


The renderPropertyPanel tag renders a JCA Property Panel. Its tag class is
com.ptc.core.components.tags.propertyPanel.RenderPropertyPanelTag and the
body content is “scriptless”.
Below are some of the attributes that can be set. For more information see the
components.tld.

Parameter Default Value Possible Values Req? Description

model - Of type Yes The model to render. If there are


com.ptc.core.comp no child tags just the model is
onents.descriptor.C rendered. If there are child tags,
omponentModel then the model is just used as the
default model for any
addProperty tags that don't
specify a model.

Sample Code
There are many ways to use the renderPropertyPanel tag and its child tags to
display the ComponentModel that is put into page scope by the getModel tag.
To see more code examples of using the renderPropertyPanel tag and its child tags
look at:
<WT_HOME>/codebase/netmarkets/jsp/carambola/customization/examples
/propertyPanel/examples.jsp

You can see the examples on your system here:

11-30 Windchill Customizer’s Guide


http://<HOSTNAME>/<WEBAPP>/netmarkets/jsp/carambola/customization/
examples/propertyPanel/examples.jsp

Examples of Usage in Windchill Code


<WT_HOME>\codebase\netmarkets\jsp\configuration\
createConfiguration_step.jsp

<jca:describePropertyPanel var="attributeDisplayPanelDescriptor"
mode="VIEW">
<jca:describeProperty id="number" label="${base_part_number}" />
<jca:describeProperty id="orgid"/>
<jca:describeProperty id="version" label="${base_part_version}"
/>
<jca:describeProperty id="name" label="${base_part_name}" />
</jca:describePropertyPanel>

<jca:describePropertyPanel var="attributeInputPanelDescriptor"
mode="CREATE" >
<jca:describeProperty id="name" inputRequired="true"
label="${part_config_name}" />
<jca:describeProperty id="description"
label="${part_config_desc}" />
</jca:describePropertyPanel>

<wc:batch>
<jca:getModel var="attributeDisplayPanel"
descriptor="${attributeDisplayPanelDescriptor}"
serviceName="wt.fc.StandardPersistenceManager"

Customizing HTML Clients Using the Windchill JSP Framework 11-31


methodName="refresh">
<jca:addServiceArgument
value="${commandBean.primaryOid.oid}"
type="wt.fc.ObjectIdentifier" />
</jca:getModel>
<jca:getModel var="attributeInputPanel"
descriptor="${attributeInputPanelDescriptor}"

serviceName="com.ptc.core.components.forms.CreateAndEditModelGette
r"
methodName="getItemAttributes">
<jca:addServiceArgument
value="${attributeInputPanelDescriptor}"
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>
</wc:batch>

<jca:renderPropertyPanel>
<jca:addPropertyPanel model="${attributeDisplayPanel}"/>
<jca:addSeparator/>
<jca:addPropertyPanel model="${attributeInputPanel}" />
<w:radioButton propertyLabel="${populate}" name="PopulationType"
value="<%=PartConfigurationCommand.POPULATION_BASIC%>"
label="${basic}" checked="true" required="true" />
<w:radioButton name="PopulationType"
value="<%=PartConfigurationCommand.POPULATION_FULL%>"
label="${full}"/>
</jca:renderPropertyPanel>

11-32 Windchill Customizer’s 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/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 11-33


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

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

packageSharedTeamTemplate.xml 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 isn’t extended.
Location: <WT_HOME>/loadXMLFiles/

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 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 file applies to the entire site which means you can not
customize it for specific contexts or specific packages.

11-34 Windchill Customizer’s Guide


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
packageSharedTeamTemplate.xml will be used and the roles from
packageTemplate.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>
<WTPrincipalReference isInternal="true">
<groupName>PACKAGE MANAGER</groupName>
<groupType>ALL</groupType>
</WTPrincipalReference>
<grantPermissionSet>
<AccessPermissionSet>
<permissionField name="ALL"/>
</AccessPermissionSet>
</grantPermissionSet>
</AccessControlRule>

Customizing HTML Clients Using the Windchill JSP Framework 11-35


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

11-36 Windchill Customizer’s Guide


Generating HTML Tags for ProductView Visualization
Within a JSP Page
At the Windchill 6.2 release there is no supported API for generating the HTML
tags for ProductView visualization within a JSP page. This TAN documents the
support now available.
To generate HTML code for the ProductView visualization components in a JSP
page, use the com.ptc.wvs.common.ui.VisualizationHelper class. See this class
entry in your installed Windchill Javadoc for more information.
public static final String
THUMBNAILS_PROP_PAGE_PREF_KEY
Constant defining preferences entry for generating thumbnails on the property
page
public static final String
DEFAULT_THUMBNAILS_PROP_PAGE_PREF_VALUE
Default value for generating thumbnails on the property page
public String getCreateDialogWindow()
Returns the JavaScript to create the Dialog Window function
creationDialogWindow. This should be called once per page. This JavaScript
function is used by the HREFs created from getDefaultVisualizationData().
public String[] getDefaultVisualizationData(String
representableObjectReference, Boolean forListing, Locale
locale)
Returns a set of HTML fragments to allow the default representation to be
manipulated by a UI.
public int getIndexOfVisLink(String prefKey, String
prefDefault)
Returns the index in the data array returned by getDefaultVisualizationData
of the URL to use for launching ProductView.
public int clipboardLinkIndex()
Returns the index of the Add to Clipboard link in the data array returned by
getDefaultVisualizationData
public int printLinkIndex()
Returns the index of the Print link in the data array returned by
getDefaultVisualizationData
public int viewRepsLinkIndex()
Returns the index of the view representations link in the data array returned
by getDefaultVisualizationData
public int[] getThumbnailSize()
Returns the user-preferred thumbnail width and height
public boolean isWVSEnabled()
Returns true if WVS is enabled, otherwise it returns false.

Customizing HTML Clients Using the Windchill JSP Framework 11-37


public static VisualizationHelper newVisualizationHelper()
Default factory for the class.

General flow of logic:


The VisualizationHelper can be instantiated via the newVisualizationHelper()
factory method.
getCreateDialogWindow() is required to generate the Javascript fragment
required by the results returned from getDefaultVisualizationData(String,
Boolean, Locale). This code must be embedded somewhere in the HTML returned
by the JSP page.
getDefaultVisualizationData(String, Boolean, Locale) method returns an array of
String values. Each value corresponds to a different component within the
ProductView Visualization Service. Elements in the array can be accessed
directly through the indexes returned by the following methods:
getIndexOfVisLink(String, String), clipboardLinkIndex(), printLinkIndex(),
viewRepsLinkIndex(). Each String is the base HTML code for the ProductView
visualization component and can be embedded into the HTML returned by the
JSP page. It may be an '<A HREF .. /A>' code tag or other simple unformated
HTML tags.

Note: The getDefaultVisualizationData(String, Boolean, Locale) method returns


the basic HTML components necessary for accessing the ProductView
visualization components. Most likely the results will need to be used within
proper HTML tags. The responsibility of designing the user interface and properly
using the values returned by these methods belongs to the implementer.

Example usage:
// comp.ptc.wvs.common.ui.VisualizationHelper is assumed to be imported.
VisualizationHelper visHelper = newVisualizationHelper();
if (visHelper.isWVSEnabled()) //only execute code if WVS is enabled
{
// Embed the create dialog JavaScript somewhere in returned HTML.
// The below is just an example of calling it. Placement within
// HTML is the responsibility of the implementer.
out.println(visHelper.getCreateDialogWindow());

//ObjectReference object or and locale object is assumed to be obtained prior to


the following line
String visData[] = visHelper.getDefaultVisualizationData(or.toString(),new
Boolean(false), locale);
//Obtain array indices for thumbnail, clipboard link, print link, and
representations link
int thumbnailIndex = visHelper.getIndexOfVisLink(
VisualizationHelper.THUMBNAILS_PROP_PAGE_PREF_KEY,
VisualizationHelper.DEFAULT_THUMBNAILS_PROP_PAGE_PREF_VALUE);
int clipboardIndex = visHelper.clipboardLinkIndex();
int printIndex = visHelper.printLinkIndex();
int repsOrMarkupsIndex = visHelper.viewRepsLinkIndex();
/**

11-38 Windchill Customizer’s Guide


* Print the various HTML code fragments generated for each component.
* Any HTML formatting code must be wrapped around each of the following lines
**/
out.println(visData[thumbnailIndex]);
out.println(visData[clipboardIndex]);
out.println(visData[printIndex]);
out.println(visData[repsOrMarkupsIndex]);
}

Customizing HTML Clients Using the Windchill JSP Framework 11-39


Tools Overview
This section contains the following information:
• Available Attributes Report
• Debugging
• Taglib documentation
• Action Report
• Action Model Report

Available Attributes Report


To find the list of supported attributes for a given object type (eg:
wt.part.WTpart), you can use the Available Attributes Report that can be accessed
from a running Windchill installation. The report includes information about the
attribute such as the id used to reference the attribute in your JSPs and the label
used for that attribute in the UI. The data utility mapped to that component is also
listed.

http://<machine_name>/<app_name>/netmarkets/jsp/carambola/createta
bleview/availableAttributesReport.jsp

11-40 Windchill Customizer’s Guide


Debugging
There is a debug mode that can be enabled in the UI that can help track down
information about a particular action on a page. The jcaDebug tool is a display
parameter that can be added to any URL to add debug info to the current page
inline with the items in the page.
The debug tool can:
• debug what class is handling data that gets displayed in a table cell
• shows what kind of component is rendering the cell data
• shows what class is responsible for hiding/enabling/disabling an action

Enable jcaDebug
To enable the JCA debug feature add the following to the end of any url, that is
JCA:
&jcaDebug=true

For example:
<servername>/Windchill/servlet/TypeBasedIncludeServlet?Containe
rOid=OR%3Awt.pdmlink.PDMLinkProduct%3A4462&oid=VR%3Awt.part.WTP
art%3A5142&u8=1&jcaDebug=true

Action Tool Tips


If you perform a mouse over on an action, the following tooltip displays.

The tool tip displays the following information:

Attribute Description

Display Name Displays the name of the action.

Action Name Displays the action type separated by a period and the
action name. The Action Name is also a hyperlink to
the action details page.

Action Model Name Displays the action model name. The Action Model
Name is also a hyperlink to the action model details
page.

Customizing HTML Clients Using the Windchill JSP Framework 11-41


Attribute Description

Validator Displays the validator.

Validator Status Displays the status of the validator.

Table Cell Tooltips


The Table Cell objects have an icon (red lady bug), that you can mouse over to
display the following tooltip.

The tool tip displays the following information

Attribute Description

Data Utility Displays the data utility.

GUI Type Displays the GUI type.

Column ID Displays the ID used to look up the customizable


delegates.

Row Object Displays the object passed into the data utility that the
table cell is displaying info about.

Taglib documentation
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.
Refer to the taglib javadoc at the following location:
http://www.ptc.com/view?im_dbkey=61784

11-42 Windchill Customizer’s Guide


Action Report
We support modularized actions and actionmodels within the system, so to find
what file an action is defined in, there is a reporting tool that can be used. On a
running Windchill installation, you can use the Actions report.
The Action Report is a search page that returns the details of actions matching the
search criteria.
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, object type.

The search supports multiple search parameters, regular expressions and case-
insensitive matching.

Location
http://<your machine name>/<app-
name>netmarkets/jsp/carambola/tools/actionReport/action.jsp

Search Supports
• Multiple search parameters
• Regular expressions
• Case-insensitive matching

Customizing HTML Clients Using the Windchill JSP Framework 11-43


Action Details Page

If there is no information for the particular action, the line is shown blank.

Search Examples

Description
remove ==> Matches: "remove", "list_delete", "related_delete_described_part",
etc.

Action Name
• remov.* ==> Matches: "remove", "remove_deliverable", "removeUses", etc.
• r[a-z]* ==> Matches: "reply", "REVISEITEMS", "reassignLC", etc.

11-44 Windchill Customizer’s Guide


• .*move ==> Matches: "remove", "CONTAINERMOVE", "WFMOVE", etc.
• .* ==> Matches: everything

Hot Keys
m ==> Matches: "home"
.* ==> Matches: "home", "productStructure", "documentStructure", etc.

Action Model File/Action Definition File


only files under \codebase\
search matches files under "\config\actions\" with specifying it

Note: Some matches may be deceiving due to include tags in xml files

Known Bugs
• Opposite facing slashes in file paths
– On Details Page
Definition file: Z:\\Windchill\codebase\config/actions/RelContext-
actions.xml
– In Details Table

• In Internet Explorer
– When pressing the back button from the Details Page, you are given:

Customizing HTML Clients Using the Windchill JSP Framework 11-45


– Then, when refreshing this page, you get the alert:

Clicking retry will correctly refresh this page.

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.

11-46 Windchill Customizer’s Guide


Action Model Report
We support modularized actions and actionmodels within the system, so to find
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 ActionModels report.
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.

Location
The Action Model Report is available at the following location:
http://<your machine name>/<app-
name>/netmarkets/jsp/carambola/tools/actionReport/actionModel.jsp

Search Supports
• Multiple search parameters
• Regular expressions
• case-insensitive matching

Search Examples
Returns action models depending on search:

(all examples below are the action model names returned)

Customizing HTML Clients Using the Windchill JSP Framework 11-47


Action Model Details Page

If there is no information for the attribute of a particular action model, the line is
shown blank.

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

Model File
• only files under \codebase\
• search matches files under "\config\actions\" without having to specify it

11-48 Windchill Customizer’s Guide


Note: Some matches may be deceiving due to include tags in xml files.

Action Model Details

Description for this Model


This represents the comments for an action model. When a "description" tag is
used in an actionmodel xml file, the information in the tag is then saved and
displayed.

Order in Table
This shows the order of the actions within an actionmodel xml file.

Known Bugs

In Internet Explorer
When pressing the back button from the Details Page, you are given:

Then, when refreshing this page, you get the alert:

Customizing HTML Clients Using the Windchill JSP Framework 11-49


Clicking retry will correctly refresh this page.

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 what you are looking for.

11-50 Windchill Customizer’s Guide


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.

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.

Customizing HTML Clients Using the Windchill JSP Framework 11-51


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 method’s 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
{

}

}

11-52 Windchill Customizer’s Guide


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
– 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 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 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?
The UI Component (Action) Validation Service exposes one or more APIs for
each of the types of validation listed above.

Customizing HTML Clients Using the Windchill JSP Framework 11-53


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 section will concentrate on the authoring of Validator classes and methods.

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

11-54 Windchill Customizer’s Guide


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, you’ll 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 team’s 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/<vali
daitonKey>/null/0=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?)

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:

Customizing HTML Clients Using the Windchill JSP Framework 11-55


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,
UIValidationMsgType.INFO)
}
// return a validation result with the calculated status
and message
return new UIValidationResult(a_key, contextObject,
status, msg);
}

}

11-56 Windchill Customizer’s Guide


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,
UIValidationStatus.PERMITTED, null));
}
else{
resultSet.addResult(new UIValidationResult(a_key,
targetRef,
UIValidationStatus.DENIED, new
UIValidationMsg
(localized text,
UIValidationMsgType.INFO)));
}

Customizing HTML Clients Using the Windchill JSP Framework 11-57


}

// 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
they’ve 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:
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:

11-58 Windchill Customizer’s Guide


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

Customizing HTML Clients Using the Windchill JSP Framework 11-59


}
}

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, it’s
important to note that in practice it’s 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

Note: This source code can be found at the following location: \Windchill\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;

import com.ptc.core.ui.validation.*;

import java.lang.ClassNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;

import org.apache.log4j.Logger;

import wt.access.AccessPermission;
import wt.access.AccessControlHelper;
import wt.epm.workspaces.EPMWorkspaceHelper;
import wt.fc.Persistable;
import wt.fc.ReferenceFactory;
import wt.fc.WTReference;
import wt.fc.collections.WTArrayList;
import wt.fc.collections.WTCollection;
import wt.folder.CabinetBased;
import wt.folder.CabinetMember;
import wt.folder.Foldered;

11-60 Windchill Customizer’s Guide


import wt.folder.FolderHelper;
import wt.inf.container.WTContained;
import wt.inf.container.WTContainerHelper;
import wt.log4j.LogR;
import wt.org.WTUser;
import wt.sandbox.SandboxHelper;
import wt.session.SessionHelper;
import wt.util.WTException;
import wt.vc.Iterated;
import wt.vc.VersionControlHelper;
import wt.vc.wip.Workable;
import wt.vc.wip.WorkInProgressHelper;
import wt.vc.wip.WorkInProgressState;

public class DefaultWIPValidator extends DefaultUIComponentValidator


{
private Logger logger = LogR.getLogger("wt.method.server.httpgw");
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
* 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
{
logger.debug("ENTERING DefaultWIPValidator.performLimitedPreValidation");
logger.trace(" validtionKey -> " + validationKey);
logger.trace(" validationCriteria -> " + validationCriteria.toString());

Customizing HTML Clients Using the Windchill JSP Framework 11-61


UIValidationResultSet resultSet = performWIPValidation(validationKey,
validationCriteria, locale, LIMITED);

logger.trace("RETURNING " + resultSet.toString());


logger.debug("EXITING DefaultWIPValidator.performLimitedPreValidation");
return resultSet;
}

public UIValidationResultSet performFullPreValidation (String validationKey,


UIValidationCriteria validationCriteria, Locale locale)
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 validationKey,


UIValidationCriteria validationCriteria, Locale locale)
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,
UIValidationStatus.DENIED, null);
}

Workable workable = (Workable)persistable;

if (validationKey.equalsIgnoreCase("checkin") ||
validationKey.equalsIgnoreCase("undocheckout")){
result = performCheckinValidation(validationKey, workable, SELECTED,
(WTUser)(validationCriteria.getUser().getPrincipal()));
}
else if (validationKey.equalsIgnoreCase("checkout")){
result = performCheckoutValidation(validationKey, workable, SELECTED);
}

logger.trace("RETURNING " + result.toString());


logger.debug("EXITING DefaultWIPValidator.validateSelectedAction");
return result;

11-62 Windchill Customizer’s Guide


}

public UIValidationResultSet validateSelectedMultiSelectAction (String


validationKey,
UIValidationCriteria validationCriteria, Locale locale)
throws WTException
{
logger.debug("ENTERING
DefaultWIPValidator.validateSelectedMultiSelectAction");
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.validateSelectedMultiSelectAction");
return resultSet;
}

// ***NOTE:
// 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.getTargetObjects());
Iterator workableIter = getWorkableIterator(targetObjects);
Workable workable = null;

while (workableIter.hasNext()){
workable = (Workable)workableIter.next();
if (validationKey.equalsIgnoreCase("checkin") ||
validationKey.equalsIgnoreCase("undocheckout")){
resultSet.addResult(performCheckinValidation(validationKey,
workable, validationType, (WTUser)(validationCriteria.getUser().getPrincipal())));
}
else if (validationKey.equalsIgnoreCase("checkout")){
resultSet.addResult(performCheckoutValidation(validationKey, workable,
validationType));
}
}
resultSet.appendResults(processNonWorkables(targetObjects, validationKey,
validationType));

Customizing HTML Clients Using the Windchill JSP Framework 11-63


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,
UIValidationStatus.ENABLED, null);
}
else{
return new UIValidationResult(validationKey, wtRef,
UIValidationStatus.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).getContainerRefer
ence(), user))){

11-64 Windchill Customizer’s Guide


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

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,
UIValidationStatus.DISABLED, null);
}
else{
return new UIValidationResult(validationKey, wtRef,
UIValidationStatus.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,
AccessPermission.MODIFY)) &&
(!WorkInProgressHelper.isCheckedOut(workable) &&
(VersionControlHelper.isLatestIteration((Iterated)workable))
&&
(!SandboxHelper.isCheckedOutToSandbox(workable)))){

Customizing HTML Clients Using the Windchill JSP Framework 11-65


return new UIValidationResult(validationKey, wtRef, goodStatus,
null);
}
else{
return new UIValidationResult(validationKey, wtRef, badStatus,
null);
}
}
return new UIValidationResult(validationKey, wtRef,
UIValidationStatus.ENABLED, null);
}

private Iterator getWorkableIterator(WTCollection targetObjects)


{
try{
return
targetObjects.persistableIterator(Class.forName("wt.vc.wip.Workable"), true);
}
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;
}

11-66 Windchill Customizer’s Guide


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();
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 11-67


11-68 Windchill Customizer’s Guide
12
Adding Actions and Hooking
Them Up in the UI

This chapter describes how to customize actions and add them to the user
interface.

Topic Page
Windchill Client Architecture Action Framework Overview .......................... 12-2
Tab Models..................................................................................................... 12-17
Customizing Role-based Visibility ................................................................ 12-28
Navigation Stickiness ..................................................................................... 12-37

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

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

StandardNmActionService .java The StandardNmActionService manages the actions and


(and corresponding helper and actionmodels in the system.
forwarder)
Run time Location:
<Windchill>\codebase\com\ptc\netmarkets\util\misc

12-2 Windchill Customizer’s Guide


Element Type Description

actions.xml .xml Default system xml file for defining actions in the
system.
Run time Location:
<Windchill>\codebase\config\actions

actionmodels.xml *.xml Default system xml file for defining action models ins
the system.
Run time Location:
<Windchill>\codebase\config\actions

actions.dtd .xml Default system dtd file for defining structure of an


actions*.xml
Run time Location:
<Windchill>\codebase\config\actions

actionmodels.dtd *.xml Default system dtd file for defining structure of an


actionsmodels*.xml
Run time Location:
<Windchill>\codebase\config\actions

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
<windchill-install-dir>/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. ChangeManagement-actions.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.

Adding Actions and Hooking Them Up in the UI 12-3


For details about how to configure the action model to use for a component, see
related sections:
• See the Constructing Wizards chapter beginning on page 15-1 for more
detailed information on wizards
• See the information on tables and trees in the Presenting Information in the UI
chapter beginning on page 14-1
• See the information in the Information Pages chapter beginning on page 16-1

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
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”. We recommend that all your
objecttypes have a prefix specific to your 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.

Default Possible
Parameter Value Values Req? Description

name n/a any combination Yes The name used to reference this object-
of alpha-numeric type
characters

12-4 Windchill Customizer’s Guide


Default Possible
Parameter Value Values Req? Description

class n/a A valid java class Yes Object class for the enclosed actions

resourceBundle n/a Any valid No Class name for the default resource
resource bundle bundle to use for the properties of the
class name actions that are to be localized

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.
If there is no URL parameter specified, then the location of the jsp is assumed to
be <WT_HOME>/codebase/netmarkets/jsp/<objecttype name>/<action
name>.jsp. For example, the jsp of the "create" action (as show above on page
12-4) would be: <WT_HOME>/codebase/netmarkets/jsp/document/create.jsp.
Naming conventions for the name of an action can be any combination of alpha-
numeric 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.

Possible
Parameter Default Value values Req? Description

name n/a all Yes This is the name by which the action will
be referenced

ajax n/a Page No Specifies the scope of the AJAX refresh


Component
Row
thirdLevelNav
popupMenu

ajaxActionClass n/a No The jsp that is requested via ajax

cad false true No Indicates if this action is only valid within


the Wildfire embedded browser

enabledwhensusp false true No Enabled when the project is


ended suspended/cancelled/completed

Adding Actions and Hooking Them Up in the UI 12-5


Possible
Parameter Default Value values Req? Description

installType n/a WINDCHILL No Applicable actions based on the installed


PDM components. This is for legacy purposes
PDM only.
PJL
PDM

multiselect false false / true No Used to indicate that multi-selection of


row data can be used for this action.

selectRequired false false / true No Determines if the UI should allow the


action to proceed if nothing has been
selected. Results in "Nothing Selected"
popup

afterJS n/a No JS function name to invoke on client side


validation for a wizard step after the step
is completed.

beforeJS n/a No JS function name to invoke client side


validation for a wizard step when the step
is loaded

afterVK n/a No Server validator name to invoke client


side validation for a wizard step after it is
finished.

beforeVK n/a No Server validator name to invoke client


side validation for a wizard step when the
step is loaded.

id objecttype.actio No Overrides the id of the wizard step


n (default is objecttype.action)

preloadWizardPa true false / true No Specifies that the wizard step is to be


ge downloaded when the wizard is launched

hidden false false / true No A wizard step to be hidden first, or that an


action is rendered as non-clickable

required false false / true No Used for an wizard action that represents
a step in the wizard. Specifies the wizard
step is required.

resourceBundle No Class name for the resource bundle to use


for the properties of the actions that are to
be localized

12-6 Windchill Customizer’s Guide


Possible
Parameter Default Value values Req? Description

renderType PDM No Default:


http://<host>/<webapp>
General:
http://<host>/<webapp><command.meth
od>
General with context:
http://<host>/<webapp><command.meth
od>?oid=...
PDM: url generated by
URLactionDelegate; used for template
processing

uicomponent No References entry n roleaccessprefs.xml


(uic.name) to specify role-based access.

preloadJS No The javascript function executed


executed before a wizard step is loaded or
displayed.

postloadJS No The javascript function is executed after a


wizard step is loaded into memory, but
before it is displayed to the user.

If necessary, place a <command> tag in the body of the <action> tag to define the
processing aspects of the action.
<command
class="com.ptc.windchill.enterprise.doc.forms.CreateDocFormProcess
or" method="execute" windowType="popup"
onClick="validateCreateLocation(event)"/>

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.

Adding Actions and Hooking Them Up in the UI 12-7


Possible Command Attributes

Possible
Parameter Default Value Values Req? Description

class n/a No The class to handle post

method n/a No The method in the class to execute and


handle post

url n/a No Used to override the generated url

onClick n/a No Specified an additional onclick


function to call. Useful for confirming
with the user whether to execute a
special action

windowType page New No New: like a popup, except includes a


no_content browser bar
normal no_content: no window action
page
popup normal: default, submit the form
wizard_step wizard_step: display the action as a
wizard step
page: display a new page
popup: create a non-modal popup
dialog, typically a wizard. Sets come
form of data

Possible NonSupportedType Attributes

Possible
Parameter Default Value Values Req? Description

value n/a Any object Yes This action will be disabled for the
types. It can object type/s mentioned in the
be comma "Possible values". Actions will be
separated. disabled in Third Level Navigation,
Row Level action. No filtering will be
done for MenuBar and Table Tool Bar
actions.

12-8 Windchill Customizer’s Guide


Possible SupportedType Attributes

Possible
Parameter Default Value Values Req? Description

value n/a Any object Yes This action will be enabled only for the
types. It can objecttype/s mentioned in the "Possible
be comma values". Actions will be enabled in
separated. Third Level Navigation, Row Level
action. No filtering will be done for
MenuBar and Table Tool Bar actions.

By specifying SupportedTypeAttribute or NonSupportedTypeAttribute,


ActionFramework will either enable or disable the Actions depending upon the
object types mentioned. This filtering will be applied only for Third Level
Navigation and Row Level Actions. Also this will be carried out before calling
any other Filtering ( Validation service ) class defined by application developers.
In short it is a UniversalFilter.
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>
</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>

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 section of the
Internationalization and Localization chapter on page 40-8.
The format for the entries in the rbinfo files for actions is:

Adding Actions and Hooking Them Up in the UI 12-9


<objecttype name>.<action name>.<purpose>.value=<value>

Element Possible Values Description

objecttype name all Corresponds to the name of the objecttype specified in the
actions.xml file.

action name all Corresponds to the name of the action specified in the actions.xml
file.

purpose title title: localizable text for the title bar if the action is for a wizard
description
description: the localizable text for the label of the action
tooltip
icon tooltip: the localizable text shown on mouse over of the action
morurlinfo icon: image file, relative to codebase/netmarkets/images
hotkey
moreurlinfo: parameters used to size the window for this action
hotkey: the alphanumeric key to trigger this action.

value all The actual value for the entry.

For example:
<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

icon and tooltip shown here:

12-10 Windchill Customizer’s Guide


title shown here:

icon and description shown here:

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" type="object"/>
<action name="list_copy" type="object"/>
<action name="fbpaste" type="object"/>
<action name="pasteAsCopy" type="saveas"/>
<action name="list_paste_sharing" type="folder"/>
<action name="list_delete" type="object"/>
<action name="CONTAINERMOVE" type="pdmObject"/>
<action name="PAGERELOADINGMULTICHECKOUT" type="folder"/>
<action name="WFADDTOWORKSPACE" type="folder"/>
<action name="separator" type="separator"/>
<action name="create" type="folder"/>
<action name="create_share_folder" type="folder"/>
<action name="create" type="document"/>
<action name="create_shared_doc" type="document"/>
<action name="createMulti" type="document"/>
<action name="createFromTemplateWizard" type="document"/>
<action name="createPartWizard" type="part"/>
<action name="createMultiPart" type="part"/>

Adding Actions and Hooking Them Up in the UI 12-11


<action name="add_link" type="bookmark"/>
<action name="create" type="problemReport"/>
<action name="create" type="changeRequest"/>
<action name="create" type="changeNotice"/>
<action name="SBUpdatePrj" type="sandbox"/>
<action name="separator" type="separator"/>
</model>

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.

Possible Model Attributes


Details about these parameters can also be found in the
codebase/config/actions/actionsmodels.dtd.

Parameter Default Value Possible values Req? Description

name n/a all Yes This is the name by which the action
model will be referenced

menufor n/a Any valid class No Specifies which action should be


name. highlighted by default. This is only
applicable if the model is used as a
third level nav bar

defaultActionNa First action in the Action name for Specifies which action should be
me model is used by one of the actions highlighted by default. This is only
default in the model. applicable if the model is used as a
third level navigation bar.

defaultActionTy First action in the Object type of one


pe model is used by of the actions in
default the model.

resourceBundle Class name for the resource bundle to


use for the properties of the action
models that are to be localized

Possible Action Attributes


Details about these parameters can also be found in the
codebase/config/actions/actionsmodels.dtd.

Parameter Default Value Possible values Req? Description

name n/a Name of any Yes This is the name of an action defined in
action defined in an actions.xml file
an actions.xml file

12-12 Windchill Customizer’s Guide


Parameter Default Value Possible values Req? Description

type n/a Name of any Yes This is the name of an objectype defined
objectype defined in an actions.xml file.
in an actions.xml
file

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.

Possible SubModel Attributes


Details about these parameters can also be found in the
codebase/config/actions/actionsmodels.dtd.

Parameter Default Value Possible Values Req? Description

name n/a Name of any action Yes This is the name of an action model
model defined in an defined in an actionmodels.xml file.
actionmodels.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 the section on UI Validation for details about the validation service, writing a
validator, and registering the validator for your action. See UI Validation on page
14-109 for more information.
Procedure - Setting a Custom Action Image Directory
You can set a custom action image directory by adding the following property in
their site.xconf:
<Property name="com.ptc.jca.customActionImageDir"
targetFile="codebase/wt.properties"
value="com/mycompany/images"/>

Where com/mycompany/images is the path releative to codebase to the custom


image directory. The image path for the value must be set relative to codebase,
images can not be accessed outside of codebase. For example the above path is
resolved to: codebase/com/mycompany/images.

Adding Actions and Hooking Them Up in the UI 12-13


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 12-9.
object.relatedItems.description.value=<U
class='mnemonic'>R</U>elated Objects

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 Tools Overview section in the Customizing HTML Clients Using the
Windchill JSP Framework chapter on page 11-40 for information on the Action
Report and the Action Models Report.

Customization Points
As mentioned earlier in Solution Elements section on page 12-2, 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

12-14 Windchill Customizer’s Guide


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 before yours
unless that is the intent.

Sample Code

Action Model - configurtion for a soft type


This is an example of a 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>

Adding Actions and Hooking Them Up in the UI 12-15


Where org.default.www.SampleChangeRequest is the Name of the soft type
entered in the Type Manager.

12-16 Windchill Customizer’s Guide


Tab Models

Objective
You want to change something in the header section of the page. Examples: Add
and remove tabs or sub tabs, Change logo, change other styles.

Background
The tabs and sub tabs rendered in the header area are actions in action lists just
like any other actions in the system. The action lists are being displayed by a
special tag that knows how to render them as tabs and sub tabs instead of
rendering them in any of the other formats found throughout the system. Adding
tabs and sub tabs is very much like adding any other action into the system, but
there are some additional special consideration.
The look and feel of the header and footer areas is controlled by CSS classes in
nmstyles.css. A detailed list of the styles used and a description of their purpose is
provided in this document in the Procedure - Changing the header or footer look
and feel section on page 12-22.

Scope/Applicability/Assumptions
• Assume you need to change the look and feel of Windchill to conform to your
company's branding.
• Assume you need to add a new tab or sub tab to the main navigation of the
product.
• Assume you need to remove an existing tab or sub tab from the main
navigation of the product.

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 12-2.
The management of RBINFO file customizations. For more information see,
Procedure - Localizing an action on page 12-9.

Adding Actions and Hooking Them Up in the UI 12-17


Solution Elements

Element Type Description

codebase\config\actions\ XML This file contains the action definitions for


navigation-actions.xml the actions that represent the tabs and sub
tabs in the Windchill system

codebase\config\actions\ XML This file contains the action model


nigation-actionModels.xml definitions used in the navigation.
Including the main tab list, the sub tab list,
the recent lists, and the header actions lists.

codebase\action.properties or rbinfo Preferences files


an rbinfo file.

codebase\netmarkets\css\ CSS This file contains the style classes used to


nmstyles.css create the look and feel of the Windchill
header and footer.

<mytab>/<list>.jsp JSP 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 a Main Tab


The process of adding a main tab consists of the following steps:
• Create an action in navigation-actions.xml
• Add your action to the main navigation action model in navigation-
actionModels.xml
• Create an entry in action.properties or an rbinfo file
• Create a new sub tab model for your tab in navigation-actionModels.xml
• Create a new stickiness Preference and load it into the Database
• Add a Sub Tab

Create an action in navigation-actions.xml


Create an action for your new tab in navigation-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>

12-18 Windchill Customizer’s Guide


Add your action to the main navigation action model in navigation-actionModels.xml
To get your main tab to show up you will need to add it to the action model for the
main tabs. My new tab is shown in bold below:
<!-- 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"/>
<action name="site" type="navigation"/>
</model>

Create an entry in action.properties or an rbinfo file


Create localization strings for your action in action.properties or your own rbInfo
file. For more information see, Procedure - Localizing an action on page 12-9.

Create a new sub tab model for your tab in navigation-actionModels.xml


Your new tab will need a sub tab model. In order for the navigation to find the
subtab model it must be named after the main tab that it belongs to. For sub tab
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 subtabs to your new action model. You must create at least one
sub tab whose name and type match the defaults specified in the action model tag.

Create a new stickiness Preference and load it into the Database


Your preferences should be named <tabName>stickyAction and
<tabName>StickyType. So for this example they are “mytabStickyAction” and
“mytabStickyType”.
Here is a complete xml examples for the two preferences for mytab.
<?xml version="1.0"?><!DOCTYPE NmLoader SYSTEM "standardX10.dtd">
<NmLoader>
<csvPreferenceDefinition
handler="wt.preference.LoadPreference.createPreferenceDefinition">
<csvname>mytabStickyAction</csvname>
<csvvisibility>HIDDEN</csvvisibility>
<csvcategoryName>DISPLAY_CATEGORY</csvcategoryName>
<csvdisplayName>wt.preference.preferenceResource:UNASSIGNED_WIT

Adding Actions and Hooking Them Up in the UI 12-19


H_NAME</csvdisplayName>
<csvdescription>wt.preference.preferenceResource:UNASSIGNED_WIT
H_NAME</csvdescription>
<csvlongDescription>wt.preference.preferenceResource:UNASSIGNED
_WITH_NAME</csvlongDescription>
<csvdefaultValue/>
<csvhandler>com.ptc.windchill.enterprise.preference.handler.Str
ingPreferenceValueHandler:</csvhandler>
</csvPreferenceDefinition>

<csvLinkPreferenceClientDefinition
handler="wt.preference.LoadPreference.setClientDefinitionLink">
<csvname>mytabStickyAction</csvname>
<csvclientName>WINDCHILL</csvclientName>
</csvLinkPreferenceClientDefinition>

<csvPreferenceDefinition
handler="wt.preference.LoadPreference.createPreferenceDefinition">
<csvname>mytabStickyOid</csvname>
<csvvisibility>HIDDEN</csvvisibility>
<csvcategoryName>DISPLAY_CATEGORY</csvcategoryName>
<csvdisplayName>wt.preference.preferenceResource:UNASSIGNED_WIT
H_NAME</csvdisplayName>
<csvdescription>wt.preference.preferenceResource:UNASSIGNED_WIT
H_NAME</csvdescription>
<csvlongDescription>wt.preference.preferenceResource:UNASSIGNED
_WITH_NAME</csvlongDescription>
<csvdefaultValue/>
<csvhandler>com.ptc.windchill.enterprise.preference.handler.Str
ingPreferenceValueHandler:</csvhandler>
</csvPreferenceDefinition>

<csvLinkPreferenceClientDefinition
handler="wt.preference.LoadPreference.setClientDefinitionLink">
<csvname>homeStickyOid</csvname>
<csvclientName>WINDCHILL</csvclientName>
</csvLinkPreferenceClientDefinition>
</NmLoader>

Add a Sub Tab


This step consists of multiple sub steps and can be repeated as many times as
needed. The process of adding a main tab consists of the following steps:
• Create the JSP
• Create an action in navigation-actions.xml
• Create an entry in action.properties or an rbinfo file
• Add your action to the action list in navigation-actionModels.xml

Create the JSP


In order to ensure that the correct main tab is selected properly, you must create
your JSP in a package named after that tab. In our example I will create my list.jsp
in the following path: codebase\netmarkets\jsp\mytab\list.jsp

12-20 Windchill Customizer’s Guide


This will ensure that mytab is selected when the user is viewing this JSP.
Example JSP content:
<!-- Import the navigationRB file that contains the constant for
the page title. -->
<%@page import="com.ptc.core.ui.navigationRB" %>

<!-- Set a request attribute to tell the navigation infrastructure


the title constant -->
<!-- OPTIONAL, the default is "Windchill" -->
<!-- This must be done before including begin.jspf -->
<%request.setAttribute("browserWinTitleConst",
navigationRB.WIN_TITLE_WORKSPACE_VIEW); %>

<!-- Set a request attribute to tell the navigation infrastructure


the help context -->
<!-- OPTIONAL, the default is that no help is displayed -->
<!-- This must be done before including begin.jspf -->
<%request.setAttribute("helpFileSelectorKey", "myTabListHelp"; %>

<!-- begin.jspf is required to draw the header -->


<%@ include file="/netmarkets/jsp/util/begin.jspf"%>

<!-- Your content should occur between begin.jspf and end.jspf -->
<H1>Hello World!</H1>

<!-- end.jspf is required to draw the footer -->


<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Create an action in navigation-actions.xml


Create an action for your new sub tab in navigation-actions.xml. You can create
any type of action for a sub tab. In this example we will create an action that maps
to the JSP created in the previous step.
<objecttype name="mytab" class="com.ptc.myTabClass">
<action name="list" >
<command windowType="page"/>
</action>

</objecttype>

Create an entry in action.properties or an rbinfo file


Create localization strings for your action in action.properties or your own rbInfo
file. For more details see Customizing Localizable Labels and Enumerations on
page 19-29.

Add your action to the action list in navigation-actionModels.xml


Add an entry to the action model that will add your action to
<model name="mytab navigation" defaultActionType="mytab"
defaultActionName="list">
<action name="list" type="mytab"/>

Adding Actions and Hooking Them Up in the UI 12-21


</model>

Customization Points
• Procedure - Changing the application logo
• Procedure - Changing the header or footer look and feel
• Procedure - Removing a Main Tab
• Procedure - Removing a Sub Tab
• Procedure - Context Bar

Procedure - Changing the application logo


The application logo is controlled by CSS. Depending on what your install set is, a
different CSS style is used. The following table lists the CSS style classes that are
used and when they are used. When in doubt you can always change all the CSS
classes to indicate the logo image you desire.

Style Class Install Set

pjlApplLogo Windchill ProjectLink standalone is


installed.

pdmlApplLogo Windchill PDMLink standalone is


installed.

proIApplLogo ProI is installed.

atcmApplLogo Arbortext Content Manager is


installed.

wncApplLogo Windchill ProjectLink and Windchill


PDMLink are installed together.

Procedure - Changing the header or footer look and feel


The look and feel of the header and footer is controlled by CSS style classes
defined in nmstyles.css. To change the look of the header update the appropriate
style class. Below is a list of all the style classes and a description of what they do.
For details on the logo image, please see the previous section Procedure -
Changing the application logo.

Style Class Description

pageHeader This style defines the image that


displays behind the logo and above the
tabs and subtabs.

12-22 Windchill Customizer’s Guide


Style Class Description

pageHeaderActions This style controls the look and feel of


the actions that are rendered above the
tabs in the page header.

headerBtns This style controls the look and feel of


the copy page button that is rendered
above the tabs in the page header.

nav1 This style controls the look and feel of


the first level tabs.

nav2 This style controls the look and feel of


the second level navigation or sub
tabs.

footer This style defines the look and feel of


the page footer, including the PTC
logo displayed in the footer.

Procedure - Removing a Main Tab


To remove a main tab simply remove the action for that tab from the main
navigation list in navigation-actionModels.xml.
<!-- 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"/>
<action name="site" type="navigation"/>
</model>

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>

Adding Actions and Hooking Them Up in the UI 12-23


Procedure - Removing a Sub Tab
To remove a sub tab simply remove the action for that sub tab from the sub tab
navigation list in navigation-actionModels.xml.
<model name="product navigation">
<action name="list" type="product"/>
<action name="separator" type="separator"/>
<action name="view" type="object"/>
<action name="listFiles" type="product"/>
<action name="listTeam" type="product"/>
<action name="listProduct" type="work"/>
<action name="changeMonitor" type="product"/>
<action name="view_forum" type="project"/>
<action name="MyWorkspace" type="product"/>
<action name="listTemplates" type="product"/>
<action name="listUtilities" type="product"/>
</model>

After removing the Change Monitor sub tab from the product sub tab list above.
The list will look like this:
<model name="product navigation">
<action name="list" type="product"/>
<action name="separator" type="separator"/>
<action name="view" type="object"/>
<action name="listFiles" type="product"/>
<action name="listTeam" type="product"/>
<action name="listProduct" type="work"/>
<action name="view_forum" type="project"/>
<action name="MyWorkspace" type="product"/>
<action name="listTemplates" type="product"/>
<action name="listUtilities" type="product"/>
</model>

Procedure - Context Bar


The context bar has the capability to be customized. Three parts exist in the
context bar. You have the container type followed by the container name. Then
you may have a bread crumb depending on your location. In the example shown
below, the bread crumb shows we are in a workspace and gives the name.
Depending on your location you may see actions to the left of the container. These
three parts of the context bar have the ability to be customized.
• Extend the ContextBarDelegate or a subclass of ContextBarDelegate
• Register MyContextBarDelegate

Extend the ContextBarDelegate or a subclass of ContextBarDelegate


The ContextBarDelegate is packaged under
com.ptc.windchill.enterprise.navigation.ContextBarDelegate. The first thing you
need to do is create a subclass of ContextBarDelegate or extend a subclass like
WTLibraryContextBarDelegate. Below is an example. Since we are extending
WTLibraryContextBarDelegate we have the choice of using super method instead

12-24 Windchill Customizer’s Guide


of having to override the three main methods. Otherwise, if ContextBarDelegate
is extended you will need to implement each of the three abstract methods.
Sample Code:
public class MyContextBarDelegate extends
WTLibraryContextBarDelegate {

@Override
protected NmHTMLActionModel getActionModel() throws WTException {
//Insert customized code
}

@Override
protected GUIComponentArray getLeftSideComponents() throws
WTException {
//Insert customized code
}

@Override
protected GUIComponentArray getRightSideComponents() throws
WTException {
//Insert customized code
}

Description of the three methods


• getActionModel() - This returns the action model to be shown in the context
bar
• getLeftSideComponents() - In most cases this currently returns the container
type, name and the breadcrumb.
• getRightSideComponents() - Components can be shown on the far right side
of the context bar. An example of this is when you are in the Project container
you will see a yellow/green/red indicator of the project status.

Register MyContextBarDelegate
As an example you can view the components.service.properties.xconf located
under: Windchill\codebase\com\ptc\core\components. Though the properties
should be added to a specific customized service.properties.xconf file.
In the above example you would write something like the following:
<Service context="default"
name="com.ptc.windchill.enterprise.navigation.ContextBarDelegate">
<Option requestor=" wt.inf.library.WTLibrary"
serviceClass="com.ptc.windchill.enterprise.org.navigation.MyContex
tBar" selector="cbNav" />
</Service>

Adding Actions and Hooking Them Up in the UI 12-25


Procedure - Display a custom object type's details page under your new tab
This section describes how to make a custom object's details page display on a
custom tab. This assumes the custom object has already been created and is called
com.mycompany.MyObject and the custom tab has already been added following
the instructions above and is called mytab.

Create a custom Navigation Delegate


The tab highlighting has the capability to be customized even further than the
examples given already above. Tab highlighting is controlled by classes that
extend the interface com.ptc.windchill.enterprise,navigation.NavigationDelegate.
In general it is not recommended to implement the interface directly. You should
subclass one of the existing out of the box implementations. Many of the
NavigationDelegates available out of the box can be found in the
com.ptc.windchill.enterprise.navigation package.
For this example you will need to create a custom subclass of
com.ptc.windchill.enterprise.WTContainedNavigationDelegate. This subclass
will be very simple as it only needs to override one method:
getSelectedTabFromContextObject()
Package com.mycompany;

import wt.util.WTException;
import
com.ptc.windchill.enterprise.navigation.WTContainedNavigationDeleg
ate;

public class MyObjectNavigationDelegate extends


WTContainedNavigationDelegate {

/**
* Creates a new instance of MyObjectNavigationDelegate
*/
public void MyObjectNavigationDelegate () {}

/**
* All MyObjects are displayed on mytab, so when this class is
* invoked, The tab from context object should always be mytab.
*/
protected final String getSelectedTabFromContextObject()
throws WTException
{
return "mytab";
}

There are other methods that you may wish to override but
getSelectedTabFromContextObject() is the only one required for this use case.

Register MyObjectNavigationDelegate
For some examples you can view the components.service.properties.xconf located
under: Windchill\codebase\com\ptc\core\components. Though the properties

12-26 Windchill Customizer’s Guide


should be added to a specific customized service.properties.xconf file or
site.xconf.
In the above example you would write something like the following:
<Service context="default"
name="com.ptc.windchill.en
terprise.navigation.NavigationDelegate">
<Option requestor="com.mycompany.MyObject "
serviceClass="com.mycompany.MyObjectNavigationDelegate"
selector="mainNav" />
</Service>

After registering you will need to run xconfmanager -p from a windchill shell and
restart the method server.
In some cases it may be necessary to increase the order of the delegate. Essentially
this increases the priority of the delegate and bumps it above other delegates.
Currently this is done in the out of the box product for the
VerstionableChangeItemNavigationDelegate like so:
<Service context="default"
name="com.ptc.windchill.enterprise.navigation.NavigationDelegate">
<Option order="1"
requestor="wt.change2.VersionableChangeItem"
serviceClass="com.ptc.windchill.enterprise.change2.navigatio
n.VersionableChangeItemNavigationDelegate"
selector="mainNav" />
</Service>

When order is used be sure to use an order higher than the delegate you are trying
override.

Limitations
In order to get your tab and sub tab to display and highlight correctly you must
follow the following conventions
• You must place your sub tab JSPs in a directory that exactly matches the
name you gave to your main tab in Procedure - Adding a Main Tab on page
12-18. 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 the Create a new sub tab model for your tab in navigation-
actionModels.xml section on page 12-19. 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".

Adding Actions and Hooking Them Up in the UI 12-27


Customizing 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 the Windchill Business Administrator's Guide for more details about profile-
and role-based visibility administration.

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

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:

12-28 Windchill Customizer’s Guide


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

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

Adding Actions and Hooking Them Up in the UI 12-29


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

12-30 Windchill Customizer’s Guide


Solution Elements
Element Type Description

*actions.xml XML 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.

Roleaccessprefs.xml 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/netmarkets/roleAcc
ess/.

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

Adding Actions and Hooking Them Up in the UI 12-31


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 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" guestEnabled="false"/>

See the section on the The uic Element on page 12-33 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

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

Caution: Follow best practices in backing up your XML files when


customizing them.

4. Restart the servlet engine and the method server.

12-32 Windchill Customizer’s Guide


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.

Default Possible
Parameter Value values Req? Description

name n/a string Y 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.

Order ? Non-negative? N The position of this UI component in the wizard. UI


Integer components with lower numbers are placed before
those with higher numbers.

Enabled true true | false N Whether or not this uicomponent will be shown in
the wizard and utilized by the system.

DefaultAll true true | false N The default visibility value for All Members.

DefaultManag true true | false N The default visibility value for Project Managers.
er 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.

DefaultGuest true true | false N 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.

Adding Actions and Hooking Them Up in the UI 12-33


Default Possible
Parameter Value values Req? Description

ManagerEnabl true true | false N Whether or not this uicomponent can affect the
ed manager role. Do not change this value in out-of-
the-box UICs. For customized UICs, you may
choose your own setting.

GuestEnabled true true | false N 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.

RunClass - Java class N The class on which runMethod exists


name

runMethod - Java method N The method to run when the UIAccess is changed.
name 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)
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 profile-
based 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 actions.xml with the UIComponent.


< oolean pe name="customization" >
<action name="list2" uicomponent="CUSTOMIZED_TAB">
<command windowType="page"/>
</action>

12-34 Windchill Customizer’s Guide


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 Customized Tab
40.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 the Procedure - Making an Action Available
to Visibility Administration section on page 12-32 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.

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 Folders - My New Label
31.constant=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"

Adding Actions and Hooking Them Up in the UI 12-35


defaultManager="true" defaultGuest="false"
managerEnabled="false" guestEnabled="false"

runClass="com.ptc.netmarkets.roleAccess.StandardNmRoleAccessServic
e"
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

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-of-the-box 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


• The Windchill Customizer's Guide - Managing Customizations on page 5-1

Other Related Windchill Documentation


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

12-36 Windchill Customizer’s Guide


Navigation Stickiness

Objective
Your users are not able to access tabs because the stickiness context is wrong.
Examples: Clicking on Library tab leads to the Product tab.

Background
Each tab maintains a sticky info in order to take the user back to the same page
they were on last time they visited the tab. It is possible for the stickiness info to
be corrupted somehow (e.g. Library tab having a sticky context object that is in a
Product results in the issue described in the problem statement – clicking on the
Library tab leads to the Product tab).
This issue should not occur during the normal course of navigating the UI, but it is
very easy to simulate the issue by manually manipulating the url.
One way to force this issue to occur is to visit the details page of an object in a
Product and add tab=library as a url parameter. This would cause the object in the
Product to be stored as the sticky object for the Library tab. Now clicking on the
Library tab will lead to the Product tab.

Solution
Clear the sticky info for the tab with the issue.

Prerequisite knowledge
To see or clear the sticky info for a particular user, you need to be logged in as the
user.

Note: Depending on which solutions are installed and the user’s role, you would
see a different set of tabs than what is shown in the screen shots.

Procedure – Viewing Current Sticky Info


Log in as the user whose sticky info should be cleared. Once you’ve visited a
particular tab, the sticky info will be in the session and you can see it by visiting
this url:
http://<machine>/<webApp>/netmarkets/jsp/components/stickiness.jsp

This will lead to a page that looks like this:

Adding Actions and Hooking Them Up in the UI 12-37


In the above example you can see that the sticky info for the Product tab is a
Product oid and the Discussions action (the Discussions sub tab).
Also note, you can see there is no sticky info in the current session for the Project
tab. This means either you haven’t visited the project tab in this session, or you
have just cleared the sticky info for the project tab. Once you’ve visited a tab
within the session, you’d see at least a sticky action. The sticky context oid is
optional and some sub tabs don’t have one. (e.g. the Products List)

Procedure – Clearing the Sticky Info for a Tab


Log in as the user whose sticky info should be cleared. Visit this url:
http://<machine>/<webApp>/netmarkets/jsp/components/stickiness.jsp

For example, if clicking on the Library tab leads to the Product tab, the Library tab
sticky info should be cleared. So click on the “clear library tab” hyperlink. (or
click on “clear sticky info for all tabs” if you don’t mind clearing out all the
stickiness info for that user)
Notice both sticky context oid and sticky action should be blank after you’ve
cleared the sticky info.

12-38 Windchill Customizer’s Guide


Use Search to “clear” sticky object
Log in as the user whose sticky info should be cleared. Search for an object in the
appropriate type of container and go to its details page to replace the corrupt
sticky info with new valid sticky info.
For example, if clicking on the Library tab leads to the Product tab, search for any
object that is in any library. Going to the details page of that object will highlight
the Library tab and save new sticky info for the Library tab, thus fixing the issue.

Additional Resources:
• Windchill Client Architecture Action Framework Overview on page 12-2

Adding Actions and Hooking Them Up in the UI 12-39


12-40 Windchill Customizer’s Guide
13
Gathering the Data for the UI

This chapter describes how to gather data to be used in the user interface.

Topic Page
Data Acquisition Configuration Properties .............................................. Page 13-2
Acquiring Data via Info*Engine .............................................................. Page 13-9
NmObject Utilities ................................................................................. Page 13-15

13-1
Data Acquisition Configuration Properties

Objective
You want to configure how data is retrieved for a Windchill Client Architecture
table, tree or property panel.

Background
This document describes how you can configure Windchill Client Architecture
components to retrieve and process data, without writing framework-specific Java
code.
Windchill Client Architecture allows you to configure a means to get your
backing component data, and then a way to configure how this data is post-
processed to extract the properties that will actually be shown in the UI. What this
means is that you have a lot of flexibility regarding the kind of data you retrieve,
as long as it can be post-processed by the infrastructure.

Scope/Applicability/Assumptions
Specific considerations for each type of Windchill Client Architecture component
are covered in their respective sections within the Windchill Customizer’s Guide.

Intended Outcome
An understanding of what options are available to you to configure data
acquisition for a Windchill Client Architecture component.

Solution
Use the getModel, describeColumn and describeProperty tags to configure a data
source for your Windchill Client Architecture component.

Prerequisite knowledge
To apply this knowledge you need to have an understanding of the following:
• JSP expression language (EL)
• JSP tags
• Windchill Client Architecture overview

13-2 Windchill Customizer’s Guide


Solution Elements
Element Type Description

getModel tag JSP tag Configures a MethodServer data source

getIeModel tag JSP tag Configures an Info*Engine data source

describeColumn tag JSP tag Configures a column to display in a


table

describeProperty tag JSP tag Configures a property to display in a


property panel. Supports the same API
as describeColumn.

targetObject attribute JSP tag attribute A tag attribute that allows you to change
the "backing object"

Property report Reporting tool A reporting tool to find what existing


Windchill Client Architecture extension
points are in the system

batch tag JSP tag Batches together multiple getModel


calls

Procedure - Deciding between getModel and getIeModel


There are two ways to get data for a Windchill Client Architecture table:
• Invoke a Java API on the MethodServer using getModel
• Invoke an Info*Engine task using getIeModel
Your choice will often be dictated by some pre-existing API that you are trying to
integrate into the page. If that is not the case, then consider the following.
getModel will:
• Enable coding to Persistable and other plug and play interfaces
• Facilitate unit testing and more POJO-style development
getIeModel will:
• Facilitate federation and customization
• Limit the attributes available to you to whatever is specifically requested,
rather than the entire java object. This can either be a good or bad thing,
depending on the use case
• Require the definition of logical attributes to return associations
If you choose to use the getModel tag, then refer to the Constructing and
Rendering a Table Using the JSP Framework section on page 14-23 for details on
how it is configured.

Gathering the Data for the UI 13-3


If you choose to use the getIeModel tag, then refer to the Acquiring Data via
Info*Engine section on page 13-9 for more information.

Procedure - Extracting properties from data elements when using the getModel tag
If you configured your component using the getModel tag, you still need to tell
the Windchill Client Architecture framework how to extract each property that
will be displayed in the component from the resulting data elements. In many
cases Windchill Client Architecture can automatically figure out how to extract
these properties:
• Bean properties: If you are using an API that returns a Java bean, and you
intend to display a property in the UI that corresponds to a property of the
bean, the infrastructure can handle this automatically.
• Soft attributes: Windchill Client Architecture knows how to automatically
find soft attributes for your business objects, even if the objects you returned
do not know about the soft attributes.
• Existing Windchill Client Architecture extensions: Windchill Client
Architecture already has a rich set of logical "properties" which can augment
the business object or Info*Engine Element that you return.

Do I need to return Persistables?


Your backing APIs and tasks do not need to return Persistable objects. However,
in order for non-Persistable objects to be selectable in the interface some
additional configuration and/or extension may be necessary.

Bean properties
Windchill Client Architecture handles Java beans in the same way that the JSP EL
does, meaning 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 with a column like the following:
<jca:describeColumn id="foo" .../>

Then the infrastructure will look for a "getFoo" method on each result object that
it processes when it executes your getModel API. If the method isn't found, then
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 bean. In fact, anything you can do
with the JSP EL can also be accomplished with Windchill Client Architecture. For
example, you can use the dot notation to refer to nested properties. In addition,
Windchill Client Architecture 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 Windchill Client
Architecture uses to process bean properties.

13-4 Windchill Customizer’s Guide


More examples:
• 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")

What about Info*Engine?


The bean-style property access only works for getModel calls. Info*Engine calls
that need to retrieve associated properties should instead define logical attributes
for those properties.

targetObject
targetObject provides a complementary approach to bean-style notation to access
nested properties of objects. It is described in more detail below.

Soft attributes
Windchill Client Architecture can automatically look up the soft attributes for
your Typed business objects if you ask it to. If you have a soft attribute on your
part named "baz", and have added a column descriptor as follows:
<jca:describeColumn id="baz" .../>

Windchill Client Architecture will fail to find a bean property for "baz" on your
business object, but will not just give up. It will next try to see if "baz" could be a
soft attribute of the object. There are two ways that Windchill Client Architecture
can determine this:
• If "baz" corresponds to a logical attribute of the object type.
• If the component id is a soft attribute external form, such as IBA|baz
If Windchill Client Architecture is able to find a soft attribute definition for the
object, then it will go and fetch the object's value.
• Retrieval of soft attributes can be expensive, so if Windchill Client
Architecture determines a soft attribute retrieval is in order, it will get the soft
attributes for all objects in the data set at once.

Batch soft attributes


The soft typing infrastructure provides some convenience attributes that you can
include in table definition to get a collection of related soft attributes. For
example, the ALL_SOFT_ATTRIBUTES attribute will, as the name implies,
retrieve any soft attribute that is visible on the object. To use this in a table
definition, do the following:
<describeColumn id="ALL_SOFT_ATTRIBUTES" .../>

Gathering the Data for the UI 13-5


The out-of-the-box Windchill Client Architecture rendering infrastructure
recognizes batch attributes and knows to expand out the resulting attribute set into
individual columns per attribute.

Existing Windchill Client Architecture extensions


Beyond simple bean-style property retrieval and soft typing, Windchill Client
Architecture also provides extensions that handle the many properties that need
additional processing beyond what the core business object model provides. Some
of these properties may still correspond to an underlying property of the business
object, and some may in fact be doing their own separate data acquisition to add in
data that the core business object doesn't know about.
Refer to the "Finding existing Windchill Client Architecture extensions"
procedure below for more information on discovering what extension points exist
in the system.

Procedure - Using the targetObject configuration to change the "backing object" for a
component
targetObject allows the developer to manipulate the result set from a backing API
call, so that the infrastructure treats a property of each result object as the "row"
object rather than the result object itself. For example the following configuration
tells the infrastructure to use the "foo" property of the result object as the backing
object for the "bar" row:
<jca:describeColumn id="bar" targetObject="foo" .../>

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 configuration calls getFoo().getBar() on the row object returned by
your API:
<jca:describeColumn id="foo.bar" .../>

Rule of thumb: Use targetObject with Windchill Client Architecture extension classes
The difference between the foo.bar and targetObject="foo" approaches is that
when you configure target object, the infrastructure treats the target object as if it
were the object returned by your backing API. When you use the bean-style
property configuration, the backing object for the API remains the row object that
the Windchill Client Architecture infrastructure interacts with. This difference
becomes significant when using Windchill Client Architecture extension classes
in particular -- these classes may base functionality on what they think the current
row object is, not just on what the specific property is that was requested in the
component configuration. For this reason, it is generally a good practice to use the
targetObject property when reusing a Windchill Client Architecture extension
class (typically a DataUtility implementation).

13-6 Windchill Customizer’s Guide


This difference is also significant when implementing a selectable component.
With targetObject, the selected object will be the nested object, whereas if using
bean properties, the selected object will still be the data element returned by the
getModel API.

Where can I use targetObject?


You can use target object at both the component level, in which case it applies to
all columns or properties, or on specific columns or properties within the
component.

What object types can targetObject return?


The targetObject can be any of the following types:
• Persistable
• WTReference
• ObjectIdentifier
• NmObject
• NmOid
• NmSimpleOid

Can targetObject be used with non-Persistables?


You can use target object to point to an object that is not a Persistable by wrapping
the object in an NmSimpleOid. Refer to the NmObject Utilities section on page
13-15 for more information.

Procedure - Finding existing Windchill Client Architecture extensions


Windchill Client Architecture extension points are implementations of the
DataUtility interface. Windchill is installed with a reporting tool that helps you
find out what data utilities are available to you. This tool reports on all the
available ids that you can add to your table configurations, as well as what the
DataUtility implementation class is for that id. You can then refer to the JavaDoc
for that DataUtility in order find out more details on what it does.
The reporting tool can be accessed at:
http://<HOSTNAME>/<WEBAPP>/netmarkets/jsp/property/propertyReport.
jsp

For information on how to implement your own Windchill Client Architecture


extensions, refer to the Data Acquisition Configuration Properties section on page
13-2 for more information.

Gathering the Data for the UI 13-7


Procedure - Batching getModel calls
You can use the batch tag to retrieve multiple models at once. This cuts down on
interprocess communication between the servlet container and method server. To
use the batch tag you need to include the wc tag library as follows:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/core"
prefix="wc"%>

The following shows you could use the batch tag:


<wc:batch>
<jca:getModel ..../>
<jca:getModel ..../>
</wc:batch>

Customization Points
Refer to the Constructing and Rendering a Table Using the JSP Framework
section on page 14-23 and the Windchill Client Architecture Tree section on page
14-64 for details on the various tag customization points discussed in this
document

Sample Code
Refer to the Constructing and Rendering a Table Using the JSP Framework
section on page 14-23 and the Windchill Client Architecture Tree section on page
14-64 for more code samples.

13-8 Windchill Customizer’s Guide


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
Windchill Client Architecture provides a getIeModel tag that works similarly to
the getModel tag, but that retrieves its data from Info*Engine. The tag interacts
with other Windchill Client Architecture tags just as getModel does. The
difference is that instead of specifying a service method, one specifies an “action”
that maps to an Info*Engine task.

Intended Outcome
A Windchill Client Architecture table that has its data backed by an Info*Engine
task

Solution
Use the Windchill Client Architecture getIeModel tag to configure a Windchill
Client Architecture table component

Prerequisite knowledge
Readers should be familiar with Info*Engine as well as with the basic Windchill
Client Architecture data acquisition concepts.

Solution Elements

Element Type Description

getIeModel tag JSP tag Configures the task to use to get the data

ie tag library JSP tag library The Info*Engine tag library

Param tag JSP tag A tag from the ie tag library that supplies
parameters to the getIeModel tag

Procedure – Implementing the getIeModel tag


The getIeModel tag is used in a JSP page in the same way that the getModel tag is.
The only required configuration for the getIeModel tag (beyond descriptor and
var) is an “action” that says what task should be executed to get the model data.
For example, the following code snippet demonstrates the use of the “dca-Search”

Gathering the Data for the UI 13-9


task, where the resulting model is put in the scoped “tableModel” variable, and the
relevant table descriptor is supplied by the “tableDescriptor” scoped variable:
<jca:getIeModel var="tableModel" descriptor="${tableDescriptor}"
action="dca-search"/>

getIeModel is implemented by an Info*Engine-based tag handler. This means it


works like the tags included in the Info*Engine JSP library, and can interact with
them. Since it is an Info*Engine tag, getIeModel uses the page VDB and is
embeddable. In addition, you supply parameters to the tag using Info*Engine’s
“param” tag. To use the param tag, you need to include the Info*Engine tag
library in your page, as follows:
<%@ taglib uri="http://www.ptc.com/infoengine/taglib/core"
prefix="ie"%>

The param tag is nested in your getIeModel tag declaration as follows:


<jca:getIeModel var="tableModel" descriptor="${tableDescriptor}"
action="dca-search">
<ie:param name="GROUP_OUT" data="groupOutName"/>
</jca:getIeModel>

Configuring task selection


Internally, the getIeModel tag uses Info*Engine’s Dispatch-Tasks webject to look
up the task implementation for the action task name that is configured in the JSP.
getIeModel exposes several parameters which are passed on to Dispatch-Tasks
that it uses to choose the right implementation task. Refer to the Dispatch-Tasks
documentation in the Info*Engine User’s Guide.
<jca:getIeModel var="tableModel" descriptor="${tableDescriptor}"
action="dca-search">
<!--These parameters are used by Dispatch-Tasks-->
<ie:param name="GROUP_IN" data="groupInName"/>
<ie:param name="TYPE" data="typeName"/>
<ie:param name="CLIMBER" data="climberName"/>
</jca:getIeModel>

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 page’s URL ends with something like
“/somePage.jsp?foo=bar”, then in your task implementation,
“@FORM[]foo[]” will map to “bar”.
If you want to explicitly configure the form data for your task, then you can do
this by creating the form group in your jsp page (using Info*Engine’s JSP tag
library), and then specifying the name of the group as an attribute of the
getIeModel tag, as follows:
<jca:getIeModel var="tableModel" descriptor="${tableDescriptor}"
form="formGroupName"
action="dca-search">

13-10 Windchill Customizer’s Guide


Using configurable table views
The getIeModel tag fully supports configurable table views. Sort and filter criteria
from the current table view are passed along to your task as described in the
following section.

Using information supplied to your task by 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
• PAGE_OFFSET: The first result row to return from the paging session, if any
• PAGING_SESSION_ID: The current paging session id, if any

Note: Most of these parameter names can be reconfigured to some other name
using ie:params. See the Customization Points section below for details.

Customization Points

getIeModel attributes
The following are attributes of the getIeModel tag that can be customized:

Parameter Default Value Possible Values Req? Description

action None Any valid task name Yes The name of the task to execute

form The current Name of a valid group No A group that contains form data for
request in the page VDB the task
parameters

Gathering the Data for the UI 13-11


ie:param customization points
The following are all parameters that can be specified using the <ie:param> tag:

Parameter Default Value Possible Values Req? Description

GROUP_OUT output Any No The name of the resulting group

GROUP_IN None Any No The name of the group in to supply


to Dispatch-Tasks

TYPE None Any No The name of the type to supply to


Dispatch-Tasks

CLIMBER None Any No The name of the climber to supply


to Dispatch-Tasks

ATTRIBUTE_P “ATTRIBUTE” Any No The name of the attribute to put the


ARAM_NAME requested attribute list in

SORTBY_PAR “SORTBY” Any No The name of the attribute to put the


AM_NAME sort criteria in

SORTED_PAR “SORTED” Any No The name of the attribute to put the


AM_NAME sort direction criteria in

WHERE_PARA “WHERE” Any No The name of the attribute to put the


M_NAME filter criteria in

TYPE_PARAM “TYPE” Any No The name of the attribute to put the


_NAME type criteria in

VERSION_PAR “VERSION” Any No The name of the attribute to put the


AM_NAME version criterion in

ITERATION_P “ITERATION” Any No The name of the attribute to put the


ARAM_NAME iteration criterion in

ATTRIBUTE_T “ATTRIBUTE_ Any No The name of the attribute to put the


YPE_CONTEX TYPE_CONTE attribute type context criterion in
T_PARAM_NA XT”
ME

PAGE_LIMIT_ “PAGE_LIMIT” Any No The name of the attribute to put the


PARAM_NAM page limit info in
E

PAGE_OFFSET “PAGE_OFFSE Any No The name of the attribute to put the


_PARAM_NA T” page offset info in
ME

Limitations
Currently there is no Info*Engine support for trees.

13-12 Windchill Customizer’s Guide


Sample Code
The following JSP page demonstrates how a simple search page could be
constructed, given a backing task name “demo-Search”. The page submits back to
itself, supplying the TYPE and WHERE parameters to the backing task.
<%@ include file="/netmarkets/jsp/util/begin.jspf"%>

<%@ taglib uri=http://www.ptc.com/windchill/taglib/components


prefix="jca"%>
<%@ taglib uri=http://www.ptc.com/infoengine/taglib/core
prefix="ie"%>

<h2>Test Search</h2>

<table>
<tr>
<th scope="row" align="right">Type:</th>
<td>
<input type="text" name="TYPE" value="${param.TYPE}"/>
</td>
</tr>
<tr>
<th scope="row" align="right">Additional criteria:</th>
<td>
<input type="text" name="WHERE" value="${param.WHERE}"/>
</td>
</tr>
<tr>
<td colspan="2" align="right"><input type="submit"
value="Search"/></td>
</tr>
</table>

<p>

<jca:describeTable var="tableDescriptor" id="searchTable"


label="Search Results">
<jca:describeColumn id="name"/>
<jca:describeColumn id="number"/>
<jca:describeColumn id="version"/>
</jca:describeTable>

<jca:getIeModel var="tableModel" descriptor="${tableDescriptor}"


action="demo-Search"/>

<jca:renderTable model="${tableModel}"/>

<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Examples of Usage in Windchill Code


Windchill search uses getIeModel.

Gathering the Data for the UI 13-13


Additional Resources

Related Documentation
• Windchill Adapter Guide (Info*Engine)

13-14 Windchill Customizer’s Guide


NmObject Utilities

Objective
You need to give each row in a Windchill Client Architecture table or tree a
unique identifier, and a persisted object identifier is either inappropriate or
unavailable.

Background
Left to their own devices, Windchill Client Architecture components assume that
each row object that they are processing is a Windchill Persistable object.
Components use the object identifier from the Persistable as a way to uniquely
identify the object for selection and hyperlinks.
If you run into a situation where the data returned by your query is not a
Persistable object, or the data does not map to a Persistable in an obvious way,
then you can implement an NmObjectUtility to provide the infrastructure a way to
uniquely identify your objects.
targetObject is preferable to NmObjectUtility
If the row objects expose an API that returns a supported object type, then you do
not need to write an NmObjectUtility. In this case, you can use the targetObject
configuration at the table and/or column level to tell the infrastructure what
property to use as the backing object for the row. The supported object types
along with additional information are documented in the Data Acquisition
Configuration Properties section on page 13-2.
If it is possible to modify the row objects to expose an API for targetObject, this
approach is considered a better practice than writing an NmObjectUtility, as it
means you have fewer dependencies on framework-specific code.

Intended Outcome
An implementation of the NmObjectUtility interface

Solution
Implementing an NmObjectUtility

Prerequisite knowledge
You need to have an understanding of the following:
• Windchill application context (“service.properties”)
• Windchill Client Architecture Overview
• Configuring Data Acquisition
• NmObjects Overview

Gathering the Data for the UI 13-15


Solution Elements
Element Type Description

NmObjectUtility Interface The NmObjectUtility interface that you


will implement

DefaultNmObjectUtilit Class The default implementation of


y NmObjectUtility that you may extend

An xconf file Configuration The file in which you will register your
file new NmObjectUtility

Procedure – Implementing an NmObjectUtility


The NmObjectUtility interface has two methods: getNmObject() and
getTargetObject(). Your customization should only deal with the getNmObject()
method. The getTargetObject() method is unsupported and you should only
provide a no-op implementation of it.
The getNmObject() method must create an instance of NmObject. The interesting
part of the NmObject is its NmOid. An NmOid points to a persistent object, and
its subclass NmSimpleOid points to an unpersisted one.

Constructing an NmObject for a persisted object


To construct an NmObject for a persisted object, you must obtain a Persistable,
WTReference, or ObjectIdentifier for that object. Once you have the identifier,
you use it to construct an NmOid and subsequently an NmObject.
//Construct an NmObject from a Persistable
public NmObject getNmObject(Object datum, ModelContext mc) {
//getPersistableFromDatum is your method to find
//the Persistable object
Persistable p = getPersistableFromDatum(datum);
NmOid oid = new NmOid(p);
NmObject result = new NmObject();
result.setOid(oid);
return result;
}

Constructing an NmObject for a non-persisted object


To construct an NmObject for a non-persisted object, you must create a unique
String key for the object. Once you have the key, you use it to construct an
NmSimpleOid and subsequently an NmObject.
//Construct an NmObject from a Persistable
public NmObject getNmObject(Object datum, ModelContext mc) {
//getStringKeyFromDatum is your method to find
//the unique String key
String key = getStringKeyFromDatum (datum);
NmSimpleOid oid = new NmSimpleOid();
oid.setInternalName(key);
NmObject result = new NmObject();

13-16 Windchill Customizer’s Guide


result.setOid(oid);
return result;
}

Registering your NmObjectUtility


Once you have written your NmObjectUtility, you need to let the Windchill Client
Architecture infrastructure know about it. To do this, you add an application
context mapping for the NmObjectUtility, where the table id that you want the
NmObjectUtility to be used for is the application context selector. For example, if
the table id is “customTable”, then the xconf entry would look as follows:
<Service
name="com.ptc.core.components.descriptor.NmObjectUtility">
<Option serviceClass="com.myco.MyCoNmObjectUtility"
selector="customTable"
requestor="java.lang.Object"
cardinality="singleton"/>
</Service>

After adding the xconf entry, be sure to run the xconfmanager to propagate the
change to your installation.

NmCommandBean
Object that 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
Contains a number of helper APIs:
• 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.
See javadoc for more info api usages.

Gathering the Data for the UI 13-17


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.

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. Often it is used 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.

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 project's folders
page. Note that the $, ^, and !* are reserved separator characters.
"folder$list$OR:wt.projmgmt.admin.Project2:2343$OR:wt.folder.Su
bFolder:7195^VR:wt.doc.WTDocument:18913!*

13-18 Windchill Customizer’s Guide


14
Presenting Information in the
UI

This chapter describes how to customize information that is displayed in the user
interface.

Topic Page
Attribute Handling.............................................................................................14-2
Soft Attributes and SCAs ................................................................................14-21
Constructing and Rendering a Table Using the JSP Framework ....................14-23
Windchill Client Architecture Tree.................................................................14-64
Adding Custom Modeled Attributes to all Table Views.................................14-91
Attribute Tables...............................................................................................14-92
Generating the Name Attribute Server............................................................14-97
Partial Activation of JSCA ............................................................................14-102
Icon Delegates ...............................................................................................14-103
UI Validation.................................................................................................14-109
Customizing the Find Number Field .............................................................14-152

14-1
Attribute Handling

Objective
You want to render a UI component for an attribute of a Windchill object to either
capture the user’s input during Create/Edit or to display the existing value of that
attribute.

Background
In a Windchill client application, attributes of Windchill objects are rendered in 2
modes – the ‘input’ mode for Create and Edit and the ‘view’ mode (on the
Information pages, Tables, etc). The data-type of these attributes is restricted to
the Windchill supported data-types exposed in the Information Modeler and the
Attribute Manager. Standard data acquisition, translation, rendering and form
processing mechanisms are required to maintain consistent attribute handling
behavior across all client applications. The consistency is achieved by using the
JCA framework. This framework provides re-usable components for building the
UI components to represent attributes, from the server-side objects that represent
them. The framework also provides extension points for customization via the
ability to override the standard data-translation and rendering behavior. This
document describes the best practices for creating and rendering a HTML GUI
component to represent a Windchill attribute.
A data utility is used to create a GUI component for an attribute. The data used to
create this GUI component is a combination of the attribute and constraint
definitions, and the configurations listed in the Customization Points section on
page 14-12. The renderer for the GUI component generates the HTML for
rendering the component.
The Property Panel section on page 11-26 and the Constructing and Rendering a
Table Using the JSP Framework on page 14-23 describe how to configure an
attribute for being rendered in the client.
The GUI components and their renderers can also be used to represent attributes
that are not Windchill attributes like drawing a simple check-box on a page to
capture some input from the user.
GUI components can be simple components such as a text-box or composite GUI
components built using the simple components, like a component that uses a text-
box and 2 combo-boxes, as shown below:
Simple GUI component:

14-2 Windchill Customizer’s Guide


Composite GUI component:

The components generated by this framework also have some built-in client-side
validations, based on the constraint definitions and the configurations.

Scope/Applicability/Assumptions

Applicability
This practice should be followed when developing clients that need to display the
following attributes:
• Attributes whose type is a valid Windchill soft attribute type.
– Boolean
– Integer
– Floating point number
– Floating point number with Units
– String
– Date & Time
– wt.fc.EnumeratedType
– URL
– WTOrgRef: At this time, the framework has support to display the value
of these types of attributes, but does not support the input/editing of those
values. The Windchill Product Structure Explorer provides the necessary
support to input values for these attributes.
– Classification Node
• Attributes whose type is any of the following native Java types:
– primitive boolean, java.lang.Boolean
– primitive byte, short, integer, long, java.lang.Byte, java.lang.Short,
java.lang.Integer, java.lang.Long
– primitive float, double, java.lang.Float, java.lang.Double
– java.lang.String
– java.sql.Timestamp
• Special Windchill attributes

Presenting Information in the UI 14-3


– Name
– Number
– Location
– Revision label
– Principal
– Status (work in progress state)
– Lifecycle state
– Lifecycle template
– Team template

Intended Outcome
Consistent attribute handling behavior (rendering, validation wherever applicable
and attribute processing) on any Windchill client that uses a given Windchill
attribute in a given mode.

Solution
Use the Windchill client framework for rendering attributes in a Windchill client
application.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• The Windchill soft attributes, Attribute Manager, Type Manager, constraints
that can be defined on attributes in the Type Manager.
• The InfoModeler and constraints that can be defined on attributes in the
InfoModeler.
• Basic knowledge of the Windchill Client Architecture
• The Windchill JSP ‘describeColumn’ , ‘describeProperty’ tags
• AllClients.xml and Windchill preferences for customizations
• The management of RBINFO file customizations

14-4 Windchill Customizer’s Guide


Solution Elements

Element Type Description

Windchill Info Modeler Used to define the modeled attributes of


a Windchill class and to define the
constraints on each of those attributes.

Windchill Attribute Manager Used to define the instance based


and Type Manager attributes and the attribute constraints
using this tool.

Object Initialization Rules Used to define rules and constraints on


Administrator objects.

Windchill Preference Used to customize some of the attribute


Manager rendering behavior that needs to be
applied to all attributes across all clients.

AllClients.xml Xml file Used to customize some of the attribute


rendering behavior that needs to be
applied to a specific attribute across all
clients.

Jsp files JSP Used to customize some of the attribute


rendering behavior that needs to be
applied to a specific attribute in a
specific client.

componentRB.rbInfo rbInfo

<your_file>.rbInfo rbInfo Contains localized strings, can be


defined separately for each module.

Data utility delegate java Implements the methods to create


concrete GUI component objects for a
given attribute.

service.properties (xconf) properties Configuration point for mapping


files components to data utilities to override
default GUI component creation
behavior

GUI Component java The model for a GUI component class

GUI Component Renderer java Implements the rendering of a GUI


component

components.service.properti properties Configuration point for mapping GUI


es components to renderers to override
default rendering behavior

Presenting Information in the UI 14-5


Element Type Description

Form processing delegates java The classes that process the form data of
the OOTB GUI components.

Determining the attribute handling approach


Attribute is a Windchill supported type, and no custom behavior is required (only
the standard out-of-the-box attribute handling behavior is required)
Configure the attribute as described the Using OOTB Attribute Handling
Behavior section on page 14-8.

Attribute type is not a Windchill JCA framework supported type


If the type of your attribute is not one of the Windchill Client Architecture
framework supported types listed in the Scope/Applicability/Assumptions section
on page 14-3, or you need to augment/alter the data returned by a core API,
implement a data utility as explained below in the Implementing a Data Utility
section on page 14-8 to create a GUI component for that attribute.
Example:
The 9.0 Windchill Client Architecture does not support the handling of attributes
of type java.sql.Date out-of-the-box. If you want to render an attribute of this type
in a JCA client, you may need to implement a DataUtility that knows how to
create a GUIComponent for this type.
Object getDataValue(String component_id, Object datum,
ModelContext mc) throws WTException
{
……

Object rawValue = getAttributeValue(component, datum, mc);


DateDisplayComponent gui = new DateDisplayComponent(label);
if (rawVal != null && rawVal instanceof Date) {
gui.setValue(new Timestamp(rawVal.getTime()));
}
……

return gui;
}

If custom UI behavior is required for the attribute, you are familiar with the JCA
GuiComponent that represents that attribute and the data held in this object is
sufficient to provide the rendering behavior you require, implement a custom
Renderer for rendering the GUI component outlined in the Implementing a GUI
component renderer section on page 14-10.
Example:

14-6 Windchill Customizer’s Guide


The OOTB Renderer implementation for rendering a GUI component for date &
time renders the component like this:

Suppose you want the component to be rendered as:

In this case you would write a custom renderer for the DateInputComponent.
If the desired behavior cannot be achieved by just implementing a Renderer, the
next alternative is to implement a GUI component for the attribute as outlined in
Implementing a GUI component section on page 14-11.
You may need to create a special form processing delegate if you are trying to use
custom GUI components. See the Wizard Processing section on page 15-19 and
Building Wizards to Create a Single Object on page 15-38 for information on how
to do this.

Attribute Type is Windchill supported type, but you need to modify the way it is rendered
Same as Attribute type is not a Windchill JCA framework supported type on page
14-6 except that you may need to implement a data utility only if you are creating
a custom GUI component.

Data needs to come from a different source


You may be able to do this just by configuration using the target object as
described in Data Acquisition Configuration Properties on page 13-2. If that does
not meet your requirements, you can implement a data utility that knows how to
interpret the data and create a GUI component from it.

Need to post-process the raw data returned by the core APIs before displaying it
Same as Attribute type is not a Windchill JCA framework supported type on page
14-6. You can post-process the raw data in the data utility before using it to create
the GUI component.
You may need to create a special form processing delegate if you are planning to
use custom GUI components. For example, you may want to generate a hidden

Presenting Information in the UI 14-7


field to store some data that may be required in conjunction with the data from the
GUI component in order to derive the actual value for an attribute. The generic
OOTB form processors will not have any knowledge of this specific hidden field
that was part of your custom GUI component and how it needs to be processed. In
this case, you may need to write your own form processing delegate that knows
how to process this field.

Using OOTB Attribute Handling Behavior


1. Define the attribute and its constraints in the Windchill Info Modeler or the
Windchill Type and Attribute Manager.
2. Configure the client to display the attribute as described in the following
sections:
– Building Wizards to Create a Single Object (see page 15-38)
– Information Pages (see page 16-2)
– Constructing and Rendering a Table Using the JSP Framework (see page
14-23) and Windchill Client Architecture Tree (see page 14-64)
3. Perform any necessary customizations as described in the Customization
Points section on page 14-12.
Refer to the Data Acquisition Configuration Properties on page 13-2 for details on
how to get a report of all the available ids that you can add to your configurations,
as well as what the data utility implementation class is for that id.

Implementing a Data Utility


When you find that configuration will not be enough to get your component to
work, your next alternative is to extend JCA by implementing a data utility. Data
utilities let you augment the data returned by a core API with additional
information. 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.
The DataUtility interface has two core methods:
Object getDataValue(String component_id, Object datum, ModelContext
mc) throws WTException

void setModelData(String component_id, List objects, ModelContext


mc) throws WTException

Create a Data Utility implementation class


After defining your attribute and its constraints, you should be ready to
implemenat a data utility to handle that attribute.
Since data utilities are looked up using application context, your implementation
class must be public, and have a public no-arg constructor.

14-8 Windchill Customizer’s Guide


Implement the getDataValue() method of the DataUtility interface:
The getDataValue method gets the value that should be placed within a particular
table cell. Typically, the object that is returned by this method should be an
instance of GUIComponent.
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, Mod-


elContext mc)
throws WTException {
…..
…..
String rawVal = myObjetc.get(component_id);
String displayVal = rawVal + “My extra text”;
TextDisplayComponent gui = new TextDisplayCompo-
nent(…);
gui.setValue(displayVal);


return gui;
}

Implement the setModelData() method of the DataUtility interface:


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 method is called
before getDataValue() is called for any row, and is supplied in a list of all the
objects that will be processed. You can take advantage of this call to do some
multi-object queries. The FolderedDataUtility is one example that does this (it
queries for all folder locations at once). If this method is implemented, then you
must configure the data utility to be stateful.

Configure the data utility


Add an application context entry like the following:
<Service name="com.ptc.core.components.descriptor.DataUtility">
<Option
serviceClass="com.ptc.core.components.factory.dataUtilities.Pro
jectDataUtility"
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.Folder
edDataUtility"
requestor="java.lang.Object"
selector="location"

Presenting Information in the UI 14-9


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.
Example:
The FolderedDataUtility is configured with cardinality "duplicate". This is
because the FolderedDataUtility is stateful, it does some multi-object querying in
setModelData, and then holds on to this data for subsequent calls to getDataValue.
Since the utility is stateful, you must create a new instance of the utility for each
table rendering request. By registering the data utility as "duplicate", application
context will instantiate a new data utility for you 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).

Implementing a GUI component renderer


When you find that configuration on the standard GUI components will not be
enough to get the UI behavior you require, your next alternative is to extend JCA
by implementing a custom Renderer for the GuiComponent. This requires you to
be familiar with the specific GuiComponent.
The Renderer interface has one core method:
void draw(T o, Writer out, RenderingContext renderContext) throws
RenderingException;

Example:
The OOTB Renderer implementation for rendering a GUI component for date &
time renders the component like this:

Suppose you want the component to be rendered as:

14-10 Windchill Customizer’s Guide


In this case you would write a custom renderer for the DateInputComponent.
1. Implement the custom renderer
public abstract class MyDateRenderer implements Renderer {


public void draw(T o, Writer out, RenderingContext
renderContext) throws RenderingException {


// render the textbox and icon for the calendar widget

// render a new line


// render the combo box for the hours, the combo box for
the minutes and the time zone

}
}

2. Register your custom renderer. In your data utility, when creating the
GuiComponent in the getDataValue method, register this custom renderer as
your DateInputComponent’s renderer
DateInputComponent gui = new DateInputComponent();

gui.setRenderer(new MyDateRenderer());

It is recommended that when you implement a new Renderer, you extend the
AbstractGuiComponent base class.

Implementing a GUI component


When you find that configuration on the standard GUI components and/or
overriding the Renderer will not be enough to get the UI behavior you require,
your next alternative is to extend JCA by implementing a GuiComponent.
The GuiComponent interface has one core method:
void draw( Writer out, RenderingContext renderContext ) throws
RenderingException;
The GUI component implementation holds the UI model of an attribute to be
rendered. The recommended practice is to have the draw() method of the GUI
component invoke the services of a GUI component Renderer to generate the
HTML for the UI component to be rendered.
public class MyTextBox implements GuiComponent {

private String value;


private intwidth = 10;

Presenting Information in the UI 14-11


private int maxCharLimit = 20;
protected Renderer renderer;
…………
…………

public void draw(Writer out, RenderingContext renderContext)


throws
RenderingException {
if (renderer != null) {
renderer.draw((Object)this,out,renderContext);
}
…………
…………
}
}

Using GUI component wrappers


Some GUI components have Gui component wrappers. These wrapper tags can be
found at:
com.ptc.core.components.tags.components

Some examples of the usage of these tags can be found at:


Windchill/netmarkets/jsp/carambola/tags/tags.jsp

The TLD is
$WT_HOME/WEB_INF/tlds/wrappers.tld

Finding registered data utilities


The best way to find existing data utilities is explained in Data Acquisition
Configuration Properties on page 13-2.

Customization Points

Windchill preferences
Parameter Default Value Possible Values Description

Default Value Display Mode (Site Pre-populate Do not display Mode of displaying the
level) default value in the
Pre-populate
‘Create’ and ‘Update’
Button modes
This applies to all
attributes.

Selection List Style (Site level) Buttons Buttons UI style for Discrete-
sets/Enumerated set
Dropdown List
elements

14-12 Windchill Customizer’s Guide


Parameter Default Value Possible Values Description

Boolean Style (Site level) Buttons Buttons UI style for Boolean


attributes
Dropdown List

String Length Threshold For 60 Any number >= 0 A preference used to


Multiline Input (Site level) determine whether the
input field for String
attributes and URL IBA
type attributes should be
single-line or multi-line.

Local Time Zone(User) Time zone set on the All standard time Local time zone of the
server. zones user – will be used as the
time zone for the display
/ input of date values.

Measurement system(User) SI MKS Determines the


measurement system to
SI
be used for all numeric
USCS values that have a Unit of
CGS Measure.

Ignore URL values found in a No Yes This will filter out


string(Site) special HTML characters
No
from strings while
displaying the string
values.

Display length of attribute values 30 Any number >= 0 Used to control the
in tables number of character’s
displayed when the
attribute’s value is
displayed on a table. This
is also known as the
truncation length of an
attribute value.

Presenting Information in the UI 14-13


Parameter Default Value Possible Values Description

Display length of attribute values 30 Any number >= 0 Used to control the
in the info page number of character’s
displayed when the
attribute’s value is
displayed on an info
page. This is limited to
the top attributes panel
and the folder location
(for folder info pages).
Any table displayed on
an info page will be
based “Display length
for attribute value in
tables.” This is also
known as the truncation
length of an attribute
value.

14-14 Windchill Customizer’s Guide


AllClients.xml
Codebase location:
WT_HOME/codebase/config/logicrepository/xml/AllClients.xml
Examples for the configuration are available in the documentation provided in this
xml file.

Possible
Parameter Default Value Values Req? Description

defaultValueDispla - none No Mode of displaying the default value in


yMode the ‘Create’ and ‘Update’ modes
-
prePopulate This applies to all attributes.
- button

selectionListStyle - buttons No UI style for Discrete-sets/Enumerated set


elements
- dropdown

stringLengthThresh Any number No A preference used to determine whether


holdForMultilineIn >= 0 the input field for String attributes and
put URL IBA type attributes should be
single-line or multi-line.

inputFieldType multiLine - singleLine No


- multiLine

dateInputFieldType dateOnly – - dateOnly No Need to know this for ‘CREATE’ &


default value is ‘EDIT’ modes so that the UI can be
-
assigned in the created accordingly. (It is not possible to
dateAndTi
Java code obtain this info from the format because
me
the formats will be localized and it is not
- timeOnly easy to parse the localized formats to get
this info)

dateDisplayFormat Entries This determines the display format for


should have the Timestamp values.
these 2
parts:
rbInfo=nam
e of the
rbInfo file
key=name
of the entry

ignoreUrls - true No This will filter out special HTML


characters from strings while displaying
- false
the string values.

Presenting Information in the UI 14-15


Possible
Parameter Default Value Values Req? Description

displayLengthInTab Any number No Used to control the number of character’s


les >= 0 displayed when the attribute’s value is
displayed on a table.

displayLengthInInf Any number No Used to control the number of character’s


oPage >= 0 displayed when the attribute’s value is
displayed on an info page. This is limited
to the top attributes panel and the folder
location (for folder info pages). Any
table displayed on an info page will be
based “Display length for attribute value
in tables.”

percent true No Determines if a numeric value should be


false formatted with the locale-specific
percent format

currency true No Determines if a numeric value should be


formatted with the locale-specific
false
currency format

14-16 Windchill Customizer’s Guide


JSP files
Possible
Parameter Default Values Values Req? Description

defaultValueDispl - none No Mode of displaying the default value in


ayMode the ‘Create’ and ‘Update’ modes
- prePopulate
This applies to all attributes.
- button
Example:
<jca:describeProperty id="defaultUnit"
defaultValueDisplayMode=”button” />

selectionListStyle - buttons No UI style for Discrete-sets/Enumerated


set elements
- dropdown
Example:
<jca:describeProperty id="defaultUnit"
selectionListStyle=”buttons” />

stringLengthThres Any number No A preference used to determine whether


hholdForMultilineI >= 0 the input field for String attributes and
nput URL IBA type attributes should be
single-line or multi-line.
<jca:describeProperty id="description"
stringLengthThreshholdForMultilineIn
put =500/>

inputFieldType multiLine - singleLine No Overrides the behavior determined by


stringLengthThreshholdForMultilineInput
- multiLine
Example:
<jca:describeProperty id="description"
inputFieldType=”singleLine”/>

dateInputFieldTyp dateOnly – - dateOnly No Need to know this for ‘CREATE’ &


e default value is -
‘EDIT’ modes so that the UI can be
assigned in the dateAndTim
created accordingly. (It is not possible to
Java code e
obtain this info from the format because
the formats will be localized and it is not
- timeOnly easy to parse the localized formats to get
this info)
Example:
<jca:describeProperty id="startDate"
dateInputFieldType=” dateAndTime”/>

Presenting Information in the UI 14-17


Possible
Parameter Default Values Values Req? Description

dateDisplayFormat A format This determines the display format for


string the Timestamp values.
specified as Example:
an entry in an
rbInfo file. <jca:describeProperty id="startDate"
This format dateDisplayFormat="${standardDateTi
string shall me}"/>
use the
format
pattern letters
specified by
Java’s
SimpleDateF
ormat class.
Standard
Windchill
formats are
defined in \
wcCliSource\
UICommonR
esources\src\
com\ptc\
core\ui\
componentR
B.rbInfo
And these
can be used
by specifying
the entries in
\Windchill\
DevModules\
CommonCo
mponents\
src_web\
netmarkets\
jsp\
components\
standardAttri
buteConfigs.j
spf

14-18 Windchill Customizer’s Guide


Possible
Parameter Default Values Values Req? Description

displayLengthInTa Any number Yes Used to control the number of


bles >= 0 character’s displayed when the
attribute’s value is displayed on a table.
This is also known as the truncation
length of an attribute value.
Example:
<jca:describeProperty id="description"
displayLengthInTables

=15/>

displayLengthInInf Any number Yes Used to control the number of


oPage >= 0 character’s displayed when the
attribute’s value is displayed on an info
page. This is limited to the top attributes
panel and the folder location (for folder
info pages). Any table displayed on an
info page will be based “Display length
for attribute value in tables.” This is also
known as the truncation length of an
attribute value.
Example:
<jca:describeProperty id="description"
displayLengthInInfoPage=15/>

percent true Determines if a numeric value should be


formatted with the locale-specific
false
percent format
Example:
<jca:describeProperty
id="percentComplete" percent=true/>

currency true Determines if a numeric value should be


formatted with the locale-specific
false
currency format
Example:
<jca:describeProperty id="cost"
currency=true/>

inputRequired true Used to mark fields as ‘Required fields’


even though they may not have a
false
‘Required’ constraint.
Example:
<jca:describeProperty id="startDate"
inputRequired=true/>

Presenting Information in the UI 14-19


Possible
Parameter Default Values Values Req? Description

isInfoPageLink true Applicable to ‘Name’ and ‘Number’ and


Principal attributes only. Used to
false
specify if the attribute is to be displayed
as a hyperlink to the Info Page. This
would override the default behavior.
Example:
<jca:describeProperty id="name"
isInfoPageLink=false/>

componentRB.rbInfo file
Possible
Parameter Default Value Value Req? Description

CALENDAR_PAR A legal Date input format (dd/mm/yyyy vs.


SE_DATE in \ localized date mm/dd/yyyy etc)
wcCliSource\ format This is required so that the entered
UICommonResour defined using value can be parsed according to the
ces\src\com\ptc\ valid date- format.
core\ui\ format
componentRB.rbIn characters.
fo

HOUR_FORMAT 12 12 Hour/ 24 Hour format


in \wcCliSource\
24 This determines the entries in the
UICommonResour
hours dropdown (0 - 12 AM/PM vs. 0-
ces\src\com\ptc\
24)
core\ui\
componentRB.rbIn
fo

Additional Resources
See the following sections for more information.
• Building Wizards to Create a Single Object (on page 15-38)
• Building Wizards to Edit a Single Object (on page 15-90)
• Data Acquisition Configuration Properties (on page 13-2)
• Presenting Information in the UI chapter - various sections on tables (starting
on page 14-1)
• Property Panel (on page 11-26)

14-20 Windchill Customizer’s Guide


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 Description

ALL_SOFT_ATTRIBUTES Returns a list of all soft attributes


associated with the retrieved object as well
as values for all of those attributes.

ALL_SOFT_CLASSIFICATION_ATTR Returns a list of all soft attributes


IBUTES associated with the classification(s) of the
retrieved object as well as values for all of
those attributes.

ALL_SOFT_NON_SCHEMA_ATTRIB Returns a list of all soft attributes


UTES 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_ATTRIBUTES_ Returns a list of all soft attributes


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_CLASSIFICATION_ Returns a list of all soft attributes


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

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.

Presenting Information in the UI 14-21


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 Description

ALL_SOFT_NON_CLASSIFICATION_ Returns a list of all soft attributes


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

ALL_CUSTOM_HARD_ATTRIBUTES Returns a list of all custom hard attributes


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

14-22 Windchill Customizer’s Guide


Constructing and Rendering a Table Using the JSP
Framework

Objective
You want 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 Description

Title Bar 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 Bar The shortcut tool bar displays a subset of actions
from the 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 Sorting allows the user to control the presentation


of table 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 Columns The status glyph column(s) convey status and
messaging information about individual objects in
the table.

Object Icon Column The object icon column displays the appropriate
icon for that object.

Presenting Information in the UI 14-23


Element Description

Action Column(s) The action columns in the content area of a table


contain the 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 provides visual closure to the table and contains
the paging and View All functionality, if used.

Scope/Applicability/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:

14-24 Windchill Customizer’s Guide


Solution
Use Table Component to display the information in tabular format.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving HTML, JSP, JavaScript and Custom taglibs.
• Overview of Windchill Client Architecture tags.
• The actions framework in the Windchill client architecture.
• Configuring views.
• Data acquisition, Data Utilities, GUI component

Presenting Information in the UI 14-25


Solution Elements
Element Type Description

<your_page>.jsp JSP Your Windchill Client Architecture


Table implementation JSP file.

<your>service.properties properties Data utilities and services are


defined here.
Run time Location: <Windchill>\
codebase

<your>action.properties properties Action attributes defined here.


Run time Location: <Windchill>\
codebase

<your>actions.xml xml Actions can be defined here.


Run time Location: <Windchill>\
codebase\ config\actions

<your>actionModels.xml xml Action models can be defined here.


Run time Location: <Windchill>\
codebase\config\actions

components.tld tld Tags can be defined here:


Run time Location: <Windchill>\
codebase\WEB-INF\tlds\

<your>action.rbInfo rbInfo Contains localized strings, can be


defined separately for each module.

Procedure – Configuring Table Common Component

Include necessary artifacts


You should include the necessary artifacts in your configuring JSP file e.g.
“/netmarkets/jsp/begin.jspf” or “/netmarkets/jsp/beginPopup.jspf” file and
“/netmarkets/jsp/end.jspf” file. You also need to declare jcataglib directive.
(uri=”http://www.ptc.com/windchill/taglib/components”)

Configure Table
<%@ include file="/netmarkets/jsp/util/begin.jspf"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/core"
prefix="wc"%>

14-26 Windchill Customizer’s Guide


<%-->Build a table descriptor and assign it to page variable td<--
%>
<jca:describeTable var="tableDescriptor"
id="netmarkets.project.list" configurable="true"
type="wt.projmgmt.admin.Project2" label="Project List">
<jca:setComponentProperty key="actionModel" value="project
list"/>
<jca:describeColumn id="name" label="Name" sortable="true"/>
<jca:describeColumn id="nmActions" />
<jca:describeColumn id="owner" need="containerInfo.ownerRef"/>
<jca:describeColumn id="container" label="Host"
need="containerReference"/>
<jca:describeColumn id="category"/>
<jca:describeColumn id="phase"/>
<jca:describeColumn id="state"
need="containerTeamManagedInfo.state"/>
<jca:describeColumn id="projectHealthStatus"
need="healthStatus"/>
<jca:describeColumn id="completionStatus">
<jca:setComponentProperty key="percent" value="true"/>
</jca:describeColumn>
<jca:describeColumn id="modifyStamp"
need="thePersistInfo.modifyStamp" sortable="true"
defaultSort="true" />
</jca:describeTable>

<%-->Get a component model for our table<--%>


<wc:getCurrentUser var="user"/>
<jca:getModel var="tableModel" descriptor="${tableDescriptor}"
serviceName="com.ptc.netmarkets.project.NmProjectService"
methodName="getProjects">
<comp:addServiceArgument value="${user}"/>
</jca:getModel>

<%-->Get the NmHTMLTable from the command<--%>


<jca:renderTable model="${tableModel}"/>

<%@ include file="/netmarkets/jsp/util/end.jspf"%>

The first thing the JSP page does is defines a table using the describeTable tag.
This tag creates a table descriptor object and assigns it to the page variable
specified by the var attribute. This allows the descriptor to be referenced in the
JSP using the JSP expression language (EL).
The table defines a type, in this case Project2. The type is optional, and is only
used to do some defaulting of values. In this example, it is only being used to
default the labels for model-based column ids.
The actionModel property indicates the name of the action model (from
actionmodels.xml) that should be rendered in the table's toolbar.
The columns in the table each have their own describeColumn tag. Each column's
cell values will be produced by a data utility.

Presenting Information in the UI 14-27


Once the table descriptor is set up, it is passed in to the getModel tag. The
getModel tag takes your table descriptor plus a way to get table data and returns a
model object that can be used to render the table.
Like the describeTable tag, the result of the getModel tag is placed in the page-
scoped variable defined by the var attribute.
The rendering portion of the table is simply done by passing your model object
(defined by the getModel tag) into the renderTable tag.
The Default Sorted column is defined with the defaultSort="true" attribute on the
column tag.

Customization Points

describeTable tag attributes


describeTable describes a Table common component that can be plugged in to
Windchill Client Architecture getModel and renderTable tags. Its tag class is
com.ptc.core.components.tags.components.DescribeTableTag and the body
content is "scriptless".

Possible
Parameter Default Value Values Req? Description

id - Any Yes The identifier for this table descriptor. If


java.lang.String this table supports configurable views,
value then this id may be used to look up the
view configurations, unless it is
overridden by the configurableTableId
attribute.

var - Any Yes Name of the exported scoped variable


java.lang.String for the table descriptor. The type of the
value variable is
com.ptc.core.components.descriptor.Co
mponentDescriptor.

scope - Can be (case- No The name of the scope to export the var
insensitive): attribute to.
‘page’, ‘request’,
‘session’ or
‘application’

type - - No Name of the main type of object


displayed in this table. This can be either
a modeled or soft type. When specified,
the infrastructure will use the type to
look up labels and other default values
when it can't find them otherwise.

14-28 Windchill Customizer’s Guide


Possible
Parameter Default Value Values Req? Description

label - Any No The localized label for this component.


java.lang.String
value

mode - java.lang.String No The name of one of the modes defined in


value of a the
com.ptc.core.ui.r com.ptc.core.ui.resoureces.Component
esources.Compo Mode enum. VIEW is the default mode
nentMode if not specified.

componentTyp - java.lang.String No The name of one of the component types


e value of a defined in the
com.ptc.core.ui.r com.ptc.core.ui.resoureces.Component
esources.Compo Type enum. TABLE is the default if not
nentMode specified.

configurable “false” boolean No Whether or not this table supports


configurable views.

viewId - - No The id to use to look up configurable


views. If unspecified, then defaults to the
table id. Only used if configurable is set
to 'true'

singleViewOnl true/false When this property is true, and the table


y is configurable, then this property will
change the table rendering so that the
table view edit wizard is launched
directly from the table, as opposed to
launching the table view manager. This
is useful when the table does not support
views, but still needs to allow the
user to select columns and sort order.

toolbarName - Any No The name of the action model to use for


java.lang.String toolbar actions.
value

menubarName Any No The name of the action model to use for


java.lang.String menubar actions.
value

helpContext - - No The help context for this table. No help


icon will be displayed if no help context
is specified.

Presenting Information in the UI 14-29


Possible
Parameter Default Value Values Req? Description

targetObject - - No Allows the developer to provide more


objects for a single table row. Typically
the infrastructure treats each index of the
array returned by the getModel tag's API
as a &quot;row&quot; object. This row
object is passed to each column's
DataUtility. If a different object is
needed for some DataUtilities then that
object can be specified as the
targetObject in the describeTable or
describeColumn tag. The original row
object must have a getter method for the
name specified as the target object. (i.e.
targetObject="my_related_part" would
mean the object needs a
getMy_related_part() method).
The target object will be used in the
following places:
• The row object supplied to data
utilities.
• The object that soft attributes will
be extracted from
• The context object for the row
checkbox

summary - - No A localized summary of the information


in this table, which is used for
accessibility compliance.

disableAction - - No Flag to indicate enable or disable


collapse/expand action. It will work only
when useJSCA=false

isFreezable - Boolean No This property when set to true, then


current table will be considered for
column freezing. By default the value is
true.

14-30 Windchill Customizer’s Guide


Additional attributes set via the setComponentProperty sub tag

Parameter Possible Values Description

actionModel java.lang.String value that corresponds to an entry in an *actionmodel.xml file

scrollType java.lang.String Value that represents constants from the JSTableConstants class
under keys .JSTABLE_IMPL*
"default" - chooses the browser default
"D" = Dom based scrolling, the default for tables in popup wizard
pages.

selectable true/false Determines if the checkbox column will be displayed. If set to


false there will not be any check box column for table as well as
tree.

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

Possible
Parameter Default Value Values Req? Description

var - Any Yes Name of the exported scoped variable


java.lang.String for the descriptor.
value

scope - Can be (case- No The name of the scope to export the var
insensitive): attribute to.
“page” ,
“request”,
“session” or
“application”

serviceName - java.lang.String No The name of the service class to use to


of a fully get model data. This property is mutually
qualified class exclusive with the queryCommand or
name statementSpec attributes. If this attribute
is specified, then methodName must be
specified as well. Arguments to the
method can be specified with the
addServiceArgument tag. The service
class must either be a registered
Windchill service or implement
wt.method.RemoteAccess.

Presenting Information in the UI 14-31


Possible
Parameter Default Value Values Req? Description

methodName - Any No The name of the method to use to get


java.lang.String model data. This property is mutually
value exclusive with the queryCommand or
statementSpec attributes. If this attribute
is specified, then serviceName must be
specified as well. Arguments to this
method can be specified with the
addServiceArgument tag.

statementSpec - Is of type No The StatementSpec to use to get model


wt.pds.Statemen data. Note that QuerySpec implements
tSpec StatementSpec. This property is
mutually exclusive with the
queryCommand, serviceName, and
methodName attributes.

queryComman - Is of type No The AbstractQueryCommand to use to


d com.ptc.core.que get model data. This property is mutually
ry.command.co exclusive with the statementSpec,
mmon.Abstract serviceName, and methodName
QueryCommand attributes.

descriptor - Is of Type True The descriptor to base the component


com.ptc.core.co model on
mponents.descri
ptor.Component
Descriptor

treeHandler - java.lang.String No The selector for the TreeHandler to use


of a fully to build the data model. The tree handler
qualified class should be registered in application
name context.

pageLimit - Any integer No The number of rows to display per page


value in the table. This attribute has been
moved from renderTable tag to
getModel tag and henceforth will be
deprecated for renderTable tag.

14-32 Windchill Customizer’s Guide


Possible
Parameter Default Value Values Req? Description

fullListLimit 10000 INteger No Specify a different maximum value of


rows to be displayed in a table when the
full list action is clicked. To keep the
browser from crashing with too much
html. The objective of shifting
fullListLimit parameter to getModel tag
was to provide a two-pass approach for
Table model generation for performance
enhancement. If fullListLimit is
specified at getModel tag, then paging
happens at MethodServer side and only
the populated table model is sent to
tomcat for rendering which improves
performance considerably.

renderTable tag attributes


renderTable renders a JCA Table. f the var attribute is set, then the tag will set
page-scoped attribute with an NmHTMLTable based on the supplied
ComponentModel. If the var tag is empty, then the NmHTMLTable is created and
drawn. The tag also supports drawing a pre-built NmHTMLTable by specifying
the table attribute.
Its tag class is com.ptc.core.components.tags.components.RenderTableTag and
the body content is "scriptless". "pageLimit" and "fullListLimit" attributes should
be defined at getModel tag and not at renderTable tag. Support for pageLimit and
fullListLimit attributes on renderTable tag will be depricated in future.

Parameter Default Value Possible Values Req? Description

var - Any java.lang.String No The name of the scoped variable to


value assign the NmHTMLTable to. If this is
not specified, then the table is drawn
by the tag.

scope Can be (case- No The name of the scope to export the var
insensitive): “page” , attribute to.
“request”, “session”
or “application”

model - Of type No The component model to create (and


com.ptc.core.compo optionally draw) an NmHTMLTable
nents.descriptor.Com from. If unspecified, then an
ponentModel NmHTMLTable must be specified
using the table attribute.

Presenting Information in the UI 14-33


Parameter Default Value Possible Values Req? Description

table - Of type No The NmHTMLTable to render. If this


com.ptc.netmarkets.u is not specified, then a
til. ComponentModel must be specified
table.NmHTMLTabl from which a table will be created.
e

showCount - boolean No Optionally show the count of objects in


the table title area. The count is
displayed as “X of Y total objects”, if
Table has filter view displayed, else “X
total objects”. X is number of objects
displayed in current page & view of the
table. Y is total number of objects in
current view of the table across all
pages.

showPaging true boolean No Determines whether the table is paged.


Links

showCustom - boolean No Determines whether or not to show


ViewLink The customize view link in the view
drop down.

pageLimit - integer No The number of rows to display per


page in the table. If this was specified
by the getIeModel tag, it does not need
to be re-specified here.Its deprecated
and will be specified henceforth in
getModel tag.

fullListLimit 10000 integer Specify a different maximum value of


rows to be displayed in a table when
the full list action is clicked. To keep
the browser from crashing with too
much html. Its deprecated and will be
specified henceforth in getModel tag.

viewAllLink - URL to the view all No Option to show a view all link at the
page. bottom of the table.

helpContext - Any java.lang.String No The help context for this table. No help
value icon will be displayed if no help
context is specified.

singleSelect - boolean No Single Select mode. Use Radio buttons


or checkboxes for the row selection.

14-34 Windchill Customizer’s Guide


Parameter Default Value Possible Values Req? Description

scroll false boolean No Specifies that the table should use


scrollbars to keep the header and
actions in view when looking down at
the items in the bottom of the table.
Note: Note: Setting scroll="false" has
no effect in JSCA tables. To turn off
the scrolling, use a different table
rendering mode (see the "useJSCA"
tag for more information).

rowBasedOb - boolean No Whether objectHandles are needed for


jectHandle each row. By default, the value of this
attribute is false. Set to true to render a
table for creating/editing multiple
objects in a create/edit wizard.

afterJS - Any java.lang.String No JavaScript method to execute after the


value table has been rendered or re-rendered
as a result of sorting etc.

useJSCA false boolean Specifies whether the table should use


JSCA. If this attribute is set the rules
are ignored and the passed in value is
used to determine whether or not to use
JSCA. Set to true to force the table to
use JSCA. Set to false to force the table
to use JCA.

preferenceCo false Any java.lang.String The "preferenceContext" variable is


ntext value used to control the scope of the
preference. For e.g. user may or may
not want the preference to be applied
even when the context object is
changed.

Configuring Tables - Overview


Building a table requires three main steps:
• Creating a JSP page and define table attributes.
• Defining a method of retrieving the table data.
• Specifying any special data utilities that format the data.
To start with, make sure the page includes the “begin” and “end” JSPF files. Also,
include the common components tag library file. The code for the same is as
follows:
<%@ include file="/netmarkets/jsp/util/begin.jspf"%>

Presenting Information in the UI 14-35


<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>

<%@ include file="/netmarkets/jsp/util/end.jspf"%

Every JSP page can be structured into three main parts:


• Creating the table descriptor object
• Defining the component model
• Rendering
Details on configuring tables
The following table configuration topics are included in the following sub-
sections:
• Configuring Tables - Defining Table Attributes on page 14-37
• Configuring Tables – Set Table Model for Data acquisition on page 14-38
• Configuring Tables – Render Table on page 14-38
• Configuring Tables – Set sortable columns on page 14-39
• Configuring Tables – Adding Toolbar on page 14-40
• Configuring Tables – Adding row-level actions on page 14-41
• Configuring Tables – Adding Menu Bar on page 14-42
• Configuring Tables – Enabling row selection on page 14-43
• Configuring Tables – Enabling single/multiple row selection on page 14-44
• Configuring Tables – Adding the help icon on page 14-44
• Configuring Tables – Adding pagination and page limit on page 14-45
• Configuring Tables – Specify DataUtility for columns on page 14-46
• Configuring Tables – Adding an info page hyperlink to table data on page
14-47
• Configuring Tables – Enabling views on page 14-48
• Configuring Tables - Defining Table Attributes on page 14-37
• Configuring Tables - Show custom view Link on page 14-54
• Configuring Tables – Enable Scrolling on page 14-59
• Configuring Tables – Accessibility compliance on page 14-59
• Configuring Tables – Enable Table Count on page 14-60
• Configuring Tables – Hiding column of the table on page 14-60

14-36 Windchill Customizer’s Guide


• Configuring Tables – Display view all link on page 14-60
• Configuring Tables – Customize Preferences on page 14-60

Configuring Tables - Defining Table Attributes


The table attributes can be defined using the describeTable tag.
This tag creates the table descriptor object and assigns it to the page variable
specified by the “var” attribute.
The id attribute stores the identifier for this table descriptor.
The label attribute is the localized label for this component and is displayed as the
table header in the UI.
The columns in the table are produced by adding the describeColumn subtag. 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, which has the same semantics when used in table
components. The id attribute for this tag is used to look up default properties for
the column.
The code for the same is as follows:
<%-->Build a descriptor and assign it to page variable
tableDescriptor<--%>
<describeTable var="tableDescriptor" type="wt.part.WTPart"
id="netmarkets.test.table" label="${tableName}" >
<describeColumn id="name"/>
<describeColumn id="number"/>
</describeTable>

Here <describeTable> is the tag which is responsible for rendering the columns in
the table . The label of the column can be fetched from the resource file. For this
we need to make the entry in the rbInfo file and give the “key” as a label in the
<describeColumn> tag.
To add/remove columns in the Table, insert/remove describeColumn tag from the
describeTable tag. The column order is the order in which the columns are defined
using the describeColumn tag in describeTable tag in a JSP file.
Each column has a guiComponent corresponding to the value to be shown in the
column. Each guiComponent has a reference to renderer object that is responsible
for generating the html. To change the default renderer we need to change the
guiComponent or the renderer reference for that guiComponent. GuiComponent
are created using the dataUtility.
To hide a column, use “hidden” attribute in the <describeColumn> tag. When
true, the column will not be shown in the displayed page but can be used in sorting
and filtering. This allows custom sorting and filtering options. The default value is
false.

Presenting Information in the UI 14-37


Configuring Tables – Set Table Model for Data acquisition
We can pass the table descriptor to the getModel tag. In the data acquisition phase,
the developer combines a component descriptor with some additional information
on how to actually go and get the data that will back the component. This takes the
table descriptor and a way to get the table data and returns a model object that will
be used to render the table. The table descriptor variable must be specified in the
descriptor attribute.
The serviceName attribute is used to specify the Java API service class that
retrieves the table data.
When serviceName is included, the methodName attribute must also be used. The
name of the method within the service class is indicated using this attribute.
The code for the same is as follows:
<%-->Get a table model using our descriptor and query command,
assign model to page variable tableModel<--%>

<getModel var="tableModel" descriptor="${tableDescriptor}"


queryCommand="${queryCommand}"/>

Configuring Tables – Render Table


The rendering part is done by passing the model object into the renderTable tag.
The variable for the model object specified in the getModel tag should be passed
to the renderTable. If the model attribute is not specified, then NmHTMLTable
must be specified using the table attribute.
The code for the same is as follows:
<%-->Render the table model<--%>
<renderTable model="${tableModel}"/>

Thus the entire generated JSP will look as followed:


<%-->Build a descriptor and assign it to page variable
tableDescriptor<--%>
<describeTable var="tableDescriptor" type="wt.part.WTPart"
id="tableId" menubarName = "tabular input toolbar"
label="${tableName}" configurable="true">
<setComponentProperty key="actionModel" value="product
list"/>
<setComponentProperty key="selectable" value="true"/>
<describeColumn id="name" sortable="true"
defaultSort="true" />

<describeColumn id="number" sortable="false"/>


</describeTable>

<%-->Get a query command and assign it to page variable


queryCommand<--%>
<cmb:getTypeInstanceCommand var="queryCommand"
descriptor="${tableDescriptor}"/>

14-38 Windchill Customizer’s Guide


<%-->Get a table model using our descriptor and query command,
assign model to page variable tableModel<--%>
<getModel var="tableModel" descriptor="${tableDescriptor}"
queryCommand="${queryCommand}"/>

<%-->Render the table model<--%>


<renderTable model="${tableModel}"/>

Configuring Tables – Set sortable columns


A table column can be made sortable by setting the “sortable” attribute to “true”.
If we want to sort the table by default with a specific column, then we can mark
the column as “defaultSort”.
The code for the same is as follows:
<describeColumn id="name" sortable="true" defaultSort="true" />

This code snippet will sort the column “name” at the page load time
(defaultSort="true"). As well as user can sort the column as and when required
(sortable=”true”).
This will generate the Table as follows:

Note: If a column in a table is marked as non-sortable in a JSP through


describeColumn, then the respective change should be done in the view
configuration as well (through ConfigurableTable class). The table column
definition in the JSP should be in synch with ConfigurableTable class. If the
column definition in JSP is not in sync with the view definition then it can result
into anomalies at the user interface.

Sorting Behavior
Sorting behavior differs in following scenario:
1. For Paging tables

Presenting Information in the UI 14-39


a. If the table had no selected rows:
If the user is on page X then, table refresh resulted because of sort action
will show the table vertically positioned at the first row of the first page.
b. If the table had selected rows:
When the table is refreshed because of sort action, the table will page to
the page that contains the last of the pre-sort selected rows. The selected
rows will be retained.
2. If the table is a scrolling table, i.e. do not have pagination enabled or a full list
table
a. If the table had no selected rows:
On sort action, the table will be positioned at the first row in the table.
b. If the table had selected rows:
On sort action, the table will scroll to show the last row that was selected.
The selections are retained.
3. If column freeze is applied on the table the horizontal scroll position is always
maintained after a sort action.
4. The "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.

Configuring Tables – Adding Toolbar


Adding a toolbar to the table is achieved by using the setComponentProperty tag.
setComponentProperty tag configures properties of its parent tag that aren't
exposed as attributes of the parent tag itself. This gives the infrastructure and the
developer flexibility about the metadata they'd like to be available, without always
requiring a tld update to do so. This is a helper tag that sets properties on the
component descriptor managed by a parent describe tag. The key attribute and the
value attribute are the key and value for the properties map of the target
ComponentDescriptor, respectively.
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.
The code for the same is as follows:
<describeTable var="tableDescriptor" type="wt.part.WTPart"
id="tableId" menubarName = "tabular input toolbar"
label="${tableName}" configurable="true">
<setComponentProperty key="actionModel" value="customToolbar"/>
<setComponentProperty key="selectable" value="true"/>

<describeColumn id="name" sortable="true" defaultSort="true" />

14-40 Windchill Customizer’s Guide


<describeColumn id="number" sortable="false"/>
</describeTable>

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="document"/>
</model>

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. The "cross page functionality"
allows the user to select multiple rows across multiple pages and apply the tool
bar actions to the rows across multiple pages.
Here is the simple table example with the custom toolbar added:

Configuring Tables – Adding row-level actions


Use <describeColumn id="nmActions" sortable="false"/> in the table.
NmActions Data Utility gets the "Actions" hyperlink by default, but can be
configured with properties to get any NmHTMLActionModel or NmAction. The
drop down is generated using the Menu component.
By default this data utility will return the Actions hyperlink. And by default the
Actions hyperlink will display the action model flagged with
menufor="<someObjectType>" in an actionmodels.xml file, where
<someObjectType> is the type of the row object (e.g. wt.part.WTPart) This is

Presenting Information in the UI 14-41


determined dynamically, you should not have to configure which action model to
use, even if your table has multiple object types.
To have this data utility return an Actions hyperlink to an action model other than
the default use the "actionModel" property. In a jsp it would be like:
<jca:describeColumn id="nmActions">
<setComponentProperty key="actionModel"
value="<action_model_name>"/>
</jca:describeColumn>

From a data utility class it would be like:


descriptor.setProperty(DescriptorConstants.ActionProperties.ACTION_MODEL,
"<action_model_name>");
Where <action_model_name> is the name of some action model in an
actionmodels.xml.

Note: To avoid inconstancies in ordering/grouping of the actions and issues with


finding all the action models to adjust when adding new actions, it is preferred to
have one action model per object type that represents the Actions list across the
system (meaning in represents the actions list used in tables/trees and also on the
info page). Action validation should be used to filter the list.

Configuring Tables – Adding Menu Bar


To add a menu bar, the menubarName attribute from the describeTable tag must
be included
The name of the action model to use for the menu bar actions is specified in this
attribute
<describeTable var="tableDescriptor" type="wt.part.WTPart"
id="tableId" menubarName = "customMenubar" label="${tableName}"
configurable="true">
<setComponentProperty key="actionModel" value="customToolbar"/>
<setComponentProperty key="selectable" value="true"/>

<describeColumn id="name" sortable="true" defaultSort="true" />


<describeColumn id="number" sortable="false"/>
</describeTable>

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.
Code for the same is as follows:
<model name="customMenubar">
<submodel name="fileMenu">
<submodel name="editMenu">
</model>

<model name="fileMenu">

14-42 Windchill Customizer’s Guide


<action name="list_cut" type="object"/>
<action name="list_copy" type="object"/>
<action name="fbpast" type="object"/>
<action name="list_delete" type="object"/>
</model>

<model name="editMenu">
<action name="create" type="document"/>
</model>

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:
object.fileMenu.description=File

object.editMenu.description=Edit

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:

Since "cross page functionality" is now provided which allows the user to select
multiple rows across multiple pages, the menu bar actions will now be applicable
to the rows across multiple pages.

Configuring Tables – Enabling row selection


Making the rows selectable can be done by adding another setComponentProperty
tag. The key attribute must be set to “selectable” and the value attribute must be
set to “true”.

Presenting Information in the UI 14-43


This will provide the checkbox for each of the rows in the table, by which the user
can select any of the records for the update or deletion.
Code for the same is as follows:
<describeTable id="tableId"
var="tableDescriptor"
label="${componentName}" >
<setComponentProperty key="selectable" value="true"/>
<describeColumn id="name" label="${columnName}" />
</describeTable>

Configuring Tables – Enabling single/multiple row selection


We can also give 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 of the tag <renderTable> to “true”. 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.
The code for the same is as follows:
<renderTable model="${tableModel}" showPagingLinks
singleSelect="true"/>

Configuring Tables – Adding the help icon


The help page can easily be integrated in the table. The help page can be localized.
The tag for the same is <renderTable> and attribute for the same is
“helpContext”. This tag will pick up the entry from service.properties.xconf.
The entry in service.properties.xconf will be as follows
<Option requestor="java.lang.Object"
resource="online.accessible.ATTablesUse" selector="TEST_HELP"/>

“online/accessible/TTablesUse.html” is the path for the help page.

14-44 Windchill Customizer’s Guide


The code to be written for the help page will be as follows
<renderTable model="${tableModel}" helpContext="TEST_HELP"/>

The table with help page will look as follows


Adding help page will produce the following results:

On click of the “?” sign the pop up will open up which will show up the help for
the table.

Configuring Tables – Adding pagination and page limit


Depending on the number of records in the table, the pagination facility can be
given. The tag used for the pagination is <renderTable>. If the attribute
“showPagingLinks” is set to true, the pagination will be enabled. We can also
specify the number of records that are to be shown on each page. This can be set
by setting the maximum number of records to be displayed to the attribute
“pageLimit”. If the value for “pageLimit” is not defined, it would be fetched from
the preference value.
The code for the same is as follows:
<jca:getModel var="tableModel" pageLimit="10"/>

Presenting Information in the UI 14-45


Adding the pagination will produce the following results:

Configuring Tables - Adding pagination in header


You can can add the paging links in header. This option can be set through
preference manager. By default this option is disabled and if set it will display the
paging links in header as well as footer.

Configuring Tables – Specify 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 “dataUtilityId”
attributes of the describeColumn tag.

14-46 Windchill Customizer’s Guide


<describeColumn id="iconType" label="${columnName}"
dataUtilityId="typePicker.iconType" />

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.dataUtiliti
es.IconTypeDataUtility"
requestor="java.lang.Object"
selector="typePicker.iconType"
cardinality="duplicate"/>
</Service>

Configuring Tables – Adding an info page hyperlink to table data


We can specify the name columns link to the info page of the row object. When
the user clicks on that link, the new page (Infopage) will open up. This can be
done by setting the “isInfoPageLink” attribute of the <describeColumn> tag to
“true”. The code for the same is as follows.
<describeColumn id="name" isInfoPageLink="true"/>

The isInfoPageLink attribute overrides the default behavior of the column to add
or remove a hyperlink to the info page of the context object. The attribute is only
applicable for the name and number columns. By default the number is a
hyperlink to the info page and name is not.
Adding the link will produce the following results:

Displaying table data as hyperlink can also be achieved using a data utility. The
data utility can be configured in service.properties file.

Presenting Information in the UI 14-47


Configuring Tables – Enabling views
To filter data for a table one has to use customized views. If the table has the
customized view option available then using that, we can filter the data. The view
wizard has a "set filters" step, which can be helpful in setting the filtering rules.
There are two main steps to defining a configurable table:
• Define the columns, filter criteria, etc that you want to show up in the
configurable view wizard
• Register your table, and set up your JSP page to enable configurable tables
In order for a table to be configurable, you must explicitly specify this in the JSP.
To do this, add a configurable="true" attribute to the describeTableTag, as
follows:
<describeTable id="someTable" configurable="true" ... />

Setting configurable="true" adds the Current View drop-down to the top-right


corner of the table.
If you want your table to use a configurable table id that is different from the table
id, you can use the new "viewId" attribute:
<describeTable id="someTable" viewId="my_view_Id" ... />

Note that setting viewId implicitly sets configurable to "true".

Configuring Tables - Create a customized view


Table views intended for JCA are required to extend the
com.ptc.core.htmlcomp.components.JCAConfigurableTable class. Once the table
is implemented, it needs to be registered in an application context in order for the
infrastructure to find it. For that, add a service to the service.properties.xconf file
and the serviceClass attribute must match the location of the
JCAConfigurableTable class. The selector must match your table's id.
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.

14-48 Windchill Customizer’s Guide


Available Attribute Report:
http://<server>:<port>/<context>/netmarkets/jsp/carambola/createta
bleview/availableAttributesReport.jsp

The table currently displays the "Sample View" created in the configurable table
implementation. 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.

Configuring Tables - Creating a Configurable Table Instance


The way to define a new configurable table is by implementing the
com.ptc.core.htmlcomp.tableview.ConfigurableTable interface. This interface has
methods that allow the configurable table wizard to find out what wizard steps,
columns and types should be available. In general, this interface should not be
implemented directly.
Table views intended for the Windchill Client Architecture are required to extend
the com.ptc.core.htmlcomp.components.JCAConfigurableTable base class. This
is required so that the appropriate mapping between Windchill Client Architecture
and CADX attribute ids can occur. For more information, see
com.ptc.core.htmlcomp.components.JCAConfigurableTableAdapter.

Controlling Which Steps Are Displayed


Each step can be hidden or displayed in the create and edit view wizard by
overriding the appropriate method. Return true to display the step and false to hide
it. By default all steps are displayed.
• showSetNameStep() - This step allows the user to set\edit the name for the
view. This step is usually hidden when only allowing a single user-editable
view.
• showChooseItemTypesStep() - This step allows the user to set\edit the set of
types that will be displayed in the view. This step is usually hidden if the table
only contains a single type.
• showFilteringStep() - This step allows the used to define filtering criteria used
to filter the data displayed in the table. This step is usually hidden if attribute
filtering is not supported or is supported by other means. (i.e. Search)

Presenting Information in the UI 14-49


• showSetColumnsStep() - This step allows the user to select the set of columns
that will be displayed in the table. There is currently no reason to ever hide
this step.
• showSortingStep() - Select sorting step. There is currently no reason to ever
hide this step.

Example
// Hide the name step
public boolean showSetNameStep(){
return false;
}

Defining Which Types Are Available


There are two methods that define the list of types that can appear as rows in the
table.
• getClassTypes() - Defines the list of available types. This method should
construct and return an array of java.lang.Class objects. This list of types,
along with any child types, will show up in the "Choose Item Types" step.
• getAttributeOnlyClassTypes() - The types defined here will not appear in the
"Choose Item Types" step, but will be used to generate attributes for the
"Select a Column" step.
This information is used to determine the set of available columns that can be
selected for the table. For example, if the class list includes WTPart.class, then the
infrastructure knows that there are a few columns that should always be available
for parts (like name, number, etc).
If null is returned from this method, all of the columns will be determined by
getSpecialTableColumnsAttrDefinition(Locale).

Example
public Class[] getClassTypes() {
return new Class[] { WTPart.class };
}

Defining Which Attributes Are Available


The available attributes factory is responsible for determining the initial list of
attributes for each configurable table. Attributes are defined per type in the
available attribute xml files. The list of types defined in the configurable table is
passed to the available attribute factory and the list of attributes for those types is
returned. This base list can be added to or filtered differently for each step.

Removing Attributes
An attribute can be removed from any step by overriding the appropriate method
and returning false for the attribute's id.

14-50 Windchill Customizer’s Guide


• canAttributeBeUsedInFilter(String) - Removes the attribute from the attribute
filtering step.
• isAttributeValidForColumnStep(String) - Removes the attribute from the list
of available columns.
• isAttributeValidForSortingStep(String) - Removes the attribute from the list
of sortable columns.

Example
// Sorting on the info page action doesn't make sense, so it is
being removed
public boolean isAttributeValidForSortingStep(String key) {
return !key.equals(ColumnIdentifiers.INFO_ACTION);
}

Special Columns
The getSpecialTableColumnsAttrDefinition(Locale) method tells the
configurable view wizard about columns that it cannot find out about
automatically (this is what makes these columns "special"). Automatic columns
are discovered by looking up the global columns that map to each data type
returned by getClassTypes.
The getSpecialTableColumnsAttrDefinition method returns a list of
com.ptc.core.htmlcomp.createtableview.Attribute.AbstractAttribute objects. Each
one of these attributes represents a column that a user can choose to include in the
table view. The primary value of these attribute definitions is that they allow the
table view wizard to know how to present filter criteria for the column. For
example, if a column is represented by a BooleanAttribute, then the wizard knows
that to filter on this column, the user should select either true or false.
There are 5 concrete types of AbstractAttributes:
• BooleanAttribute - A column that contains a boolean value
• CustomAttribute - Not used by the Windchill Client Architecture
• DateAttribute - A column that contains a Date value
• TextAttribute - A column that contains a String value
• ListAttribute - A column that contains a list of predefined values
The IDs for the attributes returned here should correspond to the ids used to define
data utilities for the columns, if needed
Most columns will not need to be listed here. It is very unlikely that a table will
have more than a few special columns. Only add a column here if it is specific to
the table. A common exception to this rule is the Actions column. Since it is not
defined globally, you will need to add it here if you want that column.

Presenting Information in the UI 14-51


Example
public List getSpecialTableColumnsAttrDefinition(Locale locale) {
List result = new ArrayList();
// add the actions column as a special column
result.add(new Attribute.TextAttribute(ACTIONS,
projectRb.getString(projectResource.ACTIONS), locale));
...
return result;
}

Defining OOTB Views


The getOOTBTableViews(String, Locale) method returns a list of
com.ptc.core.htmlcomp.tableview.TableViewDescriptor objects, where each
descriptor represents a view that should appear in the view selection list by
default. These views are loaded into the database the first time the table is visited
by the user. Because these OOTB view definitions are loaded into the database,
the loaded definitions will need to be cleared after making changes for them to
take effect.
Each TableViewDescriptor contains a Vector of
com.ptc.core.htmlcomp.tableview.TableColumnDefinition objects. Each
TableColumnDefinition represents a column that should appear in the view.
The TableViewDescriptor has a few flags that are of interest:
• system - Flags the view as a system loaded view. This prevents the user from
being able to delete or edit it. The user can, however, still choose not to show
it in the view manager. This should be false if the table only supports a single
user-editable view.
• global - No longer used. This property is ignored.
• match - Whether or not to match all or any criteria. If set to true, the criterion
are ANDed together. If false, they are ORed.
Configurable table implementations that extend
com.ptc.core.htmlcomp.tableview.AbstractConfigurableTable
(JCAConfigurableTable extends this) can take advantage of some reusable helper
methods. There are helpers to get:
• Latest version/revision criterion. (See getAdvVersionLatestCriterion() and
getAdvRevisionLatestCriterion())
• Latest version/revision column. (See getAdvVersionAttrDef(Locale),
getAdvRevisionAttrDef(Locale) and getAdvVersIterAttrDef(Locale, String,
String))
• Localized OOTB table view names and descriptions. (See
getResourceEntryKey( String classname, String propertyName))
When possible, use the column ids defined in
DescriptorConstants.ColumnIdentifiers.

14-52 Windchill Customizer’s Guide


View Filtering
Views can have filters, or TableViewCriterion, attached to them that filter the
table rows based on a set of criteria.
In order to properly filter on object type, the criterion must be formed properly.
This is required in order to show the proper object types selected in the Select
Object Types Step of the create and edit view wizard. To form the criterion
properly, the method
com.ptc.core.htmlcomp.createtableview.AttributeHelper.getObjTypeKey(Class)
should be used.
To get localized enumerated type filters, use getStringValue() on the enumerated
type value.

Example
public List getOOTBTableViews(String tableId, Locale locale) throws
WTException {
// The list of all ootb views
List<TableViewDescriptor> ootbViews = new
ArrayList<TableViewDescriptor>();

// The columns that make up one ootb view


Vector<TableColumnDefinition> columns = new
Vector<TableColumnDefinition>();

columns.add(TableColumnDefinition.newTableColumnDefinition(ColumnI
dentifiers.FOO, /*lockable*/false));

columns.add(TableColumnDefinition.newTableColumnDefinition(ColumnI
dentifiers.BAR, /*lockable*/false));

// The criteria for this ootb view


Vector<TableViewCriterion> criteria = new
Vector<TableViewCriterion>();

criteria.add(TableViewCriterion.newTableViewCriterion(ColumnIdenti
fiers.STATE, OperatorConstants.EQUALTO,
ProjectState.RUNNING.getStringValue(), null));

criteria.add(TableViewCriterion.newTableViewCriterion(ColumnIdenti
fiers.ICON, OperatorConstants.EQUALTO,
AttributeHelper.getObjTypeKey(Milestone.class), null);

// Get the localized name an description of the view


String name = getViewResourceEntryKey(RESOURCE,
fooResource.MY_VIEW_NAME);
String description = getViewResourceEntryKey(RESOURCE,
fooResource.MY_VIEW_DESCRIPTION);
TableViewDescriptor desc =
TableViewDescriptor.newTableViewDescriptor(name, tableId,
/*system*/ true,
/*global*/ true, columns, criteria, /*match*/ true,
description);

// Add the descriptor to the list of all ootb views

Presenting Information in the UI 14-53


ootbViews.add(desc);

// Create additional TableViewDescriptors and add them to


ootbViews as needed
...

return ootbViews;
}

Configuring Tables - Making a Windchill Client Architecture Table Configurable


In order for a table to be configurable it must be explicitly declared in the JSP. To
do this, add a configurable="true" attribute to the describeTableTag. If a
configurable table id that is different from the table id is required, the
"configurableTableId" attribute can be used.
<jca:describeTable id="someTable" configurable="true" ... >

OR
<jca:describeTable id="someTable"
configurableTableId="someConfigurableTableId" ... >

Note that setting a configurableTableId implicitly sets configurable to "true".

Configuring Tables - Show custom view Link


Customization of the configurable table can be removed by adding
showCustomViewLink="false" to the renderTable tag. This will remove the
"Customize..." link from the view drop down.

Example
<jca:renderTable model="${tableModel}"
showCustomViewLink="false"/>

Configuring Tables - Restricting View Creation


In some scenarios it may not make sense to allow the user to create multiple
views. By adding singleViewOnly="true" to the describeTable tag, the view drop
down will be replaced with a customize table icon that links directly to the edit
wizard for the current view. If used, the name step should not be shown and only
one view should be loaded OOTB.

Example
<jca:describeTable var="tableDescriptor" id="my.table"
configurable="true" singleViewOnly="true" ... >

Configuring Tables - Linking the JSP Table to the Configurable Table Instance
Once the table is implemented, it needs to be registered in application context in
order for the infrastructure to find it.

14-54 Windchill Customizer’s Guide


Example
<Service context="default"
name="com.ptc.core.htmlcomp.tableview.ConfigurableTable">
<Option requestor="java.lang.Object" selector="my.table.id"
serviceClass="com.ptc.my.ConfigurableTableImpl"/>
</Service>

Configuring Tables - Developing Configurable Tables


Though the initial configuration is via Java code (through the ConfigurableTable
interface), at runtime, table view information is persisted in the database. The first
time that a configurable table is requested, the infrastructure reads in the
ConfigurableTable Java class, and persists this information in the database. This
means that if changes are made to the configurable table implementation class (to
change the OOTB views for example), the configurable table information needs to
be cleared from the database in order for the changes to show up. To do this, run
the following SQL commands:
DELETE FROM TableViewDescriptor;
DELETE FROM ActiveViewLink;
commit;

Note that this will delete all user view information from the system, so it should
not be used in a production environment. In a production environment you will
need to delete the loaded ActiveViewLink and TableViewDescriptor individually.
This can be done while the system is running, and things should continue to work.

Configuring Tables - Optimizing a Query Based on the View


If a query should be optimized for a specific table view, a call can be made to get
the current selected view for a given table id allowing the query to adjust
accordingly.
//The result is the resource bundle key that has the localizable
names of the view.

String result =
com.ptc.core.htmlcomp.components.TableViewBean.getCurrentView("car
ambola.appcontext.report");

Configuring Tables - Available Attributes


The AvailableAttributes.xml files define the attributes available for each type.
Adding or removing attribute definitions from this file will affect the list of
attributes available when creating or editing table views. The main
AvailableAttributes.xml file is located at:
\wt_ma_services\modules\CoreHtmlComp\src_web\com\ptc\core\
htmlcomp\createtableview\AvailableAttributes.xml

It is recommended that you define customized attributes in a new file and then
register that file as follows in your site.xconf:
<AddToProperty
name="com.ptc.core.htmlcomp.createtableview.AvailableAttributesDig

Presenting Information in the UI 14-55


ester.fileLocation" value="ext/config/attributes/MyPart-
Attributes.xml" />

To derive the list of available attributes, the available attributes factory first asks
your configurable table instance for the list of available types. Using this type list
it then builds a list of attribute definitions from those defined in
AvailableAttributes.xml for each type.

Debugging
To view debugging information about available attributes, set the following
Log4J properties:
log4j.logger.com.ptc.core.htmlcomp.createtableview.AvailableAttrib
uteFactory=TRACE

log4j.logger.com.ptc.core.htmlcomp.createtableview.AvailableAttrib
uteCache=TRACE

log4j.logger.com.ptc.core.htmlcomp.util.TypeHelper=TRACE

log4j.logger.com.ptc.core.htmlcomp.createtableview.labels=TRACE

To view a listing of available attributes for a given type, use the following report:
http://<machine
name>/<WindchillAppName>/netmarkets/jsp/carambola/createtableview/
availableAttributesReport.jsp

Attribute Labels
Any label defined in the AvailableAttributes.xml will be used first. After that the
com.ptc.core.htmlcomp.jstable.JSStandardColumnDescriptorFactory is used. The
JSStandardColumnDescriptorFactory can retrieve attribute labels for certain
common attributes. It is not recommended to edit the
JSStandardColumnDescriptorFactory to accommodate attribute labels for
Windchill Client Architecture table views.
If the JSStandardColumnDescriptorFactory can not find a label for the attribute, it
will attempt to find a label in com.ptc.core.ui.componentRB using the JCA id as
the key. If it still can not find a label for the attribute, it will use the label retrieved
from introspection.

14-56 Windchill Customizer’s Guide


AvailableAttributes.xml Syntax

• Map Tag
Defines attribute id mappings between legacy JS Tables and Windchill Client
Architecture ids. JS ids are defined in JSPropertyDataConstants and are
needed to maintain backward compatibility with older CADX tables.
Windchill Client Architecture ids should match those used for data utilities.
Child of the Class tag.

Syntax Element Description

id Windchill Client Architecture id. Required.

jsId JS id. Required.


<Map id="type_icon" jsId="objType"/>

• Class Tag
Encompasses attribute definitions for the declared type.

Syntax Element Description

name The type. This can be either a hard or soft type and
should be formatted as a TypeIdentifier. Required.
<Class name="wt.part.WTPart">

• Attribute Tag
Defines an attribute for the given type causing this attribute to be available to
users when they are creating and editing table views. Child of the Class tag.

Syntax Element Description

id Windchill Client Architecture id. This should match


the id that id mappings for things such as validators or
data utilities are mapped to. Required.
<Attribute id="description"/>

schemaId If the id does not match the modeled attribute name,


the schemaId should be set to the attribute name. This
id needs to work with both webjects (logical attribute
should exist) and BeanUtils (getter and setter should
exist for the type).
<Attribute id="creator"
schemaId="creator.name"/>

Presenting Information in the UI 14-57


Syntax Element Description

type The type of the attribute. This will affect what kind of
criteria is available when creating filter criteria.

boolean Displays a true or false dropdown.

date Displays the date picker.

list Displays a drop down of the enumerated type values.


See enumClass.

text Displays a text field.


<Attribute id="iterationInfo.latest"
type="boolean"/>

enumClass When type is set to "list", an EnumeratedType class


must be supplied to populate the list of possible
values.
<Attribute id="category"
schemaId="theCategory" type="list"
enumClass="wt.change2.Category"/>

• Include Tag
Includes the attribute definitions defined within another Class tag. Child of
the Class tag.

Syntax Element Description

name The name of the class to include attribute definitions


from. Required.
<Include
name="wt.enterprise.RevisionControlled"/>

• Label Tag
Defines a key and a resource bundle or EnumeratedType to retrieve the
attribute's label from. Child of the Attribute tag.

Syntax Element Description

resource Resource bundle location.


<Label resource="com.ptc.core.ui.viewRB"
key="ICON"/>

14-58 Windchill Customizer’s Guide


Syntax Element Description

enumClass Enumerated type class to retrieve label from.


<Label enumClass="wt.project.Role"
key="CHANGE ADMINISTRATOR I"/>

key Key of attribute label within the supplied resource.


Required.
<Label resource="com.ptc.core.ui.viewRB"
key="ICON"/>

Troubleshooting Common Attribute Problems


• The label of my attribute is "???attribute id???" in the create/edit view wizard
available column list
Enable the table view label logging:
log4j.logger.com.ptc.core.htmlcomp.createtableview.labels=TRACE

Review the process used to find attribute labels and ensure the label for your
attribute is defined in one of those locations.
• The column name in my table is incorrect
Try enabling the common components label logging:
log4j.logger.com.ptc.core.components.labels=TRACE

It is up to the data utility defined to retrieve the label for the table column
header.
• When I edit my OOTB view, my attribute does not appear as a selected
column despite being included in the active view
If you've edited your OOTB view definitions, you need to reset your table
views. Otherwise it is possible that the table view class is loading OOTB
views with incorrect ids. Ensure you are using the ids defined in
DescriptorConstants.ColumnIdentifiers.

Configuring Tables – Enable Scrolling


The table can be made scrollable by using the “scroll” attribute of the renderTable
tag. You can provide a boolean value for this attribute. “true” value will provide
scrolling whereas “false” does not.
<renderTable model="${tableModel}" scroll="true" />

Configuring Tables – Accessibility compliance


If developers are writing any custom code that generates HTML (e.g. data utility
generating HTML), then it should be ensured that the html is Section 508

Presenting Information in the UI 14-59


compliant. Section 508 compliance standards provide guidelines to generate
accessible HTML. The default HTML generated by Table component is
complying to these standards.

Configuring Tables – Enable Table Count


The number of objects in the table (count) is normally provided in the title bar
area. You can remove this using the “showCount” attribute of the renderTable tag.
It takes a boolean value. “true” value will provide the table count whereas “false”
does not.
<renderTable model="${tableModel}" showCount="true" />

Configuring Tables – Hiding column of the table


Table component gives us the flexibility to hide any of the column displayed the
in the table as per the user requirement. This can be done by setting the value of
the attribute “hidden” to true in the tag <jca:describeColumn> . By default, this
value is false. The code for the same is as follows.
<jca:describeColumn id="number" hidden="true"/>

Configuring Tables – Display view all link


The Table footer can display “View Entire List” link, which would allow the user
to see the entire data. When “View Entire List” link is displayed, Pagination is not
displayed. To enable this link, specify “viewAllLink” parameter in
<renderTable>.
<jca:renderTable model="${tableModel}"
viewAllLink="netmarkets/jsp/work/listAssignments.jsp"
helpContext="Overview_Assignments_Help"
showPagingLinks="${tableShowPagingLinks}"
pageLimit="${param.maxRows}"/>

You must specify the jsp name in the "viewAllLink" parameter. When the user
clicks on "View All" in the Table footer, the user is taken to the JSP mentioned in
this parameter and that JSP would display list of all items in the Table. All the
Home -> Overview tables use "viewAllLink" parameter. You can disable the
footer by adding "jcaPageModel.setPageFooter("false")" in the jsp after the
include of begin.jspf.

Configuring Tables – Customize Preferences


To see Table preferences, navigate to Utilities Page > Preference Manager.
One can see a section of table related properties.

Some of the available Table preferences are:

14-60 Windchill Customizer’s Guide


• Assignment Table Size: Indicates the actual number of assignments to fetch.
This preference is ignored if it is less then the overview table size.
• Overview Table Size: The overview sub tab under the home tab contains three
summary tables with limited rows in them. This preference controls the
number of rows in these tables. The default is seven.
• Paging Limit for Tables: Controls the number of rows to display per page in
tables that have paging. It only affects tables that have paging turned on by
default. The number of rows per page can be temporarily overridden by using
the all link in the paging section.
• View All Table Size Limit: View All Table Size Limit

Configuring Table - Freeze Column and Selected Only view


Tables can be configured so as to support "Freeze Column" and "Selected Only"
view. It's a toolbar level menu which allows user to freeze columns there by
switching to "Freeze column" menu as well as "Unfreeze" those there by
switching to "Unfreeze Columns" menu. The "Freeze columns" menu can be
configured either through view manager (for table with views) and through
"isFreezable" attribute of tag "describeTable". (For tables without view) .
The selected only menu allows user to select multiple rows across multiple pages.
User when switches to "Selected only" view, can see the rows across multiple
pages in "Full List" mode. The selected only view is enabled only when the table
has rows which are multi selectable.

Limitations
None.

Presenting Information in the UI 14-61


Sample Code
<%@ include file="/netmarkets/jsp/util/begin.jspf"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/carambola" prefix="cmb"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/core" prefix="wc"%>

<fmt:setLocale value="${localeBean.locale}"/>
<fmt:setBundle basename="com.ptc.carambola.carambolaResource"/>
<fmt:message var="tableName" key="PART_TABLE_LABEL"/>
<fmt:message var="actionsName" key="ACTIONS_COLUMN_LABEL"/>

<%-->Build a descriptor and assign it to page variable tableDescriptor<--%>


<describeTable var="tableDescriptor" type="wt.part.WTPart"
id="netmarkets.test.table" label="${tableName}" >
<describeColumn id="name"/>
<describeColumn id="number"/>
</describeTable>

<%-->Get a query command and assign it to page variable queryCommand<--%>


<cmb:getTypeInstanceCommand var="queryCommand" descriptor="${tableDescriptor}"/>

<%-->Get a table model using our descriptor and query command, assign model to page
variable tableModel<--%>
<getModel var="tableModel" descriptor="${tableDescriptor}"
queryCommand="${queryCommand}"/>

<%-->Render the table model<--%>


<renderTable model="${tableModel}"/>

<%@ include file="/netmarkets/jsp/util/end.jspf"%>

14-62 Windchill Customizer’s Guide


Examples of Usage in Windchill Code
Table Description Location

Search results table This table can be accessed by JSP:


executing simple or advance <Windchill>/netmarkets/jsp/se
search. arch/executeSearch.jsp

Folder browser table for This table can be accessed by JSP (For Product tab):
Project, Product, Organization clicking on “Folders” subtab <Windchill>/netmarkets/jsp/pr
from oduct/listFiles.jsp
Program/Product/Project/Orga
nization tab.

Assignments table on Home -> This table can be accessed by JSP:


Overview clicking on Overview subtab on <Windchill>/netmarkets/jsp/w
Home tab. ork/listOverviewAssignments.j
sp

Tabular Input – Edit Structure This table can be accessed by JSP:


clicking “Edit structure” action <Windchill>/netmarkets/jsp/pa
on any part info page. rt/tabular_input.jsp

Search Criteria / Query Builder This table can be accessed by JSP:


Table clicking Advanced Search. <Windchill>/codebase/netmar
kets/jsp/search/queryBuilder.js
p

Other Resources
• Adding Actions and Hooking Them Up in the UI chapter (starting on page
12-1)
• Customizing the UI with Ajax (on page 11-4)
• Data Acquisition Configuration Properties (on page 13-2)

Presenting Information in the UI 14-63


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

– Collapse action enlarged to show detail

14-64 Windchill Customizer’s Guide


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.

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.

Scope/Applicability/Assumptions
It is assumed that your <MyPage>.jsp file in which you are implementing the
Windchill Client Architecture tree includes “/netmarkets/jsp/begin.jspf” file and
“/netmarkets/jsp/end.jspf” files

Presenting Information in the UI 14-65


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:
• JSP, JavaScript and Custom taglibs.
• The actions framework in the Windchill client architecture.
• Windchill Client Architecture Table component.
• Configuring views.
• Data acquisitions, Data Utility, GUI component.

14-66 Windchill Customizer’s Guide


Solution Elements

Element Type Description

<your_page>.jsp JSP Your Windchill Client Architecture Tree


implementation JSP file.

<your>service.properties.x xconf DataUtilities and services are defined here.


conf

<your>action.rbInfo rbInfo Action attributes defined here.

<your>actions.xml xml Actions can be defined here.

<your>actionModels.xml xml Action models can be defined here.

Another key constituent in the solution is the TreeHandler, which is responsible


for populating the tree content. These are the methods of a TreeHandler that you
must implement:
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 icon 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

Presenting Information in the UI 14-67


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() throws WTException {

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

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 it’s 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.
In the given example, the method first checks to see if the configSpec is not
initialized from the previous method. If it isn’t, then it calls the
getDefaultConfigSpec method, which gets the default ConfigSpec from the

14-68 Windchill Customizer’s Guide


WTPart class via the ConfigHelper. A Map variable named “result” is then
initialized. This will store the mapping of the child nodes for each of the parent
nodes and is returned. A three-dimensional array is also initialized using the
getUsesWTParts method from the WTPartHelper class. This method navigates
from many “used-by” parts (parents) to their “uses” part masters (children) and
applies a ConfigSpec to select the Iterations of the uses parts. It returns a 3D array
of Persistable objects where the first dimension corresponds to the used-by parts
passed in. The second dimension corresponds to the part usage links from the
used-by part. The third dimension is a two element array where [0] is the
WTPartUsageLink and [1] is the uses WTPart or WTPartMaster if the ConfigSpec
did not select an iteration of the uses part. After the 3D array is initialized, it
continues by iterating through the List of parent nodes. A 2D array of Persistable
named “branch” is initialized that stores the child nodes of the given parent if any
exist. If no children exist, it will continue to the next iteration. If children do exist,
they are added to an ArrayList named “children.” Lastly, the parent nodes with its
corresponding children are added to the Map, and the Map is returned.
public Map<Object,List> getNodes(List 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,
//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);

Presenting Information in the UI 14-69


Custom tree handlers need to be registered. Following is a sample tree handler
entry.
<Service context="default"
name="com.ptc.core.components.beans.TreeHandler">
<Option requestor="your_object"
selector="your_treeHandler"
serviceClass="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 doesn’t 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 see the NmObject Utilities section in the Gathering the Data for the UI
chapter on page 13-15 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.

Procedure – Configuring Windchill Client Architecture Tree

Building the shell - Include necessary artifacts


You should include the necessary artifacts in your configuring JSP file e.g.
“/netmarkets/jsp/begin.jspf” and “/netmarkets/jsp/end.jspf” file. You also need to
declare tree taglib directive.
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>
<%@ include file="/netmarkets/jsp/util/begin.jspf"%>

------
------
<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Configure Tree
This can be structured into three steps
1. Creating tableTree descriptor object using describeTableTree tag.
a. This tag creates the tableTree descriptor object and assigns it to the page
variable specified by the var attribute
b. The id attribute stores the identifier for this table descriptor.

14-70 Windchill Customizer’s Guide


c. The label attribute is the localized label for this component and is
displayed as the table header in the UI.
d. The columns in the table are produced by adding the describeColumn
subtag. The id attribute for this tag is used to look up default properties
for the column.
<jca:describeTableTreeid="wcaDemo_tree_example4"
var="wcaDemo_tree_descriptor4"
type="wt.part.WTPart"
label="${treeName}"
nodeColumn="number"
configurable="true"
expansion="full"
helpContext="DEFAULT_HELP_PAGE"
disableAction="false"
summary="test">
<jca:setComponentProperty key="selectable" value="true"/>
<jca:setComponentProperty key="actionModel"
value="wcaDemo_tree_toolbar"/>
<jca:describeColumn id="number" />
<jca:describeColumn id="name" />
</jca:describeTableTree>

2. Defining the component model by passing the tableTree descriptor into the
getModel tag.
a. This takes the tableTree descriptor to get the tableTree data and returns a
model object that will be used to render the tree
b. The tableTree descriptor variable must be specified in the descriptor
attribute.
c. The treeHandler attribute is used to specify the JAVA API service class
that retrieves the tree data.
<jca:getModel var="wcaDemo_tree_model4"
descriptor="${wcaDemo_tree_descriptor4}"
treeHandler="wcaDemoTreeHandler1"/>

3. Rendering the tableTree by passing the model object into the renderTableTree
tag.
a. The variable for the model object specified in the getModel tag gets
passed into the model attribute.
b. If the model attribute is not specified, then a NmHTMLTableTree must
be specified using the tree attribute instead.
jca:renderTableTree model="${wcaDemo_tree_model4}"
showTreeLines="true" />

Your entire JSP will be


<%@ taglib uri="http://www.ptc.com/windchill/taglib/component"
prefix="jca"%>

Presenting Information in the UI 14-71


<%@ include file="/netmarkets/jsp/util/begin.jspf"%>

----
----
<!-- TREE CONFIGURE START -->
<%-->Build a descriptor and assign it to page variable
treeDescriptor<--%>
<jca:describeTableTree id="wcaDemo_tree_example4"
var="wcaDemo_tree_descriptor4"
type="wt.part.WTPart"
label="${treeName}"
nodeColumn="number"
configurable="true"
expansion="full"
helpContext="DEFAULT_HELP_PAGE"
disableAction="false"
summary="test">
<jca:setComponentProperty key="selectable"
value="true"/>
<jca:setComponentProperty key="actionModel"
value="wcaDemo_tree_toolbar"/>
<jca:describeColumn id="number" />
<jca:describeColumn id="name" />
</jca:describeTableTree>

<%-->Get a component model for our tree<--%>


<jca:getModel var="wcaDemo_tree_model4"
descriptor="${wcaDemo_tree_descriptor4}"
treeHandler="wcaDemoTreeHandler1"/>

<%-->Render the NmHTMLTableTree from the command<--%>


jca:renderTableTree model="${wcaDemo_tree_model4}"
showTreeLines="true" />
<!-- TREE CONFIGURE END -->
----
----

<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Customization Points

describeTableTree tag attributes


describeTableTree describes a tree component that can be plugged into Windchill
Client Architecture getModel tag. Its tag class is

14-72 Windchill Customizer’s Guide


com.ptc.core.components.tags.components.DescribeTableTreeTag and the body
content is “scriptless.”

Parameter Default Value Possible Values Req? Description

id - Any Yes The identifier for this tree descriptor.


java.lang.String If this tree supports configurable
value views, then this id may be used to look
up the view configurations, unless it is
overridden by configurableTableId
attribute. This id is also used to define
the NmObjectUtility for the tree if
required.

var - Any Yes Name of the exported scoped variable


java.lang.String for the descriptor. The type of the
value variable is
com.ptc.core.components.descriptor.
ComponentDescriptor.

scope request Can be (case- No The name of the scope to export the
insensitive): var attribute to.
“page”, “request”,
“session” or
“application”

type - - No Name of the main type of object


displayed in this tree. This can be
either a modeled or a soft type. When
specified, the infrastructure will use
the type to look up labels and other
default values when it can't find them
otherwise.

label - Any No A localized display label for this


java.lang.String component
value

mode VIEW No The name of one of the modes defined


in the
com.ptc.core.ui.resoureces.Compone
ntMode enum.

componentType TABLE - No The name of one of the component


types defined in the
com.ptc.core.ui.resoureces.Compone
ntType enum.

nodeColumn “name” column - No The name of the column that will be


used to display node labels. The
column value must be an NmString or
a TextComponent.

Presenting Information in the UI 14-73


Parameter Default Value Possible Values Req? Description

configurable “false” boolean No Whether or not this tableTree supports


configurable views.

viewId - - No The id to use to look up configurable


views. If unspecified, then defaults to
the tree id. Only used if configurable
is set to "true"

singleViewOnly “false” boolean No Determines whether to launch the


view manager or view edit wizard.
The edit wizard is launched directly
when you have a tree that does not
support having multiple views, but
still wants to allow the user to select
columns and set sort order.

toolbarName - Any No The name of the action model to use


java.lang.String for toolbar actions.
value

menubarName - Any No The name of the action model to use


java.lang.String for menubar actions.
value

helpContext - Any No The help context for this tree. No help


java.lang.String icon will be displayed if no help
value context is specified.

14-74 Windchill Customizer’s Guide


Parameter Default Value Possible Values Req? Description

targetObject No Allows the developer to provide more


objects for a tree row. Typically, the
infrastructure treats each index of the
array returned by the getModel tag's
API as a "row" object. This row object
is passed to each column's
DataUtility. If a different object is
needed for some DataUtilities then
that object can be specified as the
targetObject in the describeTableTree
or describeColumn tag. The original
row object must have a getter method
for the name specified as the target
object. (i.e.
targetObject="my_related_part"
would mean the object needs a
getMy_related_part() method).
The target object will be used in the
following places:
• The row object supplied to data
utilities.
• The object that soft attributes
will be extracted from
• The context object for the row
checkbox

selectionObject No Deprecated

summary - String No A localized summary of this table,


which is used for accessibility
compliance.

expansion full “none”, “one” or No Controls the initial expansion level of


“full” the tree.
none (fully collapsed),
one (first level of tree is expanded),
full (tree is fully expanded).

disableAction false boolean No Flag to indicate enable or disable


collapse/expand action.

getModel tag attributes


getModel Creates a component model based on the supplied component
descriptor. The resulting model is assigned to a scoped variable specified by the
var attribute. Its tag class is

Presenting Information in the UI 14-75


com.ptc.core.components.tags.components.GetModelTag and the body content is
“scriptless.”

Paramter Default Value Possible Values Req?

var - Any Yes Name of the exported scoped


java.lang.String variable for the descriptor.
value

scope request Can be (case- No The name of the scope to export the
insensitive): “page” var attribute to.
, “request”,
“session” or
“application”

descriptor - Is of Type Yes The descriptor to base the


com.ptc.core.comp component model on
onents.descriptor.C
omponentDescript
or

treeHandler - - No The selector for the TreeHandler to


use to build the data model. The
tree handler should be registered in
application context

renderTableTree tag attributes


renderTableTree renders a netmarkets tree. If the var attribute is set, then the tag
will set a page-scoped attribute with an NmHTMLTableTree based on the
supplied ComponentModel. If the var tag is empty, then the NmHTMLTableTree
is created and drawn. The tag also supports drawing a pre-built
NmHTMLTableTree by specifying the tree attribute. Its tag class is
com.ptc.core.components.tags.components.RenderTableTreeTag and the body
conetent is “scriptless.”

Paramter Default Value Possible Values Req?

var - Any No The name of the scoped variable to


java.lang.String assign the NmHTMLTableTree to.
value If this is not specified, then the tree
is drawn by the tag.

scope request Can be (case- No The name of the scope to export the
insensitive): “page” var attribute to.
, “request”,
“session” or
“application”

14-76 Windchill Customizer’s Guide


Paramter Default Value Possible Values Req?

model - Of type No The component model to create


com.ptc.core.comp (and optionally draw) an
onents.descriptor.C NmHTMLTableTree from. If
omponentModel unspecified, then an
NmHTMLTableTree must be
specified using the tree attribute.

tree - Of type No The NmHTMLTableTree to


com.ptc.netmarkets render. If this is not specified, then
.util.treetable.NmH a ComponentModel must be
TMLTableTree specified from which a tree will be
created.

helpContext - Any No The help context for this tree. No


java.lang.String help icon will be displayed if no
value help context is specified.

useTrail false boolean No Whether or not to trail-enable links


in the tree.

preferenceConte - - No The preference context for this tree


xt

singleSelect false boolean No Single Select mode. Use Radio


buttons or checkboxes for the row
selection.

showCustomVie true boolean No Determines whether or not to show


wLink the customize view link in the view
drop down.

scroll false boolean No Specifies that the table should use


scrollbars to keep the header and
actions in view when looking
down at the items in the bottom of
the table.

showCount true boolean No Optionally show the count of


objects in the table title area.

rowBasedObject false boolean No Whether objectHandles are needed


Handle for each row. By default, the value
of this attribute is false. Set to true
to render a table for
creating/editing multiple objects in
a create/edit wizard.

afterJS No JavaScript method to execute after


the table has been rendered or re-
rendered as a result of sorting etc.

Presenting Information in the UI 14-77


Paramter Default Value Possible Values Req?

showPagingLink false No Determines whether the tree is


s paged.

pageLimit No The number of rows to display per


page in the tree.

showTreeLines false boolean No Determines if tree lines will be


displayed to show structure in the
tree

fullListLimit integer The maximum number of rows to


display per page in the tree when
the full list action is clicked. The
number can be set to a level so as to
keep the browser from crashing.

useJSCA false boolean It is used to get some out of the box


features; explained in the
Configuring Tree - useJSCA
property section on page 14-88

Configuring Tree – Defining Node Column


The id of the column that you want to display node labels should be given to the
nodeColumn attribute from the describeTableTree tag.
<jca:describeTableTree id="wcaDemo_tree_example4"
var="wcaDemo_tree_descriptor4"
type="wt.part.WTPart"label="${treeName}"
nodeColumn="number"
configurable="true"expansion="full"
--------->
------
</jca:describeTableTree>

Configuring Tree – Adding ToolBar


To add a tool bar, the toolbarName attribute from the describeTableTree tag must
be included. The name of action model to use for the tool bar actions is specified
in this attribute.
<jca:describeTableTree id="wcaDemo_tree_example5"
var="wcaDemo_tree_descriptor5"
type="wt.part.WTPart" label="${treeName}"
nodeColumn="number" configurable="true"
singleViewOnly="true"expansion="one"
disableAction="false"
menubarName="wcaDemo_tree_menubar"
toolbarName="wcaDemo_tree_toolbar" >
------
</jca:describeTableTree>

14-78 Windchill Customizer’s Guide


Adding toolbar to a tree can also be achieved by using setComponentProperty tag.
It’s a helper tag that sets properties on the component descriptor managed by a
parent describe tag. The key attribute and the value attribute are the key and value
for the properties map of the target ComponentDescriptor, respectively. 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.
Please see the Windchill Client Architecture Action Framework Overview section
in the Adding Actions and Hooking Them Up in the UI chapter on page 12-1 for
more information.
<jca:describeTableTree id="wcaDemo_tree_example4"
var="wcaDemo_tree_descriptor4" type="wt.part.WTPart"
label="${treeName}" nodeColumn="number"
configurable="true" expansion="full"
helpContext="DEFAULT_HELP_PAGE"
disableAction="false" summary="test">
<jca:setComponentProperty key="actionModel"
value="wcaDemo_tree_toolbar"/>
------
</jca:describeTableTree>

Configuring Tree – Adding MenuBar


To add a menu bar, the menubarName attribute from the describeTableTree tag
must be included. The name of action model to use for the menu bar actions is
specified in this attribute.
<jca:describeTableTree id="wcaDemo_tree_example5"
var="wcaDemo_tree_descriptor5"
type="wt.part.WTPart" label="${treeName}"
nodeColumn="number" configurable="true"
singleViewOnly="true"expansion="one"
disableAction="false"
menubarName="wcaDemo_tree_menubar"
toolbarName="wcaDemo_tree_toolbar" >
------
</jca:describeTableTree>

Presenting Information in the UI 14-79


Configuring Tree – Adding Row Level Actions
To add row level actions column, you need to define a column using
describeColumn which has id=”nmActions”. Using the setComponentProperty
tag, set the actionModel. Please refer Refer <Action/ ActionModel Document>
for more information.
<jca:describeTableTree id="wcaDemo_tree_example2"

var="wcaDemo_tree_descriptor2"

type="wt.part.WTPart" label="${treeName}"

nodeColumn="name" expansion="one">

-------------

<jca:describeColumn id="nmActions" label="Actions" sortable="false">

<jca:setComponentProperty key="actionModel" value="read only BOM"/>

</jca:describeColumn>

</jca:describeTableTree>

Configuring Tree – Enabling selectable rows


Making the rows selectable can be easily done by adding another
setComponentProperty tag. The key attribute must be set to “selectable” and the
value attribute must be set to “true”
<jca:describeTableTree id="wcaDemo_tree_example2"
var="wcaDemo_tree_descriptor2"
type="wt.part.WTPart" label="${treeName}"
nodeColumn="name" expansion="one">
<jca:setComponentProperty key="selectable" value="true"/>
<jca:describeColumn id="name" />
--------
</jca:describeTableTree>

Windchill Client Architecture Selectable & Non-Selectable Trees

14-80 Windchill Customizer’s Guide


Configuring Tree – Enabling sort able columns
Making the columns sortable can be done by using the “sortable” attribute of
describeColumn tag. The value attribute must be set to “true” to make it sortable
and “false” to make it non-sortable.
<jca:describeColumn id="name" sortable="false"/>

Configuring Tree – Specify DataUtility for columns


To specify the data utility for a column can be done by using “dataUtilityId”
attributes of the descriveColumn tag.
<jca:describeColumn id="columnId"
label="${columnName}"

dataUtilityId="your_column_data_utility_id" />

Custom data utilities need to be registered. Following is a sample data utility


entry.
<Service name="com.ptc.core.components.descriptor.DataUtility">
<Option serviceClass="your_data_utility_class"
requestor="your_object"
selector="your_column_data_utility_id"
cardinality="duplicate"/>
</Service>

Configuring Tree – Enabling views


1. To make a tree configurable you must explicitly specify that while defining
the tableTree descriptor. This can be done by adding a configurable="true"
attribute to the describeTableTree Tag.
2. Your view implementation needs to be registered in application context in
order for the infrastructure to find it. If you have specified “viewId” attribute
explicitly, then that should be used as the selector, if not “id” attribute.
<jca:describeTableTree id="wcaDemo_tree_example5"
var="wcaDemo_tree_descriptor5" type="wt.part.WTPart"
label="${treeName}" nodeColumn="number"
configurable="true"
------
configurableTableId="wcaDemo_tree_viewId1">
--------
</jca:describeTableTree>

3. Custom view implementation helpContext keys need to be registered.


Following is a sample entry.
<Service context=”default”
name="com.ptc.core.htmlcomp.tableview.ConfigurableTable">
<Option serviceClass="your_ConfigurableTableImpl_class"
requestor="your_object"
selector="your_view_id" />
</Service>

Presenting Information in the UI 14-81


4. When implementing getOOTBTableViews and defining out-of-the-box
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 Attribute Report:
http://<server>:<port>/<context>/netmarkets/jsp/carambola/creat
etableview/availableAttributesReport.jsp

5. You can control the visibility of “Customize …” link in the view drop down
by using “showCustomViewLink” attribute of renderTableTree tag. “false”
hides the link whereas “true” shows the link which is the default behavior.
<jca:renderTableTree model="${wcaDemo_tree_model6}"
showCustomViewLink ="true" />

6. If the tree has only one view and you want to modify the columns (visibility,
order etc), you need to set “singleViewOnly” attribute of describeTableTree
tag to true.
<jca:describeTableTree id="wcaDemo_tree_example5"
var="wcaDemo_tree_descriptor5" type="wt.part.WTPart"
label="${treeName}" nodeColumn="number"
configurable="true" singleViewOnly ="true"
------
configurableTableId="wcaDemo_tree_viewId1">
--------

14-82 Windchill Customizer’s Guide


</jca:describeTableTree>

Tree with views

Tree with single view customize

Configuring Tree – Control Level of Tree Expansion


When the Tree is populated and presented for the first time, you can control the
level to which it’s expanded.
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.
<jca:describeTableTree id="wcaDemo_tree_example5"
var="wcaDemo_tree_descriptor5" type="wt.part.WTPart"
label="${treeName}" nodeColumn="number"
expansion=”none”
------ >
--------
</jca:describeTableTree>

Configuring Tree – Adding Help


Tree can be enabled with “help” either by using describeTableTree tag or by using
renderTableTree tag. If you define using both the tags, the latter will be respected.
<jca:describeTableTree id="wcaDemo_tree_example4" -----
helpContext ="your_help_context_key" >
------
</jca:describeTableTree>

Presenting Information in the UI 14-83


<jca:renderTableTree model="${wcaDemo_tree_model4}"
helpContext ="your_help_context_key" />

Custom helpContext keys need to be registered. Following is a sample


helpContext key entry.
<Service context="default" name="wt.help.HelpTemplate">
<Option requestor="your_object"
selector="your_help_context_key"
resource ="online.cust.helpFile"/>
</Service>

This means that the help file is


$WT_HOME/codebase/wt/helpfiles/help_<locale>/online/cust/helFile.html

Configuring Tree – Hide Expand/Collapse icon


Expand/collapse icon presentation is controlled by using “disableAction” attribute
of the describeTableTree tag. You can provide a boolean value for this attribute.
“true” value will present the expand/collapse icon whereas “false” value will hide
them.
<jca:describeTableTree id="wcaDemo_tree_example3"
var="wcaDemo_tree_descriptor3"
type="wt.part.WTPart" label="${treeName}"
nodeColumn="name" expansion="none"
disableAction="true" ---->
------
</jca:describeTableTree>

Configuring Tree – Enable Scrolling


The tree can be made scrollable by using “scroll” attribute of the renderTableTree
tag. You can provide a boolean value for this attribute, “true” value will provide
scrolling whereas “false” not.
<jca:renderTableTree model="${wcaDemo_tree_model2}" scroll="true"
……… />

Configuring Tree – Set single/multi select


The tree’s row selection is controlled by using “singleSelect” attribute of the
renderTableTree tag. You can provide a boolean value for this attribute, “true”
value will present the tree in a single select (radio buttons) mode whereas a “false”
value will present it in a multi select (checkboxes) mode.

14-84 Windchill Customizer’s Guide


<jca:renderTableTree model="${wcaDemo_tree_model2}"
singleSelect="true" ……… />

Single & multi select Windchill Client Architecture Tree

Configuring Tree – Enable Tree Count


The number of objects in the tree(count) is normally provided in the title bar area.
You can remove them using “showCount” attribute of the renderTableTree tag. It
takes a boolean value. “true” value will provide the tree count whereas “false”
does not.
<jca:renderTableTree model="${wcaDemo_tree_model3}"
showCount="false" ……… />

Configuring Tree – Enable Tree Lines


You can show tree lines to display the structure in the tree by using
“showTreeLines” attribute of the renderTableTree tag.

Presenting Information in the UI 14-85


<jca:renderTableTree model="${wcaDemo_tree_model2}"
showTreeLines="true" ……… />

Windchill Client Architecture Tree with and without Tree Lines & Count

Configuring Tree – Disable selection for some tree rows


You may require your tree to be presented with some rows pre-selected. This can
be achieved by using getNonSelectables tag in combination with renderTableTree
parent tag.
The name of the service class that does the processing should be provided for the
“className” attribute and the name of the method should be provided for the
“methodName” attribute. The signature of the method should be
public static ArrayList<NmOid> your_method_name( NmModel nmModel )
throws WTException
1. Create NmHTMLTableTree from component model.
<jca:renderTableTree var="wcaDemo_tree_nmModel6"
model="${wcaDemo_tree_model6}" >
<jca:getNonSelectables className =
"com.ptc.carambola.svc.wcaDemoTreeHandler2"
methodName ="getPartNonSelectables" />
</jca:renderTableTree>

2. Render the NmHTMLTableTree

14-86 Windchill Customizer’s Guide


<jca:renderTableTree tree="${wcaDemo_tree_nmModel6}"
model="${wcaDemo_tree_model6}"/>

public static ArrayList<NmOid> getPartNonSelectables( NmModel


nmModel )
throws WTException {

ArrayList<NmOid> nmOid_list = null;


NmDefaultHTMLTableTree table_tree =
(NmDefaultHTMLTableTree)nmModel;
NmDefaultHTMLTable table =
(NmDefaultHTMLTable)table_tree.getTable();

for (int i = 0; i < table.getRowCount(); i++) {

NmObject nmObj = (NmObject)table.getObject(i);


if(nmObj instanceof NmPart){
NmPart nmPart = (NmPart)nmObj;
//your logic goes here
if((number_string.lastIndexOf("2")!= -1) ||
(number_string.lastIndexOf("4")!= -1) ) {
if(nmOid_list == null)
nmOid_list = new ArrayList<NmOid>();
//add the NmOid into the List
nmOid_list.add(nmObj.getOid());
}
}
}
return nmOid_list;
}

Configuring Tree – Enable the Pagination


There are three ways to make a tree paginated
• Use pageLimit attribute of getModel/getIeModel tag. This usage is highly
recommended for performance reasons. The componentModel that you get
from this tag which will be passed to the renderTableTree will have only
objects specific for the page to be displayed.
• Use pageLimit attribute of renderTableTree tag. Note that this attribute is not
supported in renderSimpleTree tag. If the pageLimit attribute is specified in
getModel/getIeModel, then there is no need to specify it again at this tag
level; even if you have specified it won't be respected.
• Use of the property available in <Windchill>\codebase\wt.properties
com.ptc.netmarkets.treeSizeLimit = <integer value>

Using this you can set the number of rows of a tree in a page and this will be
applicable to all the trees across Windchill system. Its usage is highly
discouraged and in the coming release this property will be deprecated.

Presenting Information in the UI 14-87


Configuring Tree - Describe the scroll type of a tree
You can specify the type of scrollbars on a tree by setting scrollType property in
"describeTableTree" tag.
Possible values of scrollType are
• ""V" for Viewport
• ""D" for DOM
• ""default" for browser default.
<jca:describeTableTree id="wcaDemo_tree_example3" …>

<jca:setComponentProperty key="scrollType" value="V"/>

</jca:describeTableTree>

For popup pages, the default scrollType is DOM. But, it is recommended to use
Viewport. Also. it is recommended to use "Viewport" scrollType in case of non
editable form fields.

Configuring Tree - useJSCA property


You can set useJSCA property to true to get following out of the box features on
tree.
1. Selection across the pages.
a. Selection is persisted across pages for a paginated tree.
If a user selects some objects (say 5) on a page (say page 1), navigates to
some other page (say page 3) and selects some more objects (say 3), than
the row count information in the table footer will show '8 of 120 total
objects selected' (where 120 is the total number of rows in the table across
all pages).
Again if the user navigates back to initial page (i.e. page 1), he / she will
see the objects (i.e. 5) visually selected.
b. Selection is persisted across table paging modes.
If user makes some selections across pages in a paginated tree and moves
to full list view or vice versa, the appropriate objects remain visually
selected.
c. Selection is NOT persisted in case of view change.
If user makes some selections in a paginated tree or full list tree and
decides to change the tree view from the drop down list, the selections
would not be retained. A confirmation alert message will be shown and
the tree view will be changed only if the user agrees to proceed.
d. Table footer row count information will be different for paginated tree
and full list tree.

14-88 Windchill Customizer’s Guide


If the tree is paginated, the row count message shown in the tree footer
will be format 'X of Y total objects selected'. But for the full list trees the
row count message will be 'X objects selected'.
e. Actions can be performed on selections made across pages for a paginated
tree.
The tree toolbar level and menu level actions would be performed on all
the selections that the user has made across all pages of the tree.
f. Client side JavaScript function to fetch all selected object information.
A JavaScript function named getSelectedItems() can be used to fetch
selected objects from all the tree present in a page. Another function
named getJCASelectedTableItems(tableId) can be used to fetch selected
objects for a particular tree.
2. Clear all selections
Clear across pages feature is used to clear all the checkbox selections across
multiple pages.
This feature is provided for the trees where paging is enabled. Clear all
selection feature will be disabled if there are no checkbox selections available
and it will get enable as soon as user selects checkbox. With this feature user
can reduce the pain of deselecting checkboxes individually.
3. Preserving right-left scroll position
– For paging trees
• If the tree had no selected rows:
If the user is on page X then, tree refresh resulted because of sort
action will show the tree vertically positioned at the first row of the
first page.
• If the tree had selected rows:
When the tree is refreshed because of sort action, the tree will page to
the page that contains the last of the pre-sort selected rows. The
selected rows will be retained.
– If the tree is a scrolling tree, i.e. do not have pagination enabled or a full
list tree
• If the tree had no selected rows:
On sort action, the tree will be positioned at the first row in the tree.
• If the tree had selected rows:
On sort action, the table will scroll to show the last row that was
selected. The selections are retained

Presenting Information in the UI 14-89


4. Multi column click to sort
"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.
5. Paging controls in table header
User can add the paging links in header. This option can be set through
preference manager. By default this option is disabled and if set it will display
the paging links in header as well as footer.
6. Find In List
One can find an object in tree.

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

14-90 Windchill Customizer’s 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 Handling on page 14-2 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 14-91


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
documentation 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 object’s 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.

Packaging
The attributes table component itself is located in the Windchill vob under the
CommonComponents module:
ProjectLink\NetMarkets\src_web\netmarkets\jsp\object\attribute.jsp
(the default attributes table)
ProjectLink\NetMarkets\src_web\netmarkets\jsp\util\
showSoftAttribute.jsp (the attributes table component)

14-92 Windchill Customizer’s Guide


Windchill\DevModules\CommonComponents\src\com\ptc\core\components\
beans\AttributesTableBean.java
Windchill\DevModules\CommonComponents\src\com\ptc\core\components\
util\ComponentUtility.java
Windchill\DevModules\CommonComponents\src_web\com\ptc\core\
components\tags\core\TypeBasedImportTag.java
Windchill\DevModules\CommonComponents\src_web\WEB-INF\tags\
core.tag
Windchill\DevModules\CommonComponents\src_web\WEB-INF\tlds\
components.tld

Here are the locations of some example info pages:


ProjectLink/Netmarkets/src_web/netmarkets/jsp/document/attributes.
jsp
ProjectLink/Netmarkets/src_web/netmarkets/jsp/part/attributes.jsp

codebase/netmarkets/jsp/document/attributes.jsp
codebase/netmarkets/jsp/part/attributes.jsp

What is the component


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

Presenting Information in the UI 14-93


Using the component

Create a JSP for your object type


• Creating a JSP
• Registering the JSP

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

Registering 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

14-94 Windchill Customizer’s Guide


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 xconf format:


<!--Info page fragments, Resource is the filepath to a jsp fragment
that will configure the info page -->

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

Presenting Information in the UI 14-95


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

14-96 Windchill Customizer’s Guide


Generating the Name Attribute Server

Objective
You want to make the name attribute server generated.

Background
This section 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/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 Type Description

Site.xconf Configuration Contains the configuration information required.

RuleConfigurableTypeAttribute. Configuration Contains the rule configurable attribute lists for each
properties object type.
codebase/com/ptc/core/rule/server/delegate/init/Rul
eConfigurableTypeAttribute.properties

Presenting Information in the UI 14-97


Element Type Description

GeneratedNameDataUtility Java class The new Data utility that will be created during this
procedure to enable Name to support server
generation.

NumberDataUtility Java class An out of the box data utility that knows how to
handle server generation for the number attribute.

createDocumentSetAttributesWi JSP file \codebase\netmarkets\jsp\document\


zStep createDocumentSetAttributesWizStep.jsp

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>

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>

14-98 Windchill Customizer’s Guide


<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 Administrator 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;
}
}

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 the Implementing a Data Utility section on 14-8 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:

Presenting Information in the UI 14-99


<Configuration
targetFile="codebase/com/ptc/core/components/components.dataUtilit
ies.properties">
<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
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.

14-100 Windchill Customizer’s Guide


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 9-2
• Gathering the Data for the UI on page 13-1
• Attribute Handling on page 14-2

Presenting Information in the UI 14-101


Partial Activation of JSCA
In release 9.1, JSCA is not enabled for all pages. JSCA will be turned on by
default for all display tables and for pickers. JSCA will be turned off (JCA used)
by default for all other tables in wizards or other popups.
You can override this default behavior in an individual JCA table or tree by
adding a new useJSCA param to the renderTable Tag. This parameter is only for
version 9.1 and will will be removed in version 10 when JSCA will be enabled for
for all tables.
Example:
<jca:renderTable model="${tableModel}" pageLimit="-1"
helpContext="CheckedOutTable_help" useJSCA="false"/>

If you want to test how a table works with JSCA vs JCA, you can toggle between
the two with a URL parameter.
If a developer wishes to test to see how a table works with JSCA vs JCA we have
also provided a url param that can be added to toggle the table between JSCA and
JCA. See example below:
Example:
http://machinename.ptcnet.ptc.com/Windchill/netmarkets/jsp/user/li
stCheckedOutWork.jsp?useJSCA=true

The useJSCA URL paramter name is case sensitive but the value is not case
sensitive and it will accept any form of true and false. It will also accept 1 for true
and 0 for false.
JSCA is not enabled by default. You can use the url param above to test single
pages. If you prefer to turn JSCA on as it will be when we ship you can modify the
file
windchill\codebase\WEB-INF\tlds\components.tld

and remove the default that has been temporarily specified to turn jsca off
(remove the line in bold below):
<attribute>
...
<name>useJSCA</name>
<required>false</required>
<type>boolean</type>
<default>false</default>
</attribute>

Note: Old Netmarkets architecture Tables and Trees (those that were not
converted to JCA) are currently using the JSCA rendering and do not at this time
support any methods of going back to the JCA rendering. The current
recommendation is that if you need an old legacy table to use JCA instead of
JSCA you will need to convert the table to JCA and use the tag attribute as
described above.

14-102 Windchill Customizer’s Guide


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 in Rational Rose. This icon
will be used when an object of this type is displayed. In case of soft types, the
Type Manager 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 IconDelegate

wt.part.WTPart com.ptc.windchill.enterprise.part.commands.delegate.
WTPartIconDelegate

wt.epm.EPMDocument wt.epm.identity.EPMDocumentIconDelegate

wt.doc.WTDocument 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/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.

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:

Presenting Information in the UI 14-103


• Java
• Windchill Type Identifiers

Solution Elements

Element Type Description

<custom_IconDelegate>.java java Your IcondDelegate


Run time Location:
<Windchill>\codebase\*

Your xconf file xconf 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
<Windchill>/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>

Authoring the custom IconDelegate


1. You can extend either wt.fc.IconDelegate or an existing subclass of
wt.fc.IconDelegate.
2. There are few API’s that you need to over-ride, where you have to put your
icon determining logic.

14-104 Windchill Customizer’s Guide


a. These two API’s returns an IconSelector object, which holds the
information of the icon for the specific Windchill object.

API Signature Description

public IconSelector Get the standard selector for the icon


getStandardIconSelector()
throws WTException,
IllegalAccessException,
InvocationTargetException;

public IconSelector getOpenIconSelector() Get a selector for when the object is


opened (for example when a folder is
throws WTException,
opened)
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.

API Signature Description

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

Presenting Information in the UI 14-105


sure that they are properly populated when you invoke
getStandardIconSelector() or getOpenIconSelector().

API Signature Description

protected void Update <AttributeTypeIdentifier>


initAttributes(Set<AttributeTypeIdentifier> with attributes that drive-determining
attributes) 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);
}

private static class ObjectParams {

Cabinet cabinet = null;


TypeInstance ti = null;

ObjectParams(Cabinet cabinet){
if(cabinet != null)
this.cabinet = cabinet;
}
ObjectParams(TypeInstance ti){

14-106 Windchill Customizer’s Guide


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


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

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 {
object_params = new ObjectParams(ti);
}
}
return object_params;
}

public IconSelector getStandardIconSelector()


throws WTException, IllegalAccessException,
InvocationTargetException {

Presenting Information in the UI 14-107


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>

14-108 Windchill Customizer’s Guide


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

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 they’ve entered in the current step is

Presenting Information in the UI 14-109


invalid. Post-Submit Validation applies only to wizard steps and wizard
submissions.

Scope/Applicability/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 object’s 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
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.

14-110 Windchill Customizer’s Guide


• 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
you’ll 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 Description

StandardUIComponentValidation Java class Often referred to as the validation service. This is the
Service service class that controls UI Validation. It receives
validation 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.

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

Presenting Information in the UI 14-111


Element Type Description

UIValidationCriteria Java class 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.

UIValidationResult Java class 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 where
validation is being performed for the same action on
multiple objects, a UIValidationResult can be
associated with each object.

UIValidationResultSet Java class 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 pre-validation check for the same action on
multiple objects, it could aggregate the validation
results for each of the objects into a
UIValidationResultSet.

UIValidationStatus Java class 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.

UIValidationFeedbackMsg Java class Often referred to as a feedback message.


This is a message that can be associated with a
validation result. It is only used for post-select
validation and post-submit validation. Any feedback
messages associated with validation results returned by
pre-validation will be ignored.
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.

14-112 Windchill Customizer’s Guide


Element Type Description

UIComponentValidator Java This is the interface that all validator implementations


interface need to implement. However, validators should not
directly implement this interface. Rather, they should
extend DefaultUIComponentValidator.
Each UI component can have zero or one valiadtors
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.

DefaultUIComponentValidator Java class This is a default implementation of the


UIComponentValidator interface. All validator
implementations should extend this class.

ValidationFilter Java This is the interface that all filter implementations need
interface to implement. However, filters should not implement
this interface directly. Rather, they 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-by-component 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.
Filters 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.

Presenting Information in the UI 14-113


Element Type Description

SimpleValidationFilter Java This is the interface that all simple filter


interface implementations need to implement. However, simple
filters should not implement this interface directly.
Rather, they should extend
DefaultSimpleValidationFilter.
Customizers and application developers should not have
to interact directly with this class.

UniversalValidationFilter Java This is the interface that all universal filter


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

DefaultSimpleValidationFilter Java class This is a default implementation of the


SimpleValidationFilter interface. All simple filter
implementations should extend this class.

DefaultUniversalValidationFilter Java class This is a default implementation of the


UniversalValidationFilter interface. All universal filter
implementations should extend this class.

UIComponentSolutionGroup Java This is an interface that all solution group


interface implementations need to implement.
A solution group is a special type of validator that is
used for pre-validation 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.

*actions.xml XML file(s) There are multiple “satellite” versions of actions.xml


files (typically one per module), which contain action
definitions.
It is also in these files that we configure actions to
include simple filters, and exclude universal filters.

*service.properties.xconf XConf file(s) 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.

14-114 Windchill Customizer’s Guide


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.

Client Infrastructure 1

Validation Service

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.

Presenting Information in the UI 14-115


If the cache of invalid solution-based keys contains the current validation key, the
validation service sets the component’s 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.

Cache of invalid
Client Infrastructure components for the
1
installed solutions
2a

Validation Service

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.

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.

14-116 Windchill Customizer’s Guide


If the role-based UI service returns a status of “hidden” or “disabled”, the
validation service sets the component’s 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
pre-validation checks.

Cache of invalid
Client Infrastructure components for the
1
installed solutions
2a

Validation Service
2b

Role-Based UI Service

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.

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.

Presenting Information in the UI 14-117


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
action’s 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 action’s 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

14-118 Windchill Customizer’s Guide


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

Cache of invalid
Client Infrastructure components for the
1
installed solutions
2a

Validation Service
2b

2c
Role-Based UI Service

Applicable Filters

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.

Presenting Information in the UI 14-119


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.

Cache of invalid
Client Infrastructure components for the
1
installed solutions
2a

Validation Service
2b

2c
Role-Based UI Service

2d

Validator

Applicable Filters

14-120 Windchill Customizer’s 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).
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.

Presenting Information in the UI 14-121


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

Cache of invalid
Client Infrastructure components for the
1
installed solutions
2a

3 Validation Service
2b

2c
Role-Based UI Service

2d

Validator

Applicable Filters

14-122 Windchill Customizer’s 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).
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.
3. Return the validation result or validation result set to the client infrastructure.

Presenting Information in the UI 14-123


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.

Client Infrastructure 1

Validation Service

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

14-124 Windchill Customizer’s Guide


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.

Client Infrastructure 1

Validation Service 2

Validator

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 is “denied”, the user is redirected to the previous page, and

Presenting Information in the UI 14-125


if the validator returned a message indicating why the action was denied, that
message is displayed to the user.

Client Infrastructure 1

Validation Service 2

Validator

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.

14-126 Windchill Customizer’s Guide


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 post-
submit validation is much simpler than for pre-validation. In fact, it is nearly
identical to the sequence for post-select validation.
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.

Client Infrastructure 1

Validation Service

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 wizard’s
“Next” or “OK” action.
As is the case with pre-validation and post-select validation, a validator is
associated with a wizard’s “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.
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

Presenting Information in the UI 14-127


associated with the “Next” or “OK” action, the validation service calls that
validator to get a validation status for the action.

Client Infrastructure 1

Validation Service 2

Validator

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 restricted from moving to the next wizard step or submitting the

14-128 Windchill Customizer’s Guide


wizard, and if the validator returned a message indicating why the action was
denied, that message is displayed to the user.

Client Infrastructure 1

Validation Service 2

Validator

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.

Presenting Information in the UI 14-129


Pre-Validation Procedures
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 14-130
• Implementing Solution-Based Pre-Validation on page 14-131
• Implementing Role-Based Pre-Validation on page 14-134
• Implementing Validation Filters on page 14-134
• Implementing Validators for Pre-Validation on page 14-138

Distinguishing between Pre-Validation Statuses


Depending on whether you’re validating actions or attributes, the validation
statuses you’ll 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 you’re implementing a filter or validator to perform pre-validation logic,
you’ll 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 can’t 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.
You’re almost always better off showing a user an action they can’t perform
than hiding an action that they should be able to perform.

14-130 Windchill Customizer’s Guide


• 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
wasn’t checked out, the “check-out” action would be available to the user. In
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 attribute’s name nor value is never displayed
in the UI. The “hidden value” status means that the attribute’s name will be
displayed, but not its value. The “read only” status is used to indicate that an
attribute’s name and value are displayed, but that user may not modify the value.
And the “visible” status is used to indicate that the attribute’s 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
aren’t 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 14-131


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");
}
ArrayList invalidList = new ArrayList();

14-132 Windchill Customizer’s Guide


// if PRO-I is installed, the following UI components are
not valid.
if
(InstalledProperties.isInstalled(InstalledProperties.PRO_I)){
invalidList.add(listKey);
invalidList.add(crKey);
invalidList.add(cnKey);
invalidList.add(viewKey);
}

/*
* ADD ADDITIONAL SOLUTION-BASED CHECKS AS NEEDED
*/

if (logger.isTraceEnabled()){
logger.trace("RETURNING " + (List)invalidList);
}
if (logger.isDebugEnabled()){
logger.debug("EXITING MySolutionGroup.getInvalidKeys");
}
return invalidList;
}
}

If you’re wondering how to determine which values to include in the validation


key factory methods, it depends on whether you’re creating a validation key for an
action or an attribute. If you’re 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" class=""
resourceBundle="com.ptc.core.ui.navigationRB">
<action name="product" renderType="GENERAL">
<command class="netmarkets"
method="servlet/Navigation?tab=product" windowType="page"/>
</action>
...

If you’re 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]"

Presenting Information in the UI 14-133


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
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 Functions - Attribute Visibility section on
page 10-5.

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 you’ll 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.
To implement, it is 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

14-134 Windchill Customizer’s Guide


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, you’ll 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. (NOTE: Obviously, this is an
overly-simplified example. A production-quality class would have exception
handling, logging, etc.)
public class MarkedForDeleteFilter extends
DefaultSimpleValidationFilter{
@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: (NOTE: Obviously, this is an overly-simplified example. A
production-quality class would have exception handling, logging, etc.)
public class MarkedForDeleteFilter extends
DefaultUniversalValidationFilter{
@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;
}

Presenting Information in the UI 14-135


}

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">
<Option
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">
<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 name="markedForDelete" />
</action>

<action name="program" renderType="GENERAL">


<command class="netmarkets"
method="servlet/Navigation?tab=program"windowType="page"/>
<excludeFilter name="markedForDelete" />

14-136 Windchill Customizer’s Guide


</action>

<action name="product" renderType="GENERAL">


<command class="netmarkets"
method="servlet/Navigation?tab=product" windowType="page"/>
<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.

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 name="problemReportStatus" />
</action>
<action name="editModifyContentOnly"
id="editModifyContentOnly">
<command class="…/>
<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 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 />

Presenting Information in the UI 14-137


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

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 you’ll 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 don’t 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 conditions. It’s possible and, in many cases, likely that your
performLimitedPreValidation() and performFullPreValidation() methods will
have the exact same logic.
Limited 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.

14-138 Windchill Customizer’s Guide


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 Explained
On the other hand, suppose you’re pre-validating an action in a “drop-down” list
of actions in a table row, or on an info page. Since we’re 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, we’ll 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.
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
}

Presenting Information in the UI 14-139


Implementing Pre-Validation Methods
Once you’ve created a validator class skeleton, if you’re adding pre-validation
logic for an attribute, you’ll want to implement the
performLimitedPreValidation() method. If you’re adding pre-validation logic for
an action, you’ll 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));

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:

14-140 Windchill Customizer’s Guide


//
resultSet.addResult(UIValidationResult.newInstance(validationKey,
UIValidationStatus.HIDDEN));

return resultSet;
}

Registering Validators
Once you’ve created your validator and implemented the appropriate pre-
validation 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 attribute’s 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>

Once propagated to *service.properties, it should produce an entry like this:


wt.services/svc/default/com.ptc.core.ui.validation.UIComponentVali
dator/[action name/attribute descriptor ID]/null/0=[your fully-
qualified Validator class]/duplicate

• Note that in this case, the requestor attribute is null, meaning the action’s
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 action’s 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.

Presenting Information in the UI 14-141


For example, consider this fragment of an actions.xml file (NOTE: some text
eliminated for readability):
<objecttype name="problemReport" class="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.ChangeMgmtCreateWizardsVali
dator 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.
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.ChangeMgmtCreateWizardsVal
idator) 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" requestor="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

14-142 Windchill Customizer’s Guide


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 com.ptc.core.ui.validation.UIComponentValidatorFactory
pasteAsCopy

Registered validators:
pasteAsCopy ->
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 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 com.ptc.core.ui.validation.UIComponentValidatorFactory
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)

Presenting Information in the UI 14-143


• 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 com.ptc.core.ui.validation.UIComponentValidatorFactory
pasteAsCopy create:problemReport

Registered validators:
pasteAsCopy ->
com.ptc.core.foundation.saveas.validators.PasteValidator

create:problemReport(wt.change2.WTChangeIssue) ->
com.ptc.windchill.enterprise.change2.validators.ChangeMgmtCreat
eWizardsValidator

Procedures – 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 on page 14-139 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 you’re 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 UIValidationResult validateSelectedAction()
(UIValidationKey validationKey,
UIValidationCriteria validationCriteria, Locale
locale) throws WTException {
UIValidationResult result =
UIValidationResult.newInstance(validationKey,

UIValidationStatus.NOT_VALIDATED);

14-144 Windchill Customizer’s Guide


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

@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;
}

Presenting Information in the UI 14-145


Procedures – 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 on page 14-139 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;

14-146 Windchill Customizer’s Guide


Miscellaneous Tips, Tricks, and Things to Avoid
This section contains the following topics:
• Working with Access Permissions on page 14-147
• Rule of Thumb: One Validator per Action/Attribute/Component on page
14-148
• Do Not Inflate WTReferences on page 14-149
• Handle Null Values on page 14-150
• Use the @Override Annotation on page 14-150
• UIValidationCriteria.toString() on page 14-150

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
if (accessPermissions == null){

Presenting Information in the UI 14-147


accessPermissions = AccessControlManager.getPermissions(...);
criteria.setCachedAccessPermissions(accessPermissions);
}

Additional notes regarding access permissions:


• wt.access.AccessControlManager has the following APIs available in single-
and 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


Don’t 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.
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

14-148 Windchill Customizer’s Guide


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().getObject();
WTContainer container =
validationCriteria.getParentContainer().getReferencedContainer();

if (!contextObject instanceof WTPart){


...
}
if (!container instanceof PDMLinkProduct){
...
}
}

The code above in bold italic 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())){
...
}
if
(!PDMLinkProduct.class.isAssignableFrom(containerRef.getReferenced
Class())){
...
}
}

Presenting Information in the UI 14-149


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.

Use the @Override Annotation


It’s 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)

14-150 Windchill Customizer’s Guide


If the Level of the Logger matches with the Level provided, the method will
return the information. Since the method performs some costly calculations, it’s
suggested to use this it wisely.

Presenting Information in the UI 14-151


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
samples provide an example of how to do this in the method

14-152 Windchill Customizer’s Guide


"getValue(String, Hashtable, HashTable, boolean)" of the file "Windchill\
DevModules\Foundation\src\wt\part\LoadPart.java".
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
* not disclose such confidential information and shall use it only in accordance
* with the terms of the license agreement.

Presenting Information in the UI 14-153


*
* ecwti
*/

package wt.part;

import java.lang.String;
import wt.part.ValidateFindNumbersDelegate;
import wt.part.WTPartUsageLink;
import wt.util.WTException;

//##begin user.imports preserve=yes


import wt.util.WTPropertyVetoException; // Preserved unmodeled dependency
//##end user.imports

//##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
*
* @param partUsageLinks
* @exception wt.util.WTException
**/

14-154 Windchill Customizer’s Guide


//##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
*/
private void doValidation(String[] findNumbersArray)
throws WTPropertyVetoException
{
for(int j = 0; j < findNumbersArray.length; j++)
{
String a_FindNumber = findNumbersArray[j];

Presenting Information in the UI 14-155


// 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 ));
}
}
}
}
}
}
//##end user.operations
}

14-156 Windchill Customizer’s Guide


15
Constructing Wizards

This chapter describes how to construct wizards.

Topic Page
Windchill Client Architecture Wizard ..............................................................15-2
Wizard Processing...........................................................................................15-19
Building Wizards to Create a Single Object ...................................................15-38
Building Wizards to Edit a Single Object .......................................................15-90

15-1
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. 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 a
single step or multiple steps. Each multiple steps wizard will have navigation
buttons (BACK / NEXT) at the bottom, which you can use to navigate from one
step to another.
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.
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”.

Multi-Step Wizard

15-2 Windchill Customizer’s Guide


Single Step Wizard

Multi-Step Clerk

Scope/Applicability/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.
• Scrolling is enabled for table inside wizard as well as table inside picker.
• 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

Constructing Wizards 15-3


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.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development, which involves HTML, JSP, JavaScript and Custom
taglibs.
• Overview of Windchill Client Architecture tags.
• The actions framework in the Windchill client architecture.
• Action validation framework.

Solution Elements

Element Type Description

components.tld tld Tag Library Descriptor (TLD) file, which contains


Wizard Tag and Wizard-Step Tag definition
Run time Location:
<Windchill>\codebase\WEB-INF\tlds\

wizard.js Js 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\
components

<your_wizard_page>.jsp jsp The jsp file in which your wizard implementation is


defined.

<your_wizard_step>.jsp jsp The jsp file, which contains contents of the wizard step.

<*-actions>.xml xml The actions for the wizard as well as each wizard step are
defined in this XML file.

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

15-4 Windchill Customizer’s Guide


Element Type Description

<resourceBundle>.rbInfo rbInfo This is another option where you can specify locale
specific Strings and properties for wizard step and
wizard actions.

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

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. 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. Windchill will now expect
“create.jsp” to be located in <Windchill>\codebase\netmarkets\jsp\changeTask\
folder. Since this action is for the wizard, you need to specify windowType as
“popup” inside the <command> tag.
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, you need to specify windowType as “wizard_step”.
<objecttype name="changeTask"
class="wt.change2.WTChangeActivity2">
<action name="create">
<command windowType="popup"/>
</action>

<action name="affectedAndResultingItemsStep">
<command windowType="wizard_step" />
</action>
</objecttype>

Create the Wizard page


Create a new jsp page inside <Windchill>\codebase\netmarkets\jsp\changeTask\
folder and name it as create.jsp.
The first thing that you need to do is to declare the components tag library that
contains the necessary tags for constructing the wizard and wizard steps. Next you
need to include some files that will be used by the wizard infrastructure namely;

Constructing Wizards 15-5


“/netmarkets/jsp/components/beginWizard.jspf” and
“/netmarkets/jsp/components/includeWizBean.jspf”.
Define the wizard using the <wizard> tag. All the steps for this wizard will be
defined inside <wizard> tag using <wizardStep> tag.
Finally, include "/netmarkets/jsp/util/end.jspf" file to close the form.
<%@ 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" />
<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">
<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.

Specify localized Strings / properties for wizard step and wizard actions
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 Task
changeTask.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

15-6 Windchill Customizer’s Guide


changeTask.create.icon.pseudo=false
changeTask.create.moreurlinfo.value=width=800,height=700
changeTask.create.moreurlinfo.pseudo=false

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

Create the wizard step page


This can be any JSP page, which can contain any other component(s) as well as
plain HTML contents.

Customization Points
This section contains the following topics:
• <action>.xml attributes
• <wizard> tag attributes
• <wizardStep> tag attributes
• Providing user defined buttons to Wizard
• Providing user defined form processor controller
• Providing server side validation before / after processing a wizard step
• Loading the wizard step content when it is visited
• Marking a wizard step as “required”
• Hiding a wizard step
• Displaying the hidden / dynamic step at runtime
• Providing user defined SUBMIT function
• Providing client side validations before a wizard step is displayed
• Providing client side validations after a wizard step is finished

<action>.xml attributes

Possible
Parameter Default Value Values Req? Description

id <type>.<action> Any String No Overrides the id of the wizard step


(default is type.action).

Constructing Wizards 15-7


Possible
Parameter Default Value Values Req? Description

afterJS - Any String No Specify the javascript function name to


invoke client side validation for a
wizard step when step is finished.

beforeJS - Any String No Specify the javascript function name to


invoke client side validation for a
wizard step when step is loaded.

beforeVK - Any String No Specify the server validator name to


invoke server side validation for a
wizard step when step is loaded.

afterVK - Any String No Specify the server validator name to


invoke server side validation for a
wizard step when step is finished.

preloadWizardPa true false / true No Specifies that wizard step is to be


ge downloaded when wizard is launched.

hidden false false / true No Specifies that wizard step is to be


hidden at first, or for the action to be
rendered as non-clickable.

required false false / true No Specifies that wizard step is required.

<wizard> tag attributes

Possible
Parameter Default Value Values Req? Description

buttonList “DefaultWizard Any String No The action model containing the list
Buttons” of buttons to display in the wizard.
The default set is the
DefaultWizardButtons action model.

formProcessorCo “DefaultFormPr Any String No The FormProcessorController class


ntroller ocessorControlle that should be used to process the
r” wizard when it is submitted.
If not specified,
DefaultFormProcessorController will
be used.

15-8 Windchill Customizer’s Guide


Possible
Parameter Default Value Values Req? Description

title - Any String No 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.

helpSelectorKey - Any String No The selector key to identify help file


from services.properties file.

type wizard Wizard/clerk/dia No Identifies whether wizard is of type


log clerk or not. If "clerk" is specified, the
wizard will be displayed as per clerk
UI.

progressMessage - Any String No This allows for text to be displayed


above the progress bar using the UI
standard.

<wizardStep> tag attributes

Possible
Parameter Default Value Values Req? Description

action - Any String Yes The name of the action to include in


the wizard parent tag.

type - Any String Yes The type of the action to include in


the wizard parent tag.

objectHandle - Any String No The object handle to identify which


object this step corresponds to.
Only required if the wizard needs to
create multiple objects.
By default, no object handle is
needed.

label - Any String No The label for the step.


Note: Actions should already have
labels.
Only set this attribute if you want to
override the action's label.

embeddedHelp - Any String No A small optional text help to be


displayed on top of the wizard step
content.

Constructing Wizards 15-9


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


</jca:wizard>

You need to provide corresponding entry in actionmodels.xml file:


<actionmodels>
<model name="PreferenceWizardButtons">
<action name="revertButton" type="object"/>
<action name="okButton" type="object"/>
<action name="cancelButton" type="object"/>
</model>
</actionmodels>

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 e.g.
In <your_wizard_page>.jsp
<jca:wizard formProcessorController =
"com.ptc.windchill.enterprise.change2.forms.controllers.Effectivit
yAwareIframeFormProcessorController">

15-10 Windchill Customizer’s Guide


</jca:wizard>

Note: For more information see the Wizard Processing on page 15-19.

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 e.g.
<action name="setAttributesWizStepForCreateMultiPart" beforeVK =
"nameNumberValidation">
<command windowType="wizard_step"/>
</action>

OR
<action name="setAttributesWizStepForCreateMultiPart" afterVK =
"nameNumberValidation">
<command windowType="wizard_step"/>
</action>

<Service context="default"
name="com.ptc.core.ui.validation.UIComponentValidator">
<Option requestor="null" selector="nameNumberValidation"
serviceClass="com.ptc.windchill.enterprise.part.validator.CreateMu
ltiPartNameNumberValidator" />
</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 e.g.
<action name="setClassificationAttributesWizStep"
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.

Constructing Wizards 15-11


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 e.g.
<action name="setClassificationAttributesWizStep" required="true">
<command windowType="wizard_step"/>
</action>

You can also mark a wizard step as “required” at runtime. You need to use a
javascript function called “setStepRequired” which is defined in wizard.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 e.g.
<script src="/netmarkets/javascript/components/wizard.js"></script>
<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(<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 e.g.
In <*-actions>.xml
<action name="setClassificationAttributesWizStep" 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 wizard.js file. You need to pass the “id” of the

15-12 Windchill Customizer’s Guide


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 e.g.
In <your_wizardstep_page>.jsp
<script src="/netmarkets/javascript/components/wizard.js"></script>
<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(<type>.<action >);"/>
</td>
</tr>
</table>

Note: Clerk does not make 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 wizard.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 e.g.
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" hidden="true">
<command windowType="wizard_step"/>
</action>

In <your_wizardstep_page>.jsp
<script src="/netmarkets/javascript/components/wizard.js"></script>
<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(<type>.<action>);"/>
</td>

Constructing Wizards 15-13


</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
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
e.g.
<script language="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 e.g.
In <*-actions>.xml
<action name="setClassificationAttributesWizStep" beforeJS ="
validatePreviousStep">
<command windowType="wizard_step"/>
</action>

In any JSP page or Javascript file accessible to wizard


<script language="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

15-14 Windchill Customizer’s Guide


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 e.g.
In <*-actions>.xml
<action name="setClassificationAttributesWizStep" afterJS ="
validateStep">
<command windowType="wizard_step"/>
</action>

In any JSP page or Javascript file accessible to wizard


<script language="javascript">
function validateStep() {
...
...
return true;
}
</script>

Configuring Wizard - Suppressing enter key


You can suppress form submission on enter key .
<script language="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;
}
}
}

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">
<command class="com.ptc.windchill.enterprise.part.forms.CreatePartFormProcessor"
method="execute" onClick="validateCreateLocation(event)"
windowType="popup"/>
</action>

Constructing Wizards 15-15


<action name="createMultiPart" >
<command class =
"com.ptc.windchill.enterprise.part.forms.CreateMultiPartFormProcessor"
method="execute" onClick="validateCreateLocation(event)"
windowType="popup"
url="/netmarkets/jsp/part/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 e.g.
<%@ 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" />

<jca:wizard helpSelectorKey="PartMultipleCreate"
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 the case of a clerk, while navigating between steps you may not get required
fields in Server validators, so you need to take care and apply logic accordingly.

15-16 Windchill Customizer’s Guide


For example, while creating a new document the first step has a required field
type (type of document). However, in a clerk the user is free to navigate between
other tabs while clicking on other tabs, the user might not have selected required
field type in the first step. In that case the server validator cannot get the value of
the type attribute.

Constructing Wizards 15-17


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

• 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 (can be accessed through wizard actions on table
examples):
<Windchill>\netmarkets\jsp\carambola\customization\examples\
wizard\newWizardExampleOne.jsp

• Wizard example two (can be accessed through wizard actions on table


examples):
<Windchill>\netmarkets\jsp\carambola\customization\examples\
wizard\wizardExampleTwo.jsp

• Clerk example one (can be accessed through wizard actions on table


examples):
<Windchill>\netmarkets\jsp\carambola\customization\examples\
clerk\clerkExampleOne.jsp

15-18 Windchill Customizer’s Guide


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 15-38 and Building
Wizards to Edit a Single Object on page 15-90 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/Assumptions
Assumes that you have already created the necessary JSPs, data utilities, GUI
components, and renderers to display your wizard.
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.

Constructing Wizards 15-19


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

WizardServlet Java class; runs in the servlet This is the class to which wizard form data
container gets posted and which sends the response
page sent back to the browser after
processing completes.
Runtime location:
<WT_HOME>/srclib/CommonCompone
nts-web.jar

FormProcessorController Java interface; Classes implementing this interface


implementations run in the instantiate and call
Method Server ObjectFormProcessor(s) to execute wizard
tasks.
Runtime location:
<WT_HOME>/srclib/CommonCompone
nts.jar

15-20 Windchill Customizer’s Guide


Element Type Description

DefaultFormProcessorControll Java class; runs in the A default implementation of


er Method Server 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.
Runtime location:
<WT_HOME>/srclib/CommonCompone
nts.jar

ObjectFormProcessor Java interface; Classes implementing this interface


implementations run in the perform the database and related tasks
Method Server 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
ObjectFormProcessorDelegates to
perform subtasks.
Runtime location:
<WT_HOME>/srclib/CommonCompone
nts.jar

DefaultObjectFormProcessor Java class; runs in the A default implementation of


Method Server ObjectFormProcessor that contains the
logic to execute
ObjectFormProcessorDelegates and
perform several other common tasks. This
is the base class that should be extended by
wizard-specific processors.
Runtime location:
<WT_HOME>/srclib/CommonCompone
nts.jar

Constructing Wizards 15-21


Element Type Description

ObjectFormProcessorDelegate Java interface; Classes implementing this interface are


implementations run in the called by ObjectFormProcessors to
Method Server perform processing subtasks. Multiple
ObjectFormProcessorDelegates 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/CommonCompone
nts.jar

DefaultObjectFormProcessorD Java class; runs in the A default implementation of


elegate Method Server 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/CommonCompone
nts.jar

ObjectBean Java class; runs in the A container for the form data specific to a
Method Server 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/CommonCompone
nts.jar

ProcessorBean Java class; runs in the A container for ObjectBeans that knows
Method Server which ObjectBeans should be processed
by the same processor instance and the
order in which they should be processed.
Runtime location:
<WT_HOME>/srclib/CommonCompone
nts.jar

FormResult Java class; runs in the A class used to pass method results
Method Server and client between server methods and from the
server to the WizardServet.
Runtime location:
<WT_HOME>/srclib/CommonCompone
nts.jar

15-22 Windchill Customizer’s Guide


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

Constructing Wizards 15-23


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

15-24 Windchill Customizer’s Guide


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.

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

Constructing Wizards 15-25


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

15-26 Windchill Customizer’s Guide


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

Constructing Wizards 15-27


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
ObjectBeans. You pass back a list of all the root ObjectBeans. After you have
created the ObjectBean structure, the DefaultFormProcessorController will call

15-28 Windchill Customizer’s Guide


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 WTChangeOrder2


(ObjectBean in Processor Bean 1) and store it in the "object" attribute of the
bean

2 ProcessorInstance2. create three instances of


preProcess(ObjectBeans in WTChangeActivity2 and store them in
Processor Bean 2) the "object" attributes of the beans

3 ProcessorInstance1.doOperation( persist the WTChangeOrder2


ObjectBean in Processor Bean 1)

4 ProcessorInstance2.doOperation( persist the WTChangeActivity2 instances


ObjectBeans in Processor Bean 2)

5 ProcessorInstance1.postProcess(O create the associations between the


bjectBean in Processor Bean 1) change notice and the change tasks

Constructing Wizards 15-29


Method Task Performed

6 ProcessorInstance2.postProcess(O none
bjectBeans in Processor Bean 2)

7 ProcessorInstance1.postTransacti none
onProcess(ObjectBean in
Processor Bean 1)

8 ProcessorInstance2.postTransacti none
onProcess (ObjectBeans in
Processor Bean 2)

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

15-30 Windchill Customizer’s Guide


(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
• Wizards with Multiple Target Objects

Wizards with a Single Target Object


This process consists of the following steps:
• Create your processor class
• Specify the processor class for the wizard on the wizard action
• Create any necessary ObjectFormProcessorDelegate classes for your wizard
• Specifying the ObjectFormProcessorDelegate(s) to be used in your wizard

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

Constructing Wizards 15-31


public Map<String,List<String>> getChangedComboBox()
public Map<String,String> getChangedRadio()
public Map<String,String> getChangedText()
public Map<String,String> getChangedTextArea()
public Map<String,List<String>> getChecked()
public Map<String,List<String>> getUnChecked()
public List getRemovedItemsByName(String paramName)
public List getAddedItemsByName(String paramName)
public String getTextParameter(String key)
public 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.
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.

15-32 Windchill Customizer’s Guide


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.

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 15-33


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.
Like ObjectFormProcessor methods, ObjectFormProcessorDelegate methods can
throw exceptions. How these are handled depends on the ObjectFormProcessor
calling it.

15-34 Windchill Customizer’s Guide


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.windchill.enterprise.attachments.forms.Second
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
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.

Constructing Wizards 15-35


Wizards with Multiple Target Objects
This process consists of the following steps:
• Create your processor class
• Specify the processor class for the wizard on the wizard action
• Create any necessary ObjectFormProcessorDelegate classes for your wizard
• Specify the ObjectFormProcessorDelegate(s) to be used in your wizard
• Create a FormProcessorController, if needed
• Specify the FormProcessorController to be used in your wizard, if needed

Create your processor class


The same as for a wizard with a single target object. See Create your processor
class on page 15-31.

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

Create any necessary ObjectFormProcessorDelegate classes for your wizard


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

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

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 it’s 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"

15-36 Windchill Customizer’s Guide


formProcessorController="com.ptc.windchill.enterprise.change2.form
s.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 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
• 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

Constructing Wizards 15-37


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 section of this topic on page 15-41.
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/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 you can ignore
such implementation details.
This document describes the reusable common components upon which most
Windchill create 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 create
instances of a custom type. If your type is a modeled or soft subtype of a
Windchill business class for which a wizard with a type picker is already

15-38 Windchill Customizer’s Guide


available, you may be able to use the out-of-the-box wizard for your purposes.
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 MyPart, it will be displayed in the
New Part wizard as follows:

Constructing Wizards 15-39


Input fields for any non-association attributes you have defined for your subtype
will automatically be displayed on the Set Attributes step of the New Part wizard
below the out-of-the-box attributes:

Attributes in the table will be ordered as follows:


1. Out-of-the-box attributes ordered as listed in the JSP file
2. Custom modeled attributes ordered alphabetically by display name
3. Custom soft attributes ordered alphabetically by display name
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.

15-40 Windchill Customizer’s Guide


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 the Building Wizards to Edit a Single Object section on page 15-90 of
the Windchill Customizer’s Guide for information on constructing a wizard to edit
an object.

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 achieve this objective, you need to have an understanding of the following:
• Java programming
• Basic web development using JSPs , custom tags, and HTML forms
• How to create modeled or soft Windchill business object types.
See the following chapters in the Windchill Customizer’s Guide for more
information on creating your business object classes using the Information
Modeler and Rational Rose:
– Getting Started With Windchill Customization chapter on page 3-1
– Modeling Business Objects chapter on page 4-1
– System Generation chapter on page 32-1
– Developing Server Logic chapter on page 36-1
– See the Type and Attribute Manager 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 the Adding Actions and Hooking Them Up in the UI chapter on page
12-1 for information on how to create actions.
• The Windchill framework for creating wizards and processing wizard data.

Constructing Wizards 15-41


See the rest of the Constructing Wizards chapter on page 15-1 for more
information on this topic. Also, see the Adding Actions and Hooking Them
Up in the UI chapter on page 12-1 for information on how to create actions.
• The use of tables and property panels to present information in the UI and
how to acquire the data for these components.
See the following chapters of the Windchill Customizer’s Guide for more
information:
– Customizing HTML Clients Using the Windchill JSP Framework on page
11-1
– Gathering the Data for the UI on page 13-1
– Presenting Information in the UI on page 14-1
• 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 the Presenting Information in the UI chapter on page 14-1 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.
• The Windchill service APIs or other APIs necessary to perform the data
processing tasks appropriate to the wizard
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.

15-42 Windchill Customizer’s Guide


Definition of Terms Used in This Section
Term Definition

base type A hard or soft type class that is the root type of the wizard's type picker. If the wiz-
ard 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.

context The container (Product, Library, Project, etc.) in which you are creating the
object(s).

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

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

hard attribute An object attribute defined in a Java class.

hard type An object type defined in a Java class. Hard types are typically modeled
using Rational Rose and may extend out-of-the-box Windchill business
object classes.

object type A Java class or soft type defining the attributes and behavior of the business
object(s) you want to create.

soft attribute An attribute of the object defined in the Windchill Type and Attribute
Manager 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.

soft type An object type defined using the Type and Attribute Manager rather than in
a Java class. Soft types may extend other soft types but all have a hard type
as their root type.

target object The object you are creating in your wizard.

Solution Elements
Element Type Description

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.

Constructing Wizards 15-43


Element Type Description

initializeItem Tag 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/co
mponents/InitializeItemTag

describeAttributesTable Tag Builds a table descriptor for a two-


column table of object attributes
used for entering attribute values.
The left column is the attribute
name and the right is the attribute
value.

See the javadoc for the


DescribeAttributesTableTag for
more information.
Tag handler:
com/ptc/core/components/tags/co
mponents/DescribeAttributesTabl
eTag

15-44 Windchill Customizer’s Guide


Element Type Description

describePropertyPanel Tag Builds a table descriptor for a two-


column panel of object attributes.
The left column is the attribute
label and the right is the attribute
value. Typically used to display
read-only information gathered in
previous wizard steps or from the
launch context but can also be used
for input fields.

Tag handler:
com/ptc/core/components/tags/co
mponents/DescribePropertyPanel
Tag

getModel Tag Acquires the attribute data needed


for an attributes table or property
panel previously defined by a
describeAttributesTable or
describePropertyPanel tag.
Tag handler:
com/ptc/core/components/tags/co
mponents/GetModelTag

renderPropertyPanel Tag Renders a property panel


previously defined using
describePropertyPanel and
getModel tags.
Tag handler:
com.ptc.core.components.tags.pro
pertyPanel.RenderPropertyPanelT
ag

renderTable Tag Renders a table previously defined


using describeAttributesTable and
getModel tags.
Tag handler:
com/ptc/core/components/tags/co
mponents/RenderTableTag

Constructing Wizards 15-45


Element Type Description

wizard Tag Specifies the action pointing to the


main JSP for the wizard and
defines the steps contained in the
wizard.
Tag handler:
com/ptc/core/components/tags/co
mponents/WizardTag

wizardStep Tag Specifies the action pointing to the


main JSP for the step.

JSPs
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/netmarkets/jsp/object and
<WT_HOME>/codebase/netmarkets/jsp/components directories.

createEditUIText jspf file Contains some UI text common to


create and edit wizards.

includeWizBean jspf file Defines the


CreateAndEditWizBean called
during the generation of jsp pages
to access wizard data.

setContextWizStep jsp file A JSP for the Set Context wizard


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

defineItemWizStep jsp file A default JSP that you may be able


to use for the Define Object step of
your wizard if it should contain a
read-only property panel for the
context name, a type picker, and a
driver attributes table for entering
attribute values.

15-46 Windchill Customizer’s Guide


Element Type Description

setAttributesWizStep jspf file A jsp file that can be included in


the jsp for your Set Attributes
wizard step. This will get the
model data for and render your
attributes panel and tables if you
have named them per the
instructions in this document.

setAttributesWizStepWithContent jspf file A jsp file that can be included in


.jspf the jsp for your Set Attributes
wizard step if your object type is a
FormatContentHolder. It does the
same things as the jsp above but, in
addition, will render input fields
for capturing primary content.
Location:
<WT_HOME>/codebase/netmark
ets/jsp/document

Beans

CreateAndEditWizBean Java class; Runs in the servlet This bean is available to your jsps
engine and the Method Server 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 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/netmark
ets/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.

Constructing Wizards 15-47


Element Type Description

CreateAndEditModelGetter Java class A class that may be called via a


getModel tag to generate the data
Runs in the Method Server
for property panels and attributes
tables in create wizards.

ContextWizardStepValidator Java class; runs in the Method A class that may be called to
Server validate the data in the Set Context
wizard step.

DefineObjectStepValidator Java class; runs in the Method A class that may be called to
Server validate the data in the Define
Object wizard step.

SetAttributesStepValidator Java class; runs in the Method A class that may be called to
Server validate the data in the Set
Attributes wizard step.

CreateObjectFormProcessor Java class; A class that may be used or


extended to process your wizard
Runs in the Method Server
form data. Extends
DefaultObjectFormProcessor.

DefaultObjectFormProcessorDele Java class; A class that may be extended to


gate Runs in the Method Server implement various processing
subtasks.

ObjectBean Java class; runs in the Method A container for the form data
Server 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; runs in the Method A class used to pass method results
Server and client between server processor methods
and from the server to the
WizardServlet.

Procedure – Creating Your Wizard


You will need to perform the following tasks to create your wizard:
• Laying out your wizard steps and attributes (required)
• Create an action for the wizard (required)
• Create actions and/or service properties entries for the wizard steps
• Create jsp and/or jspf files for your wizard steps or portions thereof (required)
• Create a main jsp file for your wizard (required)

15-48 Windchill Customizer’s Guide


• Create validators for the wizard data
• Create a form processor class and/or delegates to process the wizard data after
submittal
The tasks noted as required are always required. The other tasks may or may not
be needed, depending on the requirements of your wizard.
If you have 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.

Laying out your wizard steps and attributes


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
Manager 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 object’s 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
attribute’s 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:

Constructing Wizards 15-49


• Organization
• Number
• Name (variant parts only)
• Folder location
• Life cycle template
• Team template
• 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

15-50 Windchill Customizer’s Guide


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. Refer to the Loading the wizard step content when it is visited section
on page 15-11 for information on pre-loaded 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
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.
The standard layout of Windchill wizards is as follows:
1. Set Context step (for WTContained objects only)
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.
2. Define Object step
The body of this step typically contains three sections: a read-only context
property panel, a type picker, and a driver attributes property panel. Refer to

Constructing Wizards 15-51


the illustration below. All of these sections are optional, depending on the
type of object being created.

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

15-52 Windchill Customizer’s Guide


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.

3. Determine a default folder location context for the new object.


This is done as follows:
a. 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 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
b. If no renderer constraint is defined and it is not a
shared-to object
• 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
a. above

4. Based on the default initial life cycle state and the 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.

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

WTPart Create and Edit -> Part Create Default


Type

WTDocument Create and Edit -> Document Create


Default Type

Constructing Wizards 15-53


Base Type Preference

WTChangeIssue (ProblemReport) Create and Edit -> Problem Report


Create Default Type

WTChangeRequest2 (Change Create and Edit -> Change Request


Request) Create Default Type

WTChangeOrder2 (Change Notice) Create and Edit -> Change Notice


Create Default Type

For all other wizards, the base type is used as the default type.
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.
When objects are being created from a template, such as creating a document
from a template, the type picker is replaced by a template picker and the type
of the new object is determined from the template.
– 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 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.
3. Set Attributes step
This step is where information for most non-driver attributes for the object is
gathered. It generally consists of two to four parts, which may include the
following: a read-only context property panel, primary content input fields
(for FormatContentHolder objects only), an attribute input table, and

15-54 Windchill Customizer’s Guide


checkboxes for processing directives specific to the object type. Refer to the
illustration below.

– Context panel
Read-only information about the object being created that is derived from
the launch context or data entered on previous wizard steps. This will
usually contain the object type. If the new object is WTContained it will
also display the container name. If the new object is OrganizationOwned
and the preference Display -> Expose Organization is set to true it will
also display the organization id.
– Primary content
Wizards to create objects that are FormatContentHolders, such as
WTDocuments, should have a section for the user to enter the primary
content item. .
– Attribute input table

Constructing Wizards 15-55


Typically contains all the soft and hard attributes for the object type that
were not entered on previous steps, except for part classification
attributes, which are entered on a following step.
Note that one of the attributes typically presented in this table is folder
location. As stated earlier, 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 Define Object step is based on a default folder derived
from the launch context. The user could potentially select a different
folder location in this step for which the access control policies vary.
Thus it is possible the user could select a folder for which s/he does 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 Applicability Description

Keep checked out for new If checked, the system checks


RevisionControlled out the object after creation
objects

Checkout and for creating If checked, the new document is


download documents from checked out and downloaded
templates

Enabled for creating document If checked, the new template is


templates immediately available for use

4. Additional steps
Your wizard may contain additional steps pertinent to the type of object being
created.
Steps for which common components are available are:
– Classification attributes 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

15-56 Windchill Customizer’s Guide


includes a table of input fields for classification attributes. Refer to the
illustration below.

– Attachments step
This step is typically included when creating objects that are
ContentHolders. It allows the user to attach documents, links, and other
content to the new object. See the Attachments section in the
Customizing HTML Clients Using the Windchill JSP Framework chapter
on page 11-16 for information on incorporating this step.
Some object types may require additional steps to capture other information
needed to create the object. No jsp files are provided for such unique wizard
steps. However, you can develop your own jsp files for unique steps using the
same table, property panel, and javascript components used in the jsp files for
common steps.

Creating the action for your wizard


An action is needed to launch your wizard. This should be defined in an
appropriate *-actions.xml file inside of an “objecttype” tag for the base type of
your wizard.

Constructing Wizards 15-57


A minimal action definition will look like this:
<action name="<your wizard action name>" >
<command class="<path to your wizard form processor>"
windowType="popup"/>
</action>

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 above, the system would expect to
find a jsp file named <WT_HOME>/codebase/netmarkets/jsp/<objecttype
name>/<your wizard action name> to use for the main page of your wizard.
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

The command class is the java class that should be called to process the wizard
data. Typically, this will extend CreateObjectFormProcessor. See Creating Your
Form Processor and Form Processor Delegates section on page 15-75 for more
information.
Note that it is not necessary to specify a “method” attribute in the command tag if
your form processor class extends DefaultObjectFormProcessor or
CreateObjectFormProcessor.

15-58 Windchill Customizer’s Guide


Optional action tag attributes are shown in the table below.

Action tag attribute Default value Possible value Description

ajax None page Specifies what portion of the parent


page should be refreshed when the
component
wizard processing completes.
row
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. See
Creating Your Form Processor and
Form Processor Delegates section
on page 15-75 for more information.

UIComponent None References an entry in


roleaccessprefs.xml (uic name) used
to 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.CreateMyPartF
ormProcessor" 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 the
Solution Elements section on page 15-43 for more information.
See the Adding Actions and Hooking Them Up in the UI chapter on page 12-1 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 the section of
Windchill Customizer’s Guide referenced above.

Constructing Wizards 15-59


Creating actions and/or service property entries for your wizard steps
Each wizard step requires an action. You may be able to use out-of-the-box
action definitions for wizard steps that are common to multiple wizards. The
following wizard step actions are defined out-of-the-box.

Step Object Type Action definition / File location / Associated JSP page

Set Context object <action name="setContextWizStep" id="setContextWizStep"


preloadWizardPage="true" required="true"
afterVK="setContextWizStep">
<command windowType="wizard_step"/>
</action>

Action file: <WT_HOME>/codebase/actions.xml


Associated jsp page:
<WT_HOME>/codebase/netmarkets/jsp/object/setContextWizStep.jsp

Define object <action name="defineItemWizStep" id="defineItemWizStep"


Object preloadWizardPage="false" required="true"
afterVK="defineItem"
resourceBundle="com.ptc.core.ui.componentRB">
<command windowType="wizard_step"
url="servlet/TypeBasedIncludeServlet?contextAction=d
efineItemWizStep"/>
</action>

Action file: <WT_HOME>/codebase/actions.xml


Associated jsp page:
<WT_HOME>/codebase/netmarkets/jsp/object/defineItemWizStep.jsp

Set object <action name="setAttributesWizStep"


Attributes afterVK="setAttributesWizStep" id="setAttributesWizStep"
preloadWizardPage="false" required="true"
resourceBundle="com.ptc.core.ui.componentRB">
<command windowType="wizard_step"
url="servlet/TypeBasedIncludeServlet?contextAction=s
etAttributesWizStep"/>
</action>

Action file: <WT_HOME>/codebase/actions.xml


Associated jsp page: None

Set part <action name="setClassificationAttributesWizStep"


Classificatio id="setClassificationAttributesWizStep" hidden="true"
n Attributes required="true" preloadWizardPage="false">
<command windowType="wizard_step"/>
</action>

Action file: <WT_HOME>/codebase/ config/actions/PartManagement-


actions.xml.
Associated jsp page:
<WT_HOME>/codebase/netmarkets/jsp/part/setClassificationAttributesWi
zStep.jsp

15-60 Windchill Customizer’s Guide


The associated jsp page shown in the table above is a default jsp that may be used
for the step. Note there is no default jsp for the Set Attributes step, although there
is a common action definition.
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.
If these action definitions meet your requirements you do not need to define your
own actions for your wizard. However, you will need to define your own action
for a wizard step if either of the following is true:
• you need to define additional or different tag attributes for an action
• For the Set Context and Set Classification Attributes steps only: you need to
use a different jsp page for your step. For the Define Object and Set
Attributes steps, you can use a different jsp for your step without defining
your own action through use of the TypeBasedIncludeServlet described
below.
• Your step is unique to your wizard
The table below shows action tag parameters relevant to create wizard steps:

Action Default Possible


attribute tag Req? value values Description

name yes None any string The name of the action. Used as the “name”
attribute on wizard step tags.

id no <action any string Used to identify the step in certain javascript


type>.<act functions. If not specified the id <action
ion name> type>.<action name> will be used.

required no false “true” or Specifies whether the user must navigate to the step
“false” or not. The Finish button will not be enabled until
the user has completed all required steps.

beforeJS no None any string Specifies the name of a javascript function to call
when the wizard step is loaded

afterJS None any string Specifies the name of a javascript function to call
when the user clicks Next or OK on the wizard
step. Can be used to do client-side validation of the
form data.

beforeVK no None any string The name of a validator key specifying a Method
Server validator to be called when the user
navigates to the step using the Previous or Next
button.

Constructing Wizards 15-61


Action Default Possible
attribute tag Req? value values Description

afterVK no None any string The name of a validator key specifying a Method
Server validator 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.

preloadWizardPa no true “true” or Specifies that the wizard step is to be downloaded


ge “false” when wizard is launched rather than when the user
navigates to the step. Pre-loading wizard steps will
make it faster to move to the next step. However,
you should not preload wizard steps that are
dependent on information gathered in previous
steps.

Note that the “windowType” attribute of the command subtag should always be
set to “wizard_step.”

Creating service.properties Entries for the Define Object and Set Attributes Steps
You will notice that the command tag for both the Define Object and Set
Attributes wizard step actions above contain a url attribute referencing the
TypeBasedIncludeServlet. The TypeBasedIncludeServlet allows the system to
look up the correct jsp page to use for a wizard step or part of a wizard step on-
the-fly given an action name and the type of object to be created. Using this
servlet for the url for wizard steps allows:
• wizards for different object types to share the same step action definition
• reuse of the same wizard action and main wizard jsp for different object types
if the wizards are identical except for steps that use the
TypeBasedIncludeServlet for jsp lookup. Typically this is most useful when
you want to use the same wizard to create different subtypes of a base type.
For the Define Object step a default jsp is available, but you can override this by
use of the TypeBasedIncludeServlet and still use the common action definition for
your step. For the Set Attributes step, use of the TypeBasedIncludeServlet allows
you to specify different step jsps for the different object types that might be
selected by the user in the Define Object step without creating a new action for the
step or a new wizard.
The TypeBasedIncludeServlet looks up the correct jsp using
ApplicationContextServices and service.properties files. It locates the file entry
for the service “com.ptc.netmarkets.util.misc.FilePathFactory” that has a selector
matching the contextAction parameter on the url in the action tag and a requestor
object type matching the type of object the user has chosen to create. The value of
that entry gives the path of the jsp page for the step, relative to
<WT_HOME>/codebase. Entries are formatted as follows:
Xconf file:

15-62 Windchill Customizer’s Guide


<Resource context="default"
name="com.ptc.netmarkets.util.misc.FilePathFactory">
<Option requestor=" <object type to be created> >"
resource=" <jsp file path relative to WT_HOME/codebase>.jsp"
selector="<contextAction parameter on url>"/>
</Resource>

Corresponding property file entry generated by the xconfmanager:


wt.services/rsc/default/com.ptc.netmarkets.util.misc.FilePathFa
ctory/<step action name>/ <object type to be created>/0=<jsp
file path>

For example, say you want to use the jsp page


<WT_HOME>/codebase/netmarkets/jsp/ext/part/myPart/setAttributesWizStep.js
p for the Set Attributes step of wizards when the user elects to create an object of
type ext.part.MyPart. You would add the following entry to a type-based services
properties xconf file:
<Resource context="default"
name="com.ptc.netmarkets.util.misc.FilePathFactory">
<Option requestor="ext.part.MyPart"
resource=
“/netmarkets/jsp/ext/part/myPart/setAttributesWizStep.jsp”
selector="setAttributesWizStep"/>
</Resource>

The service.properties files searched by the TypeBasedIncludeServlet are those


listed in the following two properties in the codebase/wt.properties file:
wt.services.applicationcontext.TypeBasedServiceProviderFromProp
erties.defaultPropertyFiles

wt.services.applicationcontext.TypeBasedServiceProviderFromProp
erties.customPropertyFiles

See the Adding a Custom Service Provider Property File section on page 5-27 for
more information on service property files.

Creating Your Step JSP Pages


Standard includes for step jsps
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/createEditUIText.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"%>

Constructing Wizards 15-63


Non-preloaded steps should also have the following directive at the bottom of the
step jsp:
<%@ include file="/netmarkets/jsp/util/end.jspf"%>

If a step is preloaded, none of these are needed.


Attribute Input Tables and Panels
Object creation wizards typically have property panels and/or tables for entering
attribute values.
These are implemented using describePropertyPanel and describeAttributesTable
tags containing a describeProperty tag for each attribute to be displayed. The ids
on the describeProperty tags identify the attribute you want to be displayed.
Property Report
The Property Report lists all the attributes defined for a given object type (for
example, “wt.doc.WTDocument”) and whether or not a data utility is available for
it. The property report can be accessed at:
http://<WINDCHILL_HOSTNAME>/<WEBAPP NAME>
/netmarkets/jsp/property/propertyReport.jsp. If you have a custom attribute for
which no data utility, GUI component, and/or renderer exists you may need to
write your own to display the attribute. Keep in mind that many of the attributes
shown in the Property Report are not settable by the user and would not be
appropriate to display in a create or edit wizard.
The describePropertyPanel and describeAttributesTable tags for input fields
should always have a mode parameter of “CREATE” and a componentType
parameter of “WIZARD_ATTRIBUTES_TABLE.” This tells the dataUtilities to
generate a special name attribute for each input field. The
CreateObjectFormProcessor will recognize and set all attributes with such a
special name attribute automatically after the wizard is submitted.
The special name attributes consist of the following parts:
<context information>___<AttributeIdentifier and other information about the
attribute>___<input field type>
(Note that the keys in the Maps returned by such methods as getTextArea(),
getChangedTextArea(), getComboBox(), etc. of the ObjectBean class include
only the text between the “___” separators.)
These name attributes are not easily parsed and are not intended for use other than
by the CreateObjectFormProcessor. If you want to set an attribute yourself in
your form processing code and want to create a name for your attribute that you
can identify, you can do one of two things:
• Create or override the data utility used for the attribute and call the
setColumnName() method of the GUI component to set the name attribute.
• If there is a wrapper tag available for the GUI component you want to use,
you could display the attribute outside of a table or panel using the wrapper

15-64 Windchill Customizer’s Guide


tag for the GUI component. In the name attribute of the wrapper tag you
would specify the HTML name attribute for the input field. Using this
method you would need to supply the attribute default value in the wrapper
tag. See the javadoc for the wrappers tab library for the available GUI
component wrappers. See the file
WT_HOME/codebase/netmarkets/jsp/carambola/tags/tags.jsp for examples
of how to use wrapper tags.
Data acquisition
The method getItemAttributes() in the class
com.ptc.core.components.forms.CreateAndEditModelGetter is used by the
getModel tags in all out-of-the-box wizards to acquire the data needed to populate
attribute input tables and read-only tables in wizards. This is a TypeInstance-
based method that can be used for custom tables also and should be adequate for
most purposes.

Set Context Step JSP Page


If your wizard has a Set Context step, the out-of-the-box step jsp listed in the
Solution Elements section on page 15-43 will usually suffice. The only time it
might be necessary to develop your own step jsp is if you need to capture
additional attribute values before you can display attributes presented on the
Define Object step.
For example, assume that:
• Your wizard launch point has no folder context
• You do not have any OIRs that set a default folder location for new objects
• You have 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 on a step prior to the Define Object step. You could either add this
input field to the Set Context step or add a 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 can you set the
administrative domain parameter on the type picker based on the user’s folder
selection in the Set Context step.)
If you do develop your own Set Context jsp and want it to have a container picker,
we recommend that you include the out-of-the-box jsp in it rather than copying
the contents of the out-of-the-box jsp to your page. This will ensure your page
will continue to behave correctly even if the context picker is modified in a future
release.

Constructing Wizards 15-65


Define Object Step JSP Page
As stated in the Laying out your wizard steps and attributes section on page 15-49
your wizard may not need a Define Object step. If it does need one, you may be
able to use the default jsp listed in the Solution Elements section on page 15-43.
Even if you cannot use the default jsp as is, you may be able to reuse sub-jsps that
it incorporates.
The suggested name for this step JSP is:
defineItemWizStep.jsp
or
defineItemWizStepFor<object type>.jsp (if there is more than one of these
step jsps in the directory)
If the Define Object step is the first step in your wizard or nothing in this step is
affected by data on prior steps you can preload it. Otherwise, you should indicate
it should not be preloaded in the step action. Typically, if your wizard has a Set
Context step this step should not be preloaded.
The default jsp
(<WT_HOME>/codebase/netmarkets/jsp/object/defineItemWizStep.jsp) for this
step contains a property panel with the following sections (from top to bottom of
panel):
• A read-only subpanel displaying the container name.
If your new object type is not WTContained you will need to modify this.
• A type picker
If your wizard does not require a type picker or it needs to be configured
differently than the default, you will need to develop your own step jsp.
• A driver attributes subpanel for input of the object’s owning organization, if
the new object type is OrganizationOwned. Note this is only displayed if the
preference Display -> Expose Organization is set to true. If the new object is
not OrganizationOwned the default JSP will display nothing in this subpanel.
This subpanel is contained in a sub-jsp file that is looked up at runtime using
the TypeBasedIncludeServlet. If you need to display additional attributes or
don’t want to display an organization picker, you need only write a jsp
containing this panel and register it with a type-based service.properties file
entry as described in the How to create a step with no driver attributes section
on page 15-70 and the How to create a step with additional driver attributes
section on page 15-70. You can still use the default JSP page for the step.
The default Define Object Step jsp includes a number of other jsps located in
<WT_HOME>/codebase/netmarkets/jsp/components and

15-66 Windchill Customizer’s Guide


<WT_HOME>/codebase/netmarkets/jsp/object, as shown in the table and picture
below:

JSP Description

defineItemWizStep.jsp Main jsp for step; includes


configureTypePicker tag for presenting &
configuring type picker

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 driver
attributes subpanel;. The type picker is
configured to call a js function that will
refresh the driver attributes panel any time
the type value is changed.

driverAttributesSetup.jspf Makes an ajax call to the


TypeBasedIncludeServlet to get the JSP
containing the describePropertyPanel,
getModel, and renderPropertyPanel tags for
the driver attributes table. Unless
overridden by a service.properties entry for a
specific type, one of the following JSPs will
be used:
<WT_HOME>/codebase/netmarkets/jsp/ob
ject/defineItemAttributesPanel.jsp (for
OrganizationOwned objects)
<WT_HOME>/codebase/netmarkets/jsp/ob
ject/defineItemAttributesPanelEmpty.jsp
(for all other objects)

defineItemStepContextPanel.jspf contains the getModel and


renderPropertyPanel tags for the read-only
attributes subpanel

Constructing Wizards 15-67


The sections below describe how to perform common customizations of this step.
Please remember that you should always place your custom jsp and jspf files in a
directory under wtSafeArea, as described in the Managing Customizations chapter
on page 5-1.

How to create a step without a read-only property panel


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 your new
file.
3. Delete the following line from the file:
<%@ include
file="/netmarkets/jsp/components/defineItemReadOnlyPropertyPane
l.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 your new
main jsp file.

15-68 Windchill Customizer’s Guide


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/defineItemReadOnlyPropertyPane
l.jspf"%>

Be sure to set the following attributes on your describePropertyPanel tag:

Attribute Value

var “defineItemStepContextPanelDescriptor”

id “defineItemStepContextPanelDescriptor”

scope “request”

mode “VIEW”

Alternatively, you could include a new jspf file that contains your
describePropertyPanel tag instead of placing it in-line. See the Sample
Code section on page 15-84 for an example.

How to create a step without a type picker


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 your new
file.
3. Delete the following line from the file:
<jca:configureTypePicker/>

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. Create a new main jsp file for the step, as described above.
2. Copy the contents of the file
<WT_HOME>/netmarkets/jsp/object/defineItemWizStep.jsp into your new
file.
3. Add the following line to the top of the file:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/picker"
prefix="p"%>

Constructing Wizards 15-69


4. Add “pickerParam” subtags to the configureTypePicker tag as shown in the
javadoc for the ConfigureTypePickerTag. See the Sample Code section on
page 15-84 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.
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 type to be created>"
resource=”/netmarkets/jsp/object/defineItemAttributesPanelEm
pty.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.js
p 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 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 type to be created>"
resource=”<path to your jsp page ”>
selector="defineItemAttributesPanel"/>
</Resource>

Developing Your Set Attributes Step JSP Page


Because the attributes on this step vary by object type, you will need to create
your own main jsp for this step. However, once you describe the contents of the
page there are jsp components available to help you acquire the data models for
and render the elements.
The suggested name for this step jsp is:
setAttributesWizStep.jsp
or

15-70 Windchill Customizer’s Guide


setAttributesWizStepFor<object type>.jsp (if there is more than one of these
step jsps in the directory)
If your wizard does not have a type or template picker and nothing on prior steps
affects the attributes displayed on the Set Attributes step it can be preloaded.
Otherwise, you should indicate this step should not be preloaded in the step
action. Typically, the latter is the case.
Typically, in the main jsp file for this step you will do the following, in this order:
1. Include the file /netmarkets/
jsp/components/setAttributesReadOnlyPropertyPanel.jspf, which inserts a
describePropertyPanel tag for a read-only property panel displaying:
– the object’s owning container (if the object is WTContained)
– the object type
– organization id (if the preference Display -> Expose Organization is set to
true)
2. Include a describeAttributesTable tag listing the attributes you want to display
in the input table. The mode attribute of the tag should be set to “CREATE.”
You should also set the following attributes if you want to use the out-of-the-
box jspf file described in the next step for getting the table model and
rendering the table.

Attribute Value

var “attributesTableDescriptor”

id “attributesTableDescriptor”
(recommended, not required)

scope “request”

You can make use of the Property Report described in the section Attribute
Input Tables and Panels earlier in this section to obtain the ids for the
attributes you want to include in your table. Also, refer to theAttribute
Handling section on page 14-2 and the Soft Attributes and SCAs section on
page 14-21 of the Presenting Information in the UI chapter for a description of
some server calculated attributes (SCAs) that you might want to include.
If your object is a subtype of WTPart and you want to include a classification
picker in your table, you would add the following property to your table:
<jca:describeProperty id="classification.id"
label="${classificationLabel}"/>

and you must include the following hidden fields in the page:
<input id="selectedClfNodes" type="hidden"
name="selectedClfNodes" >

Constructing Wizards 15-71


<input id="selectedClfNodesDisplayName" type="hidden"
name="selectedClfNodesDisplayName" >

3. If your object is a FormatContentHolder and you want to capture primary


content input on this step, include the file
/netmarkets/jsp/document/setAttributesWizStepWithContent.jspf. This
contains the tag primaryAttachmentWithMSOI, which will render input fields
for capturing primary content. (See the Attachments section in the
Customizing HTML Clients Using the Windchill JSP Framework chapter on
page 11-16 for more information on this tag.) It also acquires the data for and
renders the read-only property panel and the attributes input table, providing
you have followed the naming conventions described in this section.
If your object is not a FormatContentHolder, include the file
/netmarkets/jsp/components/setAttributesWizStep.jspf. This does the same
things as setAttributesWizStepWithContent.jspf except that it does not
include a primaryAttachments tag.
4. .Include any checkboxes you desire to gather processing information. If your
object is RevisionControlled and you want to include a Keep checked out
checkbox, you can include the following jsp to display it:
/netmarkets/jsp/components/keepCheckedOutCheckbox.jspf

An example jsp is shown in the Sample Code section on page 15-84.


To create steps that deviate from the normal pattern described above, see below.

How to create a step without a read-only property panel


Do not include the file setAttributesReadOnlyPropertyPanel.jspf in your step jsp.

How to modify the contents of the read-only property panel


Instead of including the file setAttributesReadOnlyPropertyPanel.jspf include
your own jspf file with a describePropertyPanel tag for the panel or include a
describePropertyPanel tag for the panel directly in your step jsp at the same
location as the include. Your describePropertyPanel tag should include
describeProperty tags for the attributes you want to display. Keep in mind that
only property values that have been captured on previous steps can be displayed.
Set the mode attribute of the tag to “VIEW.” Also set the following tag
parameters if you want the setAttributesWizStep.jspf file to obtain the table data
and render the panel for you.

Attribute Value

var “attributesStepReadOnlyPanel”

id “attributesStepReadOnlyPanel”
(recommended, not required)

scope “request”

15-72 Windchill Customizer’s Guide


Adding Set Classification Attributes and Attachments Steps
JSPs for these steps are available out-of-the-box. You need only include the step
action in your main wizard JSP page.

Creating Data Validators for Your Steps


Validation of the data entered by users is done on a step-by-step basis. 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
servlet engine validation in a javascript method by specifying the method as the
value of the afterJS attribute of the step action.
Validation of data values against constraints defined for the attributes in the Rose
model or Type Manager 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.
Default server-side validators are available for the Set Context, Define Object,
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.ContextWizardS
tepValidator" requestor="null" selector="setContextWizStep"/>
<Option requestor="null"
serviceClass="com.ptc.core.components.validators.DefineObjectSt
epValidator" selector="defineItem" />
<Option
serviceClass="com.ptc.core.components.validators.SetAttributesS
tepValidator" requestor="null"
selector="setAttributesWizStep"/>
</Service>

The ContextWizardStepValidator just validates that the form data contains a valid
container object reference.
The DefineObjectStepValidator and SetAttributesStepValidators look at all the
form data with the special name attribute described in the Creating Your Step JSP
Pages section on page 15-63, Attribute Input Tables and Panels. They validate the
data against all constraints that were defined for the attributes in the Rose model
or Type Manager. They do that by calling the preProcess() method of the

Constructing Wizards 15-73


ObjectFormProcessor class for the wizard, which creates a in-progress instance of
the object and validates all its attributes.
The Set Classification Attributes step uses the same validator as the Set Attributes
step.
No validator is provided or needed for the attachments step.
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
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.

Creating Your Main Wizard JSP Page


Your main wizard JSP page should have the same standard includes as non-
preloaded wizard step JSPs. See Standard includes for step jsps on page 15-63 for
more information.
There are two major elements in your main wizard JSP page:
• an initializeItem tag
• a Wizard tag
See the Sample Code section on page 15-84 for example JSP pages.

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

15-74 Windchill Customizer’s Guide


See the <initializeItem> Tag Parameters section on page 15-82 for the attributes
of this tag. The only required attribute is “operation”, which should be set to
${createBean.create} for object creation wizards.

Wizard tag
This tag has wizardStep subtags describing the steps of the wizard. The action
parameter of these subtags points to the action defined for the step. If you are
using the predefined action definition for a step, be sure the action parameter
matches the name parameter of the action See Creating actions and/or service
property entries for your wizard steps on page 15-60 for more information.
The wizard tag also defines the buttons to be used Typically, wizards will use one
of the two following button sets defined in codebase/actionmodels.xml:
• DefaultWizardButtonsNoApply (for multi-step wizards)
• NoStepsWizardButtons (for single-step wizards)
However, other buttons sets are available in actions.xml and custom button sets
can be defined.
The wizard tag has an optional formProcessorController attribute. This should
not be needed for single-object create wizards.
See the Windchill Client Architecture Wizard section on page 15-2 for more
information on the wizard tag.

Attachment Step Requirements


See the Attachments section of the Customizing HTML Clients Using the
Windchill JSP Framework chapter on page 11-16 for information on the elements
that must be included to incorporate this step.

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 section on page 15-19.

Constructing Wizards 15-75


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:


preprocess() method
• extracts all of the ObjectBean form data that has a special name attribute as
described in the Attribute Input Tables and Panels section on page 15-64.
• 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 Manager or Rose model

15-76 Windchill Customizer’s Guide


• 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
doOperation() method
• 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
setResultNextAction() method (called by the DefaultFormProcessorController)
• 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.
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

Constructing Wizards 15-77


CreateObjectFormProcessor. Some of these are shown in the table below.
Consult the javadoc for these classes for more information on their behavior.

If your class extends: Use processor class:

WTPart If creating a wizard to be launched from a workspace:


com.ptc.windchill.enterprise.part.forms.CreatePartFrom
WorkspaceFormProcessor
If creating a wizard to be launched from the Edit Structure
client:
com.ptc.windchill.enterprise.part.forms.CreatePartFromT
abularInputProcessor
All other single-object creation wizards:
com.ptc.windchill.enterprise.part.forms.CreatePartFormP
rocessor

WTDocument For creating a document from a template:


com.ptc.windchill.enterprise.doc.forms.CreateDocFromT
emplateFormProcessor
For creating a document template:
com.ptc.windchill.enterprise.doc.forms.CreateDocTempl
ateFormProcessor
For all other single-object create wizards:
com.ptc.core.windchill.enterprise.doc.forms.CreateDocFo
rmProcessor

WTChangeIssue com.ptc.windchill.enterprise.change2.forms.processors.C
reateProblemReportFormProcessor

WTChangeRequest2 com.ptc.windchill.enterprise.change2.forms.processors.C
reateChangeRequestFormProcessor

WTChangeOrder2 com.ptc.windchill.enterprise.change2.forms.processors.C
reateChangeNoticeFormProcessor

WTChangeActivity2 com.ptc.windchill.enterprise.change2.forms.processors.C
reateChangeTaskFormProcessor

WTVariance com.ptc.windchill.enterprise.change2.forms.processors.C
reateVarianceFormProcessor.

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

15-78 Windchill Customizer’s Guide


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 the Attribute Input Tables and Panels section on
page 15-64 for more information.
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);
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.

Constructing Wizards 15-79


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 section in the Customizing HTML Clients
Using the Windchill JSP Framework chapter on page 11-4 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.
(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 can’t 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)

15-80 Windchill Customizer’s Guide


{
< 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="
${createBean.formProcessorDelegateConstant}" value=" <path name
of your 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)) {

Constructing Wizards 15-81


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.

Customization Points

<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 Default Value Possible Values Req? Description

operation None CreateAndEditWizB Yes Indicates whether the object is being


ean.CREATE created or edited.
CreateAndEditWizB
ean.EDIT

objectHandle Not used for single-object creation


wizards

baseTypeName the type any Windchill type No The string form of the Windchill type
associated with identifier string identifier for the class of object to
the wizard create. For example,
action "wt.part.WTPart" or
"wt.part.WTPart|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.

<configureTypePicker> Tag Parameters


Parameters to this tag are in the form of pickerParam subtags. Example syntax:
<jca:configureTypePicker>

15-82 Windchill Customizer’s Guide


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

Possible
Parameter Default Value Value Req? Description

seedType None any Windchill No The top-level type that should be used to
type identifier generate the list of types. For example,
string (logical or "wt.part.WTPart". May include more
external) than one of these parameters.

defaultType For certain any Windchill No The type that should be selected by
types the default type identifier default. For example, "wt.part.WTPart."
is taken from a string (logical or May be a string, such as "Select a Type"
preference (see external) rather than a type name.
Background on
page 15-38) For
all other
wizards, the
base type is
used.

filterType None any Windchill No A type that should be excluded from the
type identifier type list. For example, "SoftPartType1".
string (logical or The descendants of the filter type are also
external) excluded. May include more than one of
these parameters.

displayHierarch false true (to display No Indicates whether the type list should be
y hierarchy) displayed as a flat list or in hierarchical
form.
false (to display
flat list)

showRoot true true (to display Whether the seedTypes should not be
seed types) displayed.
false (to not
display seed
types)

adminDomainR domain any No String representation of the


efString associated with administrative administrative domain reference that
the default domain should be used for access-control
folder location reference string filtering of the type list. For example,
(see "wt.admin.AdministrativeDomain:7"
Background on
page 15-38)

Constructing Wizards 15-83


Possible
Parameter Default Value Value Req? Description

type BOTH ROOT_TYPES No Indicates the kind of types to be


(only seedTypes displayed. Value should be one of the
will be enum constant value defined in
displayed) com.ptc.windchill.enterprise.picker.type
.server.TypePickerTypes.
SOFT_TYPES
(only soft types
will be
displayed)
MODELED_T
YPES (only
modeled types
will be
displayed
BOTH (both
modeled and
soft types will
be displayed)

Sample Code

Default JSP for the Define Object Wizard Step


Filename:
<WT_HOME>/codebase/netmarkets/jsp/components/defineItemWizStep.jsp
This jsp is mapped to the “defineItemWizStep” action for objecttype=object in
<WT_HOME>/codebase/actions.xml. It is the default jsp that will be used for
this step unless overridden for a specific type.
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@ include
file="/netmarkets/jsp/components/createEditUIText.jspf"%>
<%@ include
file="/netmarkets/jsp/components/includeWizBean.jspf"%>

<%@ include
file="/netmarkets/jsp/components/defineItemReadOnlyPropertyPanel.j
spf"%>

<jca:configureTypePicker/>

<%@ include file="/netmarkets/jsp/components/defineItem.jspf"%>


<%@ include file="/netmarkets/jsp/util/end.jspf"%>

JSP for the Define Object Step of the New Part Wizard
Filename: <WT_HOME>/codebase/netmarkets/jsp/part/defineItemWizStep.jsp

15-84 Windchill Customizer’s Guide


This example illustrates how to override the read-only context panel and to
reconfigure the type picker.
<%@ 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"%>
<%@ 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"%>

<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>


<%@ include
file="/netmarkets/jsp/components/createEditUIText.jspf"%>
<%@ include
file="/netmarkets/jsp/components/includeWizBean.jspf"%>

<jca:describePropertyPanel
var="defineItemStepContextPanelDescriptor"
id="defineItemStepContextPanelDescriptor"
scope="request" mode="VIEW" type="wt.part.WTPart">

<jca:describeProperty id="containerName"
label="${createBean.containerLabel}"/>
</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>

Constructing Wizards 15-85


<%--
Type Picker picks up the default from Preferences. It does
not have be set here.
--%>

<c:forEach var="item" items="${seedPartTypes}">


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


<%@ include file="/netmarkets/jsp/util/end.jspf"%>

JSP for the Set Attributes step of the New Problem Report Wizard
Filename:
<WT_HOME>/codebase/netmarkets/jsp/problemReport/create_details.jsp
Elements typical to most Set Attributes step jsps are shown in bold.
<%@taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"
%><%@taglib uri="http://www.ptc.com/windchill/taglib/fmt"
prefix="fmt"
%><%@taglib
uri="http://www.ptc.com/windchill/taglib/changeWizards"
prefix="cwiz"
%><%@include file="/netmarkets/jsp/components/beginWizard.jspf"
%><%@include
file="/netmarkets/jsp/components/createEditUIText.jspf"

15-86 Windchill Customizer’s Guide


%><%@ include
file="/netmarkets/jsp/components/includeWizBean.jspf"
%>

<!-- Setup the localization string constants -->


<fmt:setLocale value="${localeBean.locale}"/>
<fmt:setBundle
basename="com.ptc.windchill.enterprise.change2.change2ClientResour
ce" />
<fmt:message var="tableTitle" key="ATTRIBUTES_TABLE"/>

<%@ include
file="/netmarkets/jsp/change/setAttributesReadOnlyPropertyPanel.js
pf"%>

<%-->Build a table descriptor and assign it to page variable td<--


%>
<jca:describeAttributesTable var="attributesTableDescriptor"
id="create.problemReportDetailsStep" mode="CREATE"
scope="request"
componentType="WIZARD_ATTRIBUTES_TABLE"
type="wt.change2.WTChangeIssue" label="${tableTitle}">
<jca:describeProperty id="number" />
<jca:describeProperty id="name" />
<jca:describeProperty id="requester"
inputFieldType="singleLine" />
<jca:describeProperty id="theIssuePriority"/>
<jca:describeProperty id="theCategory"/>
<jca:describeProperty id="description" />
<jca:describeProperty
id="ALL_CUSTOM_HARD_ATTRIBUTES_FOR_INPUT_TYPE"/>
<jca:describeProperty
id="ALL_SOFT_NON_CLASSIFICATION_SCHEMA_ATTRIBUTES"/>
</jca:describeAttributesTable>

<cwiz:initializeSubmitNow/>

<%@include
file="/netmarkets/jsp/components/setAttributesWizStep.jspf"%>

<script language='Javascript'>
loadAllRemainingNonRequiredSteps();
</script>

<%@include file="/netmarkets/jsp/util/end.jspf"%>

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

Constructing Wizards 15-87


<%@ 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"


%>

<%@ 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"%>

15-88 Windchill Customizer’s Guide


Additional Resources

Related Package/Class Javadoc


• com.ptc.core.components.forms.CreateAndEditModelGetter
• com.ptc.core.components.forms.CreateObjectFormProcessor
• com.ptc.core.components.forms.DefaultObjectFormProcessor
• com.ptc.core.components.forms.DefaultObjectFormProcessorDelegate
• com.ptc.core.components.forms.FormResult
• com.ptc.core.components.forms.FormResultNextAction
• com.ptc.core.components.forms.DynamicRefreshInfo
• com.ptc.core.components.tags.components.InitializeItemTag
• com.ptc.core.components.tags.components.ConfigureTypePickerTag
• Common Components Tag Lib Javadoc

Constructing Wizards 15-89


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
Rose model or Attribute and Type Manager.
• 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.
Components available specifically for editing include:
• 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

15-90 Windchill Customizer’s Guide


Scope/Applicability/Assumptions
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 non-
Workable 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 as shown
below:

Constructing Wizards 15-91


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.

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 the Building Wizards to
Create a Single Object topic (see page 15-38 for more information), especially the
Prerequisite knowledge section is on page 15-43.

15-92 Windchill Customizer’s Guide


Solution Elements
Element Type Description

Tags

autoCheckOutItem Tag Checks out the object to the current user if it is not
already checked out. Adds an object reference to
Note: All of the tags in the
the working copy as an attribute of the current
Solution Elements section of the
HTTPRequest, as a parameter in
Building Wizards to Create a
HTTPRequestData parameter map of the
Single Object topic are also
NmCommandBean, and as a hidden field in the
applicable to edit wizards. This tag
DOM. The key to the working copy value is
is in addition to those.
CreateAndEditWizBean.WORKING_COPY_RE
See Building Wizards to Create a F_PARAMETER_NAME.
Single Object on page 15-38 for
This tag should be put in the main JSP for the
more information. (The Solution
wizard immediately below the initializeItem tag.
Elements section is on page
15-43.) Tag library: <WT_HOME>/codebase/WEB-
INF/tlds/workinprogress.tld
Tag handler:
com.ptc.windchill.enterprise.wip.tags.AutoCheck
OutObjectTag

JSPs

setAttributesWizStep jspf file A jsp file (also used for create wizards) that can be
included in the jsp for your Set Attributes wizard
step. This will get the model data for and render
your attributes panel and table if you have named
them per the instructions in this document.
Runtime location:
<WT_HOME>/codebase/netmarkets/jsp/compon
ents

setAttributesWizStepWithContent jspf file A jsp file that can be included in the jsp for your
.jspf Set Attributes wizard step if your object type is a
FormatContentHolder. It does the same things as
the jsp above but, in addition, will render input
fields for capturing primary content.
Location:
<WT_HOME>/codebase/netmarkets/jsp/docume
nt

Beans

CreateAndEditWizBean Java class; Runs in This bean is available to your jsps if you include
the servlet engine the includeWizBean jspf file. It has getter
and the Method methods for wizard data such as the operation
Server (create or edit) and working copy object reference.

Constructing Wizards 15-93


Element Type Description

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
Runs in the Method
tables in edit wizards.
Server

EditAttributesStepValidator Java class; runs in A class that may be called to validate the data in
the Method Server the Set Attributes wizard step.

DefaultEditFormProcessor Java class; A class that may be used or extended to process


wizard form data for nonWorkable objects.
Runs in the Method
Extends DefaultObjectFormProcessor.
Server

EditWorkableFormProcessor Java class; A class that may be used or extended to process


wizard form data for Workable objects. Extends
Runs in the Method
DefaultObjectFormProcessor.
Server

Procedure – Creating Your Wizard


You will need to perform the following tasks to create your wizard:
• Lay out your wizard steps and attributes
• Create an action for the wizard
• Create actions and/or service properties entries for the wizard steps
• Create jsp and/or jspf files for your wizard steps or portions thereof
• Create a main jsp file for your wizard
• Create validators for the wizard data
• Create a form processor class and/or delegates to process the wizard data after
submittal
The tasks shown in bold are always required. The other tasks may or may not be
needed, depending on the requirements of your wizard.
If you have 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.

Laying out your wizard


Because the attributes described as “driver” attributes in the Single-Object Create
Wizards Best Practice are not editable, edit wizards generally have fewer steps.

15-94 Windchill Customizer’s Guide


They are also usually less complex because refresh of wizard fields when other
field values are changed is not required.
Edit wizards for non-change objects generally have one to three steps as follows:
1. Set Attributes Step
This step is common to almost all edit wizards and is where the user edits
most of the object’s attributes. It generally contains one to three parts: a read-
only context property panel, primary content input fields (for
FormatContentHolder objects only), and an attribute input table. Refer to the
illustration below.

– Context panel
Read-only information about the object being edited. This varies by
object type. Typically, the object type is displayed. If the object is
WTContained it also usually displays the container name. If the new
object is OrganizationOwned and the preference Display -> Expose
Organization is set to true it also typically displays the organization id.

Constructing Wizards 15-95


You will need to decide what, if any information needs to be displayed in
this panel for your object type.
– Primary content
Wizards to create objects that are FormatContentHolders, such as
WTDocuments, should have a section for the user to modify the primary
content item.
– Attribute input table
This typically contains input fields for all the editable soft and hard
attributes for the object type, except for part classification attributes,
which are entered on a following step. A few non-editable attributes,
such as Name in the illustration above, may be displayed at the top of the
table in read-only mode. You will need to decide what attributes should
be displayed in this table.
2. Set Classification Attributes 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(s) of the part in view mode at the top and then includes a
table of input fields for classification attributes.

15-96 Windchill Customizer’s Guide


3. Attachments Step
This step only applies to objects that are ContentHolders. It allows the user to
add and delete documents, links, and other content for the object. See the
Attachments section of the Customizing HTML Clients Using the Windchill
JSP Framework chapter on page 11-16 for information on incorporating this
step.

Creating the Action for Your Wizard


An action is needed to launch your wizard. This task is very similar to creating an
action for a create wizard. Refer the Creating the Action for Your Wizard
procedure in the Building Wizards to Create a Single Object section on page
15-97. 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 section on page 15-93 or a subclass of one of those classes.
We recommend you name your action (and main wizard jsp file) “edit.” If there
will be multiple edit actions for your objecttype based on launch point or other
criteria you can add a suffix further qualifying the action as shown below.
For example:

editFrom<launch page or table> Ex: editFromAttributesTable

edit<name for a subset of Ex: editAnnotations


attributes being edited>

Creating Actions and/or Service Property Entries for Your Wizard Steps
You may be able to use out-of-the-box action definitions for wizard steps that are
common to multiple wizards. The following wizard step actions are defined out-
of-the-box.

Step Objecttype Action definition/ File Location/ Associated JSP Page

Set Attributes object <action name="editAttributesWizStep" id="editAttributesWizStep"


preloadWizardPage="false" required="true" afterVK="editAttributes"
resourceBundle="com.ptc.core.ui.componentRB">
<command windowType="wizard_step"
url="servlet/TypeBasedIncludeServlet?contextAction=editAttributesWiz
Step"/>
</action>
Action file: <WT_HOME>/codebase/actions.xml
Associated jsp page: None

Constructing Wizards 15-97


Step Objecttype Action definition/ File Location/ Associated JSP Page

Set part <action name="setClassificationAttributesWizStep"


Classification id="setClassificationAttributesWizStep" hidden="true" required="true"
Attributes preloadWizardPage="false"
afterVK=”editAttributes”>
<command windowType="wizard_step"/>
</action>
Action file: <WT_HOME>/codebase/ config/actions/PartManagement-
actions.xml.
Associated jsp page:
<WT_HOME>/codebase/netmarkets/jsp/part/setClassificationAttributes
WizStep.jsp
Note: This is the same action used for this step in part create wizards

attachments_s attachments <action name="attachments_step" uicomponent="ATTACHMENTS"


tep (ContentHolde ajax="row" postloadJS="preAttachmentsStep"
r) preloadWizardPage="false">
<command
class="com.ptc.windchill.enterprise.attachments.forms.SecondaryAttach
mentsSubFormProcessor" windowType="wizard_step"/>
<includeFilter name="hideFromDTI" />
<includeFilter name="EDACompareFilter" />
</action>
Action file:
<WT_HOME>/codebase/config/actions/Attachments_actions.xml
Associated jsp page:
<WT_HOME>/codebase/netmarkets/jsp/attachments/attachments_step.js
p

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.
Also note that the Set Classification Attributes step is marked as hidden. It is
dynamically inserted into the wizard if the part is classified when the wizard
launches. It is dynamically removed if the user clicks the “Do Not Classify”
radio button in the "Set Attributes Step" to unclassify the part.
If these action definitions meet your requirements you do not need to define your
own actions for your wizard. However, you will need to define your own action
for a wizard step if either of the following is true:
• You need to define additional or different tag attributes for the step action
• Your step is unique to your wizard.

15-98 Windchill Customizer’s Guide


Note that you can use your own JSP for the Set Attributes step without defining
your own step action by use of the TypeBasedIncludeServlet described below.
See the Creating Actions and/or Service Property Entries for Your Wizard Steps
of the Building Wizards to Create a Single Object section on page 15-97 for more
information on creating step actions.

Creating service.properties Entries for the Set Attributes Step


The Creating service.properties Entries for the Set Attributes Step of the Building
Wizards to Create a Single Object section on page 15-99 describes how the
TypeBasedIncludeServlet is used to look up the jsp that should be used for some
wizard steps or portions of wizard steps. For edit wizards, the servlet is used to
look up the jsp that should be used for the Set Attributes step. This allows you to
use the common action definition for this step but still create and use your own
step jsp. If you have multiple wizards that differ only by the content of this step, it
also means you can use the same main wizard JSP and wizard action definition for
all of them. This is often the case when creating wizards for different subtypes of
the same base type.
To specify which jsp should be used for this step for a specific object type you
would include an entry like the following in a type-based service.properties file:
Xconf file:
<Resource context="default"
name="com.ptc.netmarkets.util.misc.FilePathFactory">
<Option requestor=" <object type to be edited> >"
resource=" <jsp file path relative to WT_HOME/codebase>.jsp"
selector="editAttributesWizStep"/>
</Resource>

Corresponding property file entry generated by the xconfmanager:


wt.services/rsc/default/com.ptc.netmarkets.util.misc.FilePathFacto
ry/editAttributesWizStep/

<object type to be edited>/0=<jsp file path relative to


WT_HOME/codebase>.jsp

Note that the selector string matches the contextAction parameter on the URL in
the step action.
For example, to use the jsp page
<WT_HOME>/codebase/netmarkets/jsp/ext/part/myPart/setAttributesWizStep.js
p for the Set Attributes step when editing objects of type ext.part.MyPart you
would add the following entry to a type-based service.properties xconf file:
<Resource context="default"
name="com.ptc.netmarkets.util.misc.FilePathFactory">
<Option requestor="ext.part.MyPart"
resource=
“/netmarkets/jsp/ext/myPart/setAttributesWizStep.jsp”
selector="editAttributesWizStep"/>
</Resource>

Constructing Wizards 15-99


Creating Your Step JSP Pages
See the Creating Your Step JSP Pages of the Building Wizards to Create a Single
Object section on page 15-63 for information on how to create your step jsps.
Differences between create and edit wizards are noted below.

Attribute Input Tables and Panels


The describePropertyPanel and describeAttributesTable tags for input fields
should have a mode parameter of “EDIT. ” The componentType parameter is
“WIZARD_ATTRIBUTES_TABLE,” just as for create.
Using EDIT mode will cause input fields to be generated for each attribute in the
table or panel by default. If you want a specific attribute to be displayed in read-
only mode you can override the default mode by specifying a mode parameter on
the describeProperty tag as shown in the example below:
<jca:describeAttributesTable var="attributesTableDescriptor"
scope="request"
id="create.setAttributes" mode="EDIT"
componentType="WIZARD_ATTRIBUTES_TABLE"
type="wt.part.WTPart" label="${attributesTableHeader}">

<jca:describeProperty id="name" mode="VIEW"/>

Developing Your Set Attributes Step JSP


Because the attributes on this step vary by object type, you will need to create
your own main jsp for this step. However, once you describe the contents of the
page there are jsp components available to help you acquire the data models for
and render the elements. These are the same components that are used for create
wizards.
The suggested name for this step jsp is:
editAttributesWizStep.jsp
or
editAttributesWizStepFor<object type>.jsp (if there is more than one of
these step jsps in the directory)
This step is very similar to the Set Attributes wizard step for create wizards.
Typically, it will include the following:
1. A describePropertyPanel tag for the read-only attributes panel at the top of the
step. This tag should have a mode parameter of “VIEW”. Also set the
following tag attributes if you are including setAttributesWizStep.jspf file to
obtain the data for and to render your panel:

Attribute Value

var “attributesStepReadOnlyPanel”

15-100 Windchill Customizer’s Guide


Attribute Value

id “attributesStepReadOnlyPanel”
(recommended, not required)

scope “request”

2. A describeAttributesTable tag for editing hard and soft attributes. The mode
of this tag should be set to “EDIT.” (See the section Attribute Input Tables
and Panels above for how to make individual attributes view-only.) You
should also set the following tag attributes if you want to use the out-of-the-
box jspf file described in the next step for getting the table model and
rendering the table.

Attribute Value

var “attributesTableDescriptor”

id “attributesTableDescriptor” (recommended,
not required)

scope “request”

If your object is a subtype of WTPart and you want to include a classification


picker in your table, you would add the following property to your table:
<jca:describeProperty id="classification.id"
label="${classificationLabel}"/>

and you must include the following hidden fields in the page:
<input id="selectedClfNodes" type="hidden"
name="selectedClfNodes" >

<input id="selectedClfNodesDisplayName" type="hidden"


name="selectedClfNodesDisplayName" >

3. If your object is a FormatContentHolder and you want to allow users to edit


the primary content input on this step, include the file
/netmarkets/jsp/document/setAttributesWizStepWithContent.jspf. This
contains the tag primaryAttachmentWithMSOI, which will render a section
for editing of primary content. See the Attachments section of the
Customizing HTML Clients Using the Windchill JSP Framework chapter on
page 11-16 for information on this tag. It also acquires the data for and
renders the read-only property panel and the attributes input table, providing
you have followed the naming conventions described in this section.
If your object is not a FormatContentHolder, include the file
/netmarkets/jsp/components/setAttributesWizStep.jspf. This does the same
things as setAttributesWizStepWithContent.jspf except that it does not
include a primaryAttachment tag.

Constructing Wizards 15-101


Note that these JSPFs are also used for create wizards. See the Sample Code
section on page 15-107 for an example page.

Adding Set Classification Attributes and Attachments Steps


JSPs for these steps are available out-of-the-box. You need only include the step
action in your main wizard JSP page. Customization of these steps is not
recommended.

Creating Data Validators For Your Steps


A default server-side validator is available for the Set Attributes step. The
selector key and validator class path are specified in the following entry in
components.service.properties.xconf:
<Option requestor="null"
serviceClass="com.ptc.core.components.validators.EditAttributes
StepValidator" selector="editAttributes" />

This validator works exactly like the SetAttributesStepValidator for create


wizards --- it also calls the preprocess() method of the wizard form processor to
validate the data against all constraints that were defined for the attributes in the
Rose model or Type Manager. If the out-of-the-box validator class meets your
needs you can use it by specifying the selector string shown in the entry above as
the value of the afterVK attribute of your wizard step action. If you need to do
additional validation, you can write your own validator, typically subclassing the
default validator.
The Set Classification Attributes step uses the same validator as the Set Attributes
step.
No validator is provided or needed for the attachments step.

Creating Your Main Wizard JSP Page


This should look much the same as that for a create wizard, with the differences
noted below. See the Sample Code section on page 15-107 for example JSPs.

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

15-102 Windchill Customizer’s Guide


This tag will check out the object to the current user before opening the wizard.
See the Solution Elements section on page 15-93 for more information.

InitializeItemTag
Like create wizards, edit wizards require 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.

Wizard Tag
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.
To include a Set Attributes step in your wizard you should provide a wizardStep
tag with the action name “editAttributesWizStep” (if you are using the common
step action shown in the Creating Actions and/or Service Property Entries for
Your Wizard Steps section on page 15-97) or the action name you specified on
your custom action.
To include Set Classification Attributes and/or Attachments steps, use the action
names shown for these steps in Creating Actions and/or Service Property Entries
for Your Wizard Steps section on page 15-97).

Classification Step Requirements


If your wizard includes a 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>

Constructing Wizards 15-103


.

<script language="Javascript">

Event.observe(window, 'load', 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.
If the Set Attributes step is not the first step in your wizard and it is not preloaded,
you will also need to include the following in your Set Attributes step jsp:
<script language="JavaScript"
src="netmarkets/javascript/part/PartHelper.js"></script>

<script language="Javascript">

Event.observe(window, 'load', loadClassificationStep);

</script>

Attachment Step Requirements


See the Attachments section of the Customizing HTML Clients Using the
Windchill JSP Framework chapter on page 11-16 for information on the elements
that must be included to incorporate this step.

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

15-104 Windchill Customizer’s Guide


These classes may be extended as necessary to meet your purposes.

Both of these processors do the following:


preProcess() method
– same as the preprocess() method of the CreateObjectFormProcessor
except that it creates a TypeInstance for a persisted object
doOperation() method
– 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
The setResultNextAction() method varies as follows:
DefaultEditFormProcessor.setResultNextAction()
(called by the DefaultFormProcessorController)

Constructing Wizards 15-105


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

15-106 Windchill Customizer’s Guide


the table below. Consult the javadoc for these classes for more information on
their behavior.

If your class extents Use processor class

WTChangeIssue com.ptc.windchill.enterprise.change2.forms.process
ors.EditProblemReportFormProcessor

WTChangeRequest2 com.ptc.windchill.enterprise.change2.forms.process
ors.EditChangeRequestFormProcessor

WTChangeOrder2 com.ptc.windchill.enterprise.change2.forms.process
ors.EditChangeNoticeFormProcessor

WTChangeActivity2 com.ptc.windchill.enterprise.change2.forms.process
ors.EditChangeTaskFormProcessor

WTVariance com.ptc.windchill.enterprise.change2.forms.process
ors.EditVarianceFormProcessor

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 the
Creating Your Form Processor and Form Processor Delegates section on page
15-75 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.

Sample Code

JSP for the Set Attributes Step of the Edit Part Wizard
Filename:
<WT_HOME>/codebase/netmarkets/jsp/part/editPartAttributesWizStep.jsp
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>
<%@ taglib tagdir="/WEB-INF/tags" prefix="tags"%>

<%@ page import="com.ptc.windchill.enterprise.part.partResource" %>


<%@ page import="com.ptc.windchill.enterprise.part.PartConstants"
%>

<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>


<%@ include
file="/netmarkets/jsp/components/createEditUIText.jspf"%>

Constructing Wizards 15-107


<fmt:setBundle
basename="com.ptc.windchill.enterprise.part.partResource"/>

<fmt:message var="classificationLabel" key="<%=


partResource.CLASSIFICATION_LABEL %>" />
<fmt:message var="locationLabel" key="<%=
partResource.LOCATION_LABEL %>" />
<fmt:message var="typeNameLabel" key="<%=
partResource.TYPE_NAME_LABEL %>" />

<fmt:message var="minimumRequiredLabel" key="<%=


partResource.MINIMUM_REQUIRED_LABEL %>" />
<fmt:message var="maximumAllowedLabel" key="<%=
partResource.MAXIMUM_ALLOWED_LABEL %>" />

<%--> Read-only context panel <--%>


<jca:describePropertyPanel var="attributesStepReadOnlyPanel"
id="attributesStepReadOnlyPanel"
scope="request" mode="VIEW" type="wt.part.WTPart">

<jca:describeProperty id="containerName"
label="${createBean.containerLabel}"/>
<jca:describeProperty id="partTypeName"
label="${typeNameLabel}"/>
<jca:describeProperty id="orgid" need="organization.id"/>

</jca:describePropertyPanel>

<%--> Attributes input table <--%>


<jca:describeAttributesTable var="attributesTableDescriptor"
scope="request"
id="create.setAttributes" mode="EDIT"
componentType="WIZARD_ATTRIBUTES_TABLE"
type="wt.part.WTPart" label="${attributesTableHeader}">

<jca:describeProperty id="number" mode="VIEW"


isInfoPageLink="false"/>
<jca:describeProperty id="name" mode="VIEW"/>
<jca:describeProperty id="version" mode="VIEW"/>
<jca:describeProperty id="partType"/>

<%-->
Source uses a special data utility to hide the other options
except 'Buy' if SUMA is installed and the part type is
manufacturing or vendor
<--%>
<jca:describeProperty id="source"/>

<%-->
The following 3 are WADM specific attributes. They are hidden by
the PartSolutionGroup logic if WADM is not installed.
<--%>
<jca:describeProperty
id="<%=PartConstants.ColumnIdentifiers.WADM_CONTRACT_NUMBER%>"/
>

15-108 Windchill Customizer’s Guide


<jca:describeProperty
id="<%=PartConstants.ColumnIdentifiers.WADM_JOB_AUTH_NUMBER%>"/
>
<jca:describeProperty
id="<%=PartConstants.ColumnIdentifiers.WADM_PHASE%>"/>

<jca:describeProperty id="classification.id"
label="${classificationLabel}"/>

<jca:describeProperty id="minimumRequired"
label="${minimumRequiredLabel}"/>
<jca:describeProperty id="maximumAllowed"
label="${maximumAllowedLabel}"/>

<jca:describeProperty
id="ALL_CUSTOM_HARD_ATTRIBUTES_FOR_INPUT_TYPE"/>
<jca:describeProperty
id="ALL_SOFT_NON_CLASSIFICATION_SCHEMA_ATTRIBUTES"/>

</jca:describeAttributesTable>

<%--> The following fields are necessary for the classification


picker in the table above <--%>
<input id="selectedClfNodes" type="hidden" name="selectedClfNodes"
>
<input id="selectedClfNodesDisplayName" type="hidden"
name="selectedClfNodesDisplayName" >

<%@ include
file="/netmarkets/jsp/components/setAttributesWizStep.jspf"%>
<%@ include file="/netmarkets/jsp/util/end.jspf"%>

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.productResourceClient
" %>
<%@ 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.productResourceClie
nt" />

Constructing Wizards 15-109


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

15-110 Windchill Customizer’s Guide


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

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

<% } %>

Constructing Wizards 15-111


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

<% } %>

<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


AttachmentsStepActionValidator hooked up to it

<--%>

<jca:wizardStep action="attachments_step"
label="${attachmentsWizStepLabel}" type="attachments" />

</jca:wizard>

<%@include file="/netmarkets/jsp/util/end.jspf"%>

15-112 Windchill Customizer’s Guide


Additional Resources

Related Package/Class Javadoc


com.ptc.core.components.forms.DefaultEditFormProcessor
com.ptc.core.components.forms.EditWorkableFormProcessor
Also see the Related Package/Class Javadoc of the Building Wizards to Create a
Single Object section on page 15-89.

Constructing Wizards 15-113


15-114 Windchill Customizer’s Guide
16
Information Pages

This chapter describes how to customize information pages.

Topic Page
Information Pages..............................................................................................16-2

16-1
Information Pages

Objective
You want to create an object information page specific to a given business object.

Solution
Use the Info Page Common Component with an info.jsp file associated to that
object type.

Design Overview
There are many types of business objects in Windchill, plus potentially many soft
types or modeled object types introduced by customers. Each type of object can
potentially have its own associated information page, a page that displays
information around a selected instance of that type. While the information
associated with different object types can vary widely, it is important to maintain
a common look and feel among the multitude of information pages. The info page
component was developed to give the Windchill products consistency for
displaying an object details page. The component is also intended to make
developing an info page much easier. Using the component, a developer only
needs to configure certain parts of the page (list of actions, which attributes to
show, etc.) while the main layout of the page is provided by the component.

Applicability
This documentation should be used for configuring the info page for some
business object in one of the Windchill products.

16-2 Windchill Customizer’s Guide


Structure

Design Elements
The info page component
• Page title area
• Top attributes panel
• Visualization area
• Navigation menu
• Filter area
• Content area
• Global navigation
• Type-specific data

Information Pages 16-3


• Actions list
• Recently visited list
• Auditing service
• Object attributes
• Status glyphs

Collaborations
• The info page component controls the layout of the various other components
on the page; page title area, top attributes panel, visualization area, navigation
menu, filter area, and content area, as well as including the global navigation.
• The info page component supports type based lookups (including soft types)
for the type specific data, attributes, 3rd level navigation menu.
• The info page component hooks up to the global navigation as appropriate
(e.g.: tab highlighting)
• The info page component displays the correct action list based on object type
• The info page component registers the object in the recently visited list
• The info page component registers the user and the object in the auditing
service for the view event
• The info page component does role based checking on attributes
• The info page component allows Status Glyph Indicators

Consequences
By following this documentation the configuration of all objects info pages should
be done in a consistent manner. This will make maintaining these info pages a
much easier and more manageable task and have a consistent user model.

Implementation

Overview
The info page component was developed using the Windchill client architecture.
This component provides a common layout for an object’s information page as it
is displayed in any of the Windchill products. Using the info page component will
provide consistency between all objects and Windchill products. The specific
content that is displayed for any given object type will be configured by
overriding certain elements in the context of the specific object types.
Configurable portions of the page include things like which action list is used and
which attributes are shown in the top attribute panel.

16-4 Windchill Customizer’s Guide


What is the component
• it is a combination of a jsp, bean, taglib, renderers and service call(s).
• it follows user interface standards
• it is Section 508 compliant per requirements
• it supports customization requirements
• it supports Soft type/attribute
• it follows a standard format for the Item Identification release specific
recommendationIdentifying the object
• it supports the Object Icon including support for soft types and part flavors
like Generic
• it supports third level Navigation stickiness and remembers the last third level
navigation table that the user was viewing. per navigation specification
The default info page implementation will only contain the object icon, the name of the
object, and possibly a link to the action list if one has already been configured
To display more than the default provides, you can create a new jsp that is
configured for your type. All the details links (e.g. , ) will lead to
the same servlet.
As shown below, the TypeBasedInclude servlet receives the request for an info
page and determines which navigator delegate to use. The navigator delegate
determines which jsp to redirect to based on the object type and the state of the
object. A jsp using the info page common component would include
netmarkets/jsp/components/infoPage.jspf.

Using the component


In the default information page, only the name of the object, the object icon and
possibly a link to the action list would appear.
Most likely, for your object type, you will want to override the default set of
information that is displayed. The configurable portions of the page are:
• Action list displayed in the top attributes panel
• Visualization area

Information Pages 16-5


• Status glyphs
• Help context
• Attributes displayed in the top attributes panel
• Third level navigation menus
• Actions contained in each third level navigation menu
• Default third level content table and table view

Create a jsp for your object type

Create a jsp
Your info page jsp will have a describeInfoPage tag, a describePropertyPanel tag,
and an include of the info page component, infoPage.jspf. Based on the
configuration in the describeInfoPage and describePropertyPanel tags, the
infoPage.jspf component will render the object icon, object identification, status
glyphs, help link, action list, attributes panel (property panel), visualization
component, 3rd level navigation and 3rd level navigation content.
Before the include of infoPage.jspf, your jsp can set up what information is
displayed on the page. (e.g. what attributes to show, whether or not visualization
applies, what action model to use for 3rd level nav etc.) See section 9.4 for the
properties that can be configured in your info page jsp:
For example:
<jca:describePropertyPanel var="propertyPanelDescriptor">
<jca:describeProperty id="name" />
<jca:describeProperty id="number" />
</jca:describePropertyPanel>

<jca:describeInfoPage showVisualization="true"
helpContext="part_details_help"
navBarName="third_level_nav_part"
propertyPanel="${propertyPanelDescriptor}">
<jca:describeStatusGlyph id="statusFamily_Share" />
<jca:describeStatusGlyph id="statusFamily_General" />
<jca:describeStatusGlyph id="statusFamily_Change" />
</jca:describeInfoPage>

Register 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.FragmentFa
ctory/InfoPage/java.lang.Object/0=/netmarkets/jsp/object/info.j
sp

16-6 Windchill Customizer’s Guide


wt.services/rsc/default/com.ptc.netmarkets.util.misc.FragmentFa
ctory/InfoPage/<fully qualified class path>/0=<jsp path
relative to codebase>.jsp

Here is an example of the xconf format:

<Resource context="default"
name="com.ptc.netmarkets.util.misc.FilePathFactory">
<Option requestor="<fully qualified class path>"
resource="<jsp path relative to codebase>"
selector="InfoPage"/>
</Resource>

See the About the xconfmanager Utility section in the Windchill Utilities chapter
on page 6-2 for more information.

Specify Status Glyphs to show in the Title Bar


<jca:describeInfoPage …>
<jca:describeStatusGlyph id="<Status Glyph Family Id>" />
</comp:describeInfoPage>

Specify the Attributes to include


<jca:describePropertyPanel var="propertyPanelDescriptor">
<jca:describeProperty id="<attribute name | data utility id |
logical form>" />
<jca:describeProperty id="<attribute name | data utility id |
logical form>" />
</comp:describePropertyPanel>

<jca:describeInfoPage propertyPanel="${propertyPanelDescriptor}">

</comp:describeInfoPage>

To determine the set of available properties that can be displayed for an object
type, you can use the property report.

Information Pages 16-7


Configure Action List Actions
The Actions that apply for a particular object type are configured in actionmodels.xml.

To specify which actionmodel to use as the actions list for a specific class or
softtype, use the attribute menufor as specified in the following example:
<!-- Part information page Actions list -->
<model name="more parts actions" menufor="wt.part.WTPart">
<action name="view" type="object"/>
<action name="viewDefaultRepresentationPV" type="wvs"/>
<action name="viewDefaultRepresentationPVLite" type="wvs"/>
<action name="launchPSE" type="explorer" />
<action name="launchABE" type="explorer" />
<action name="separator" type="separator"/>
<action name="checkin" type="wip"/>
<action name="checkout" type="wip"/>
<action name="undocheckout" type="object"/>
…..
For example:
<!-- your comment here -->
<model name="<your_action_model_name>" menufor="<fully qualified
classpath>">
<action name="view" type="object"/>
</model>
Or, if you want to have multiple classes or soft types you can comma separate the
list:

16-8 Windchill Customizer’s Guide


<model name="more meeting actions"
menufor="wt.meeting.TraditionalMeeting,wt.meeting.MeetingCenterMee
ting">
<action name="host" type="meeting"/>
<action name="join" type="meeting"/>
<action name="add_minutes" type="meeting"/>
</model>

The info page uses what is registered in actionmodels.xml with menufor as the
action list. You can override what is registered in actionmodels.xml by
configuring the describeInfoPage with a different actionListName to use:
<jca:describeInfoPage actionListName="<action model name>" >

</jca:describeInfoPage>

If no actions list should be displayed you can specify that also:


<jca:describeInfoPage actionListName="" >

</jca:describeInfoPage>

Indicate if Visualization applies


By default visualization is hidden. You can configure your info page to show
visualization by setting showVisualization to true.
<jca:describeInfoPage showVisualization="<true/false>" >

</jca:describeInfoPage>

Specify the help context to use


To specify a help topic for the info page a service.properties.xconf entry is needed and the
help selector key from that entry can be added to the describeInfoPage tag.
<Resource context="default" name="wt.help.HelpTemplate">
<Option requestor="<context class>" resource="<help file
path>" selector="<help selector key"/>
</Resource>

For example:
<Resource context="default" name="wt.help.HelpTemplate">

Information Pages 16-9


<Option requestor="java.lang.Object"
resource="online.pdm_prodmgmt.PMPartStructureEdit"
selector="PMPartStructureEdit_help"/>
</Resource>

Selector is a help selector key that will be set on the describeInfoPage tag. In the
above example it is PMPartStructureEdit_help.
Resource is the help file location and is assumed to be an html file. The help file
gets a base of $WT_HOME/codebase/wt/helpfiles/help_<locale>
Hence in the above example where
resource="online.pdm_prodmgmt.PMPartStructureEdit" the english help file will
be:
$WT_HOME/codebase/wt/helpfiles/help_en/online/pdm_prodmgmt/PMPartS
tructureEdit.html

Requestor is the class of the container context that the object is in. For example,
parts could be created in either Products or Projects. If the help topic for parts in
Projects had to be different from the help topic for parts in Products, an entry
could be added with requestor="wt.projmgmt.admin.Project2".
Once the above xconf entry is created, the help topic can be set on the info page
by adding the selector on the describeInfoPage tag:
<jca:describeInfoPage helpContext="<help selector key>" >

</jca:describeInfoPage>

Specify the Third Level Navigation Menubar to use

<jca:describeInfoPage navBarName="<action model name>" >



</jca:describeInfoPage>

Configure the Third Level Navigation Menus for your object type
The following is an example configuration of a third level navigation menu for the
part info page:
<!-- Part information page 3rd level nav menu bar -->
<model name="third_level_nav_part">
<action name="productStructure" type="object"/> <!-- Structure -->
<submodel name="general"/> <!-- General -->

16-10 Windchill Customizer’s Guide


<submodel name="relatedItems"/> <!-- Related Objects -->
<submodel name="history"/> <!-- History -->
<submodel name="collaboration"/> <!-- Collaboration -->
</model>

As you can see it is a combination of an action and submodels. An action in the 3rd level
nav bar will be displayed as just a link. (e.g. Product Structure browser) A submodel in the
3rd level nav bar will be displayed as a drop down menu (e.g. Related Items menu)
The General, Related Items, History and Collaboration menus are meant to be reused for
all object types. Actions that do not apply for certain object types will be removed via
action validation. So your action model would probably look something like this:
<!-- your comment here -->
<model name="<your_action_model_name>">
<submodel name="general"/> <!-- General -->
<submodel name="relatedItems"/> <!-- Related Objects -->
<submodel name="history"/> <!-- History -->
<submodel name="collaboration"/> <!-- Collaboration -->
</model>

Create a new 3rd level nav action


To create a new 3rd level nav action. See the Adding Actions and Hooking Them
Up in the UI chapter on page 12-1 for more information on actions. Register the
action. Add the action to the action model. Create the jsp for the action. The jsp
just has to have the 3rd level nav content between begin.jspf and end.jspf.
For example, if a jsp had this content:
<%@ include file="/netmarkets/jsp/util/begin.jspf"%>
<b>Related Parts table goes here...</b>
<table border=1>
<tr><td>A</td><td>B</td></tr>
<tr><td>C</td><td>D</td></tr>
</table>
<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Then the image below would be the resulting 3rd level nav content (the action that
led to the above jsp was added to the relatedItems submodel so that is why
“Related Objects” is highlighted)

Information Pages 16-11


Setup

Default Possible
Parameter Value Values Req? Description

Attribute None See section No describeProperty tag nested in


Specify the describePropertyPanel tag
Attributes to
include

statusGlyph None TBD Specify No describeStatusGlyph tag nested in


Status Glyphs describeInfoPage tag
to show in the
Title Bar

helpContext None User defined. No As attribute on the describeInfoPage


Specify the tag
help context to
use

navBarName None User defined No As attribute on the describeInfoPage


in tag
actionmodels.
xml.

actionListName The action User defined No As attribute on the describeInfoPage


model in tag
specified in actionmodels.
actionmodels.x xml. Set only
ml based on if you want to
classname that override
is in the oid. menufor
setting in
actionmodels.
xml.

Sample Code

Example implementation for the InfoPageComponent


This is an example of how the info page could be configured for some object type.
Assume you are configuring the info page for wt.part.CoolPart. These steps
reference codebase locations only. These steps do not include instructions for
source placement or best practices for usage of xconf files.
1. Create a jsp file called info.jsp and place it in the following location in your
codebase
codebase/netmarkets/jsp/coolpart

16-12 Windchill Customizer’s Guide


For now, just add the following content to the page:
<%@ include file="/netmarkets/jsp/util/begin.jspf"%>
<H2>This will be the cool part details page</H2>
<%@ include file="/netmarkets/jsp/util/end.jspf"%>

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/InfoPage/wt.part.CoolPart/0=/netmarkets/jsp/coolpart/info
.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/TypeBasedIncludeSer
vlet?oid=OR:wt.part.CoolPart:62028

The servlet will look up which jsp to forward to in typedservices.properties.


You should see the text that you typed into your jsp in step 1.
4. Now, let’s add some content to your page. First, you’ll need the jca
components taglib:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>

5. Then, you’ll need to describe a property panel that contains the attributes that
apply for your object type. Using the property report on your build (see
Property Report on page 15-64), find the attribute names you want to use:
<jca:describePropertyPanel var="propertyPanelDescriptor">
<jca:describeProperty id="name" />
<jca:describeProperty id="number" />
</jca:describePropertyPanel>

6. Next, describe the info page. Specify the third level nav, the help file, whether
visualization applies, which property panel to use, and the status glyph
families to be shown:
<jca:describeInfoPage showVisualization="true"
helpContext="<cool_part_info_help>"
navBarName="<third_level_nav_for_cool_part>"
propertyPanel="${propertyPanelDescriptor}">
<jca:describeStatusGlyph id="statusFamily_Share" />
<jca:describeStatusGlyph id="statusFamily_General" />
</jca:describeInfoPage>

7. After setting up the describePropertyPanel and describeInfoPage tags include


the infoPage.jspf. The component will acquire the necessary data (attributes,
icon images, action models, etc.) and display the info page (attribute panel,
title bar, 3rd level nav, etc.)
<%@ include file="/netmarkets/jsp/components/infoPage.jspf"%>

Information Pages 16-13


Here is the example info.jsp:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>
<%@ include file="/netmarkets/jsp/util/begin.jspf"%>

<jca:describePropertyPanel var="propertyPanelDescriptor">
<jca:describeProperty id="name" />
<jca:describeProperty id="number" />
</jca:describePropertyPanel>

<jca:describeInfoPage showVisualization="true" helpContext="<cool_part_info_help>"


navBarName="<third_level_nav_for_cool_part>"
propertyPanel="${propertyPanelDescriptor}">
<jca:describeStatusGlyph id="statusFamily_Share" />
<jca:describeStatusGlyph id="statusFamily_General" />
</jca:describeInfoPage>

<%@ include file="/netmarkets/jsp/components/infoPage.jspf"%>


<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Implementation of Info Page with No 3rd Level Navigation


Some info page instances do not require a third level navigation menu. For
instance when there are few enough tables that all the tables should just display on
the screen by default. For these cases, simply omit the navBarName attribute:
<jca:describeInfoPage navBarName="<action model name>" >

</jca:describeInfoPage>

Or include the line, but with the navBarName value as an empty string:
<jca:describeInfoPage navBarName="" >

</jca:describeInfoPage>

Known Uses
Many out-of-the-box business objects in Windchill have info pages that are built
using the Info Page component. Here are a couple examples:
• WTPart – codebase/netmarkets/jsp/part/info.jsp
• WTDocument – codebase/netmarkets/jsp/document/info.jsp

16-14 Windchill Customizer’s Guide


17
Incorporating Pickers in JSP
Clients

This chapter describes how to customize and configure pickers.

Topic Page
Picker Interaction ............................................................................................. 17-2
Common Picker Configuration Options......................................................... 17-14
Configuring a Context Picker......................................................................... 17-18
Configuring an Item Picker ............................................................................ 17-24
Configuring an Organization Picker............................................................... 17-31
Configuring a Type Picker ............................................................................. 17-37
Configuring a User Picker.............................................................................. 17-50
Configuring a Participant Picker .................................................................... 17-57

17-1
Picker Interaction

Objective
You want to configure a property picker in some wizard step and manage
interaction between that page and the picker.

Background
There are many types of business objects in Windchill, plus potentially many soft
types or modeled object types introduced by the user. These types would
predominantly would have some relationship with the other types. There are
numerous instances when user creates or updates objects of such types using an
user interface, he would need to specify the property value(s) derived from the
other available objects of the same or different type. e.g. The business object like
Part or Document are owned by a specific organization and hence at the time of
their creation user needs to be able to specify an owning organization.
This sort of user interaction is achieved through the use of property picker. The
property picker simply aids in picking up a property from an existing business
object. The user would pick an object by launching the picker and have it’s pro
properties used to update visible and/or non-visible properties on the page. The
following sketch illustrates this sort of interaction pictorially.

Scope/Applicability/Assumptions
Assume you have a customized type <myObjectType> object needing to be
created. On the first step of the create wizard, you need to define a relation ship
with an object of type <someObjectType>. This spawns a need to let user select
the object he desires from a picker and have the attributes of these objects used to
populate some content on the first step of the create wizard.

17-2 Windchill Customizer’s Guide


Intended Outcome
By following this design concept, the property picker user model would be
consistent with the one that exists across the product at multiple places.

Solution
Follow the design concept as described to facilitate the picker interaction.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving HTML forms, JSP, JavaScript based DOM
manipulations, AJAX
• The actions framework in the Windchill client architecture
• The table component to list the objects.
• The wizard component in the Windchill client architecture

Incorporating Pickers in JSP Clients 17-3


Solution Elements
Element Type Description

picker.tld tld Tag Library Descriptor (TLD) file, which contains


Picker related Tag definitions. The
‘propertyPicker’,’populate’ and ‘pickerParam’ are the
ones needed to be used to implement this design
concept.
Run time Location:
<Windchill>\codebase\WEB-INF\tlds\

create_step_<step no>.jsp JSP This JSP page provides the content for the specified
step of the Create Wizard . This step would include
the controls to launch a picker and populate values
from the picked object.
This JSP could as well render a javascript picker
callback function to be executed once the picker ‘OK’
action is executed.
Run time Location:
<Windchill>\codebase\netmarkets\
<myObjectType>\create_step_<stepno>.jsp

<someObjectType>_picker.jsp JSP This JSP page defines a single step wizard with ‘OK’
and ‘Cancel’ actions for the wizard. The wizard step
would render a content that presents a list of
<someObject> in table or tree component. The user
would select the object of interest by ticking the check
boxes to select row(s) in the table.
Run time Location:
<Windchill>\codebase\netmarkets\<
someObjectType >\
<someObjectType>_picker.jsp

<someObjectType>_picker_st JSP This JSP page defines the content for the picker
ep.jsp wizard step. This step can contain a table listing the
objects of <someObjectType> or search criteria along
with
Run time Location:
<Windchill>\ codebase\netmarkets\<
someObjectType >\
<someObjectType>_picker_step.jsp

17-4 Windchill Customizer’s Guide


Element Type Description

Actions.xml XML The file has definitions of all the actions. The action
that launches picker need to get defined for the type
<myObjectType>. The picker wizard step actions as
well get defined in this file.

picker.jspf JSPF JSP fragment to be always included by the picker


implementation i.e. in
<someObjectType>_picker_step.jsp
Run time location:
<Windchill>\codebase\netmarkets\components\
picker.jspf

defaultPickedDataFetcher.jsp JSP Default Picker Data Fetcher available in the product.


It uses the ‘oids’ passed to get the specified attributes.
The ‘oid’ and attribute information is compiled into a
string as JSON representation to be sent back as http
response.
Run time location:
<Windchill>\codebase\netmarkets\components\
defaultPickedDataFetcher.jsp

Procedure – Creating a Picker Interaction


This section defines the exact steps to implement a picker.

Implement a Picker as a single step wizard


Author a JSP page named as <someObjectType>_picker.jsp. This JSP page must
include a single step wizard using the wizard component of the Windchill Client
Infrastructure. The jsp would look like this:
<%@ page errorPage="/netmarkets/jsp/util/error.jsp"%>
<%@ page import=" ……. %>
<jsp:useBean …… scope="request" > <!—As the wizard step content
might have a flexibility in presenting itself and can be
controlled by the picker parameters, these parameters could be
passed to the step using a bean with request scope ‡
<%@ include file="/netmarkets/util/beginPopup.jspf"%>
<%@include file=”/netmarkets/components/picker.jspf”%>
…….
……..
……..
<script language="JavaScript1.2"> <!—sets a callback to javascript
function on hitting ‘ok’ action ‡
setUserSubmitFunction(onOK);
</script>

<%--> Wizard Step. <--%>


<jca:wizard buttonList="OkCancelWizardButtons">

Incorporating Pickers in JSP Clients 17-5


<jca:wizardStep action="<someObjectType>_picker_step "
type="<someObjectType>"/>
</jca:wizard>

<!—Javascript callback function for wizard ‘OK’ action goes here ‡


<!- OK callback definition start ‡
……..
<!—OK callback definition end ‡
<%@ include file="/netmarkets/jsp/util/end.jspf"%>

The ‘picker.jspf’ is needed to be included in the picker page always. It defines the
following javascript window variables to track the pickerCallback and
jcaPickerCallback functions. These windows variables are needed to be used in
the ‘OK’ action javascript user submit function .
The ‘setUserSubmitFunction’ is needed to be invoked to configure wizard ‘OK’
action to invoke a javascript function.
The javascript callback definition would be as well included in this page, the
definition of this callback and any other definitions of functions the callback calls
need to be placed preferably before the ‘end.jspf’ is included.

Implement a Picker step


The picker step content would get defined by the codebase\netmarkets\<
someObjectType >\<someObjectType>_picke_stepr.jsp. This step would render a
search client or just a listing table to allow the user select the objects from. The
details on how this could be done can be found out in the documentation for
Search Picker OR table component.

Provide definition of the javascript function to be invoked on ‘OK’ action


The javascript callback definition would be as well included in this page, the
definition of this callback and any other definitions of functions the callback calls
need to be placed preferably before the ‘end.jspf’ is included. This java script
function has to fulfill the following responsibilities –
• It would not have any arguments to it.
• It scans the page and sifts through the table or tree data to identify what
objects have been selected, if any are selected builds an array of these objects.
• Invokes a pickedDataFetcher uri using AJAX and the array of objects selected
passed over query string parameters as ‘oid=<oid_value>’ parameters that the
pickedDataFetcher URI can understand.
• The AJAX request returns the response

Use a picker
To use the existing picker, the user would have to perform the following
procedures.
Define the action to launch a picker

17-6 Windchill Customizer’s Guide


The action needs to be defined in codebase\actions.xml as follow.
<objecttype name="< myObjectType> " class=">">

<action name="launch<SomeObjectType>Picker">

<command windowType="popup"/>

</action>

</objecttype>

Create the HTML form elements to be updated using the picker


Create the visible input fields that need to be updated as a part of the picker
interaction using the AbstractGuiComponent to the client page i.e.
create_step_<step no>.jsp. See the Presenting Information in the UI chapter on
page 14-1 for more information on how to use GUI components.
The following describes how to add a textfield.
<%

TextBox<SomeObjectType> name = new TextBox();

tab_tbox.setId("<SomeObjectType>Name_tbox_id");

tab_tbox.setName("<SomeObjectType>Name_tbox_id");

RenderingContext tab_rcontext = new


RenderingContext();

%>

<c-rt:set var="tbox" value="<%=<SomeObjectType> name %>"/>

<c-rt:set var="tboxId" value="<%=<SomeObjectType> name


.getId()%>"/>

Create the non-visible input fields that would be as well updated as a part of the
picker interaction in the client page mentioned above.
<input id="<SomeObjectType>Reference" type="hidden" value=" " />

Use the tags


Use the ‘PropertyPickerTag’ in client page, i.e. create_step_<step no>.jsp,
utilizing the information from the ‘Create HTML form elements to be updated
using the picker’ section as follows
<p:propertyPicker propertyLabel="<SomeObject>" propertyField="${
tbox }" action=" launch<SomeObjectType>Picker " type="<
myObjectType>">

<p:populate from="name" to="${ tboxId }" />

<p:populate from="oid" to="<SomeObjectType>Reference 2" />

<p:pickerParam name="pickerId" value="userPicker1" />

<p:pickerParam name="objectType" value="wt.org.WTUser" />

Incorporating Pickers in JSP Clients 17-7


<p:pickerParam name="componentId" value="pickerSearch" />

</p:propertyPicker>

The above usage supposes that user would be interested in using the ‘name’ and
‘oid’ attributes from the information extracted for the pickedObject.

Default Data Fetcher


The default data fetcher is implemented in the form of a ‘jsp’ page invoked using
the AJAX asynchronous request. This page looks for the pickedOids and
attributes query string parameters in the request. The page then invokes an
Info*Engine webject to extract the attribute values for the specified Oid. The Oid
could be in the form of Object Reference or Version Reference or UFID. The page
returns the extracted information as a single string from which one can easily
construct the javascript object. Such a string would look like
{"pickedObject": [{"oid":"uid=wcadmin,ou=people,cn=koakx10-
44,dc=ptcnet,dc=ptc,d

c=com","class":"wt.org.WTUser","name":"Administrator"},{"oid":"uid
=demo,ou=peopl

e,cn=koakx10-
44,dc=ptcnet,dc=ptc,dc=com","class":"wt.org.WTUser","name":"demo"}
]

Default Callback function


The default callback function is authored using the ‘populate’ tag information, it
does the task of updating the html form input text fields specified by the ‘id’ using
the attribute information for the object picked which is made available in the form
of a javascript object. The default callback function would be of the following
form and would be unique for each of the picker occurrence.
function jcaPickerCallBack0(objects)
{
document.getElementById("b1").setAttribute("value",objects.pickedO
bject[0].name);
document.getElementById("b2").setAttribute("value",objects.pickedO
bject[0].oid);
}
function jcaPickerCallBack1(objects)
{
document.getElementById("c1").setAttribute("value",objects.pickedO
bject[0].name);
document.getElementById("c2").setAttribute("value",objects.pickedO
bject[0].oid);
}

17-8 Windchill Customizer’s Guide


Customization Points

propertyPicker tag attributes


This tag configures a property picker.

Default
Parameter value Possible values Required? Description

label Any String Value Yes The localized display label of the
property the value of which is to
be populated using a picker.

field AbstractGuiComp Yes The AbstarctGuiComponent


onent object like TextBox that would
be used to render the form field
that would be populated from
picker object.

name Any String value Yes The name of the action as it exists
in ‘actions.xml’

type Any String value Yes The ‘type’ of the action for which
the definition exists in
‘actions.xml’ that would launch
the picker.

renderingCont RenderingContext Yes Rendering context to be used for


ext the AbstractGuiComponent
specified through a ‘field’
attribute

populate tag attributes


This tag configures source attribute of the picked object to be used to populate a
target property on the client page. The tag would be always encapsulated in the
propertyPicker tag.

Possible
Parameter Default values values Required? Description

from Any String Value Yes Specifies the name of the property
(attribute) of the picked object

Incorporating Pickers in JSP Clients 17-9


Possible
Parameter Default values values Required? Description

to Any String value Yes HTML 'id' of the form input element
but adhering to to update on the parent page.
HTML ‘id’
attribute
specification
criteria

pickerParam tag attributes


This tag configures the ‘name=value’ URL query string parameters to drive the
actual picker content. The tag would be always encapsulated in the propertyPicker
tag.

Possible
Parameter Default values values Required? Description

name Any String Value Yes Name of the query string


parameter to be passed to the
popup picker

value Any String Value Yes Value of the URL query string
parameter to be passed to the
popup picker.

Sample Code
User can refer to the following code which is available in the product, it is a type
picker.
codebase\WEB-INF\tags\organizationPicker.tag - Defines the organizationPicker
tag definition that uses internally the propertyPicker tag. Just a way to encapsulate
abstract design concept.
Following snippet of java scriptlet code, creates the visible and invisible form
fields to be updated using the information from the picked objects
<%…….

String displayFieldId =
id+SearchWebConstants.DISPLAY_FIELD_LABEL;

RenderingContext rc = new RenderingContext();

TextBox tb = new TextBox();

tb.setId(displayFieldId);

tb.setName(displayFieldId);

tb.setValue(defaultValue);

17-10 Windchill Customizer’s Guide


if("true".equals(readOnlyPickerTextBox)) {

tb.addJsAction("readonly","readonly");

tb.setWidth(Integer.parseInt(pickerTextBoxLength));

tb.setMaxLength(Integer.parseInt(pickerTextBoxLength));

%>

<input id="<%=id%>" name="<%=id%>" value="<%=defaultHiddenValue%>"


type="hidden"/>

The following snippet of code propagates selectively the parameters passed to the
organizationPicker tag to the propertyPicker tag
<p:propertyPicker label="${label}" field="${textbox}"
action="callSearchPicker" type="search">

<p:populate from="${displayAttribute}"
to="${displayFieldId}" />

<p:populate from="oid" to="${id}" />

<p:pickerParam name="pickerId" value="${id}" />

….

</p:propertyPicker>

codebase\netmarkets\jsp\search\callSearchPicker.jsp - Defines the Picker Wizard


codebase\netmarket\jsp\search\searchPicker.jsp - Defines the content for the
Wizard step
Following includes all the javascript code needed to manage the picker
interaction.
<script language="javascript"
src="<%=wncurl%>netmarkets/jsp/search/pickerSearch.js"> </script>

Following ensures specified JSP fragment is added by the picker implementation.


<%@ include file="/netmarkets/jsp/components/picker.jspf"%>

Following ensures that the search criteria and search results table are as well
added to the step content.
………

<TABLE>

<%@ include file="/netmarkets/jsp/search/pickerAttributes.jsp"%>

……..

<%@ include file="/netmarkets/jsp/search/searchResults.jsp"%>

……….

Incorporating Pickers in JSP Clients 17-11


codebase\netmarkets\jsp\search\pickerSearch.js – Defines the javascript
functions needed to be used to manager this picker interaction
Following javascript function defines the callback function being used on the
Wizard OK action, it collects the selected objects using their ‘oids’ and invokes
the data fetcher URI using AJAX.
function getSelectedValue() {

……

The AJAX callback function is defined below which is actually responsible to use
the AJAX response as JSON object and populate information on the client page
using the picker callback function
function updateParent() {

…….

codebase\netmarkets\components\picker.jspf – Defines picker interaction specific


‘must include’ code, to be included in picker implementation.
The following javascript snippet inserted in the jsp fragment ensures that certain
javascript variables are always populated and available to be used in the Wizard
‘OK’ action callback function.
……

<script type="text/javascript" >

window.pickerCallback =
"<%=request.getParameter("pickerCallback")%>";

window.pickedAttributes =
"<%=request.getParameter("pickedAttributes")%>";

window.pickedDataFetcher =
"<%=request.getParameter("pickedDataFetcher")%>";

</script>

…..

Note: The user of the picker can as well specify his own set of callback function or
data fetcher using the pickerParam tag
<p:pickerParam name=” pickerCallback” value=”myPickerCallback” />
<p:pickerParam name=” pickedDataFetcher” value=”
jsp/components/myPickedDataFetcher.jsp” />

17-12 Windchill Customizer’s Guide


Possible
Parameter Default values values Req? Description

pickerCallback jcaPickerCallBac Name of no The javascript callback function to


k the be invoked by the picker page
javascript after the user has picked object(s)
function. and activated ‘ok’ action. This
callback is defined in the client
page and would accept a single
argument only. If the client
chooses for default acquisition for
the data of the picked objects, then
this argument would be an object
with a property named
‘pickedObject’ of type Array,
each object of the Array being an
object containing the properties of
interest of the picked object. The
array would have as many objects
as the objects that the user has
picked.

pickedDataFetcher jsp/components/d URI no The URI of the ‘jsp’ page that


efaultPickedData would be delegated with a task of
Fetcher.jsp extracting the data for the picked
objects and return the information
in the form of a literal string using
which the javascript object as
understood by the callback
function could be created.

Following snippet ensures that all AJAX related javascript artifacts are available
for re-use.
<script type="text/javascript"
src="netmarkets/javascript/util/prototype.js"></script>

<script type="text/javascript"
src="netmarkets/javascript/components/wizard.js"></script>

codebase\netmarkets\components\picker.jspf

Examples of Usage in Windchill Code


All the search based pickers e.g. Item Picker, User Picker, Org Picker are all
implemented using this core capability. These picker implementations are made
available in the form of tag. These tag definitions internally use the core capability
devised for the property picker.

Incorporating Pickers in JSP Clients 17-13


Common Picker Configuration Options

Objective
To configure a picker to accept seeded criteria for containers, customize it to user
specified criteria options and results.

Background
Configure a picker to only display a specific soft-type of parts (Product Areas).
Allow user to enter criteria that includes name (not number) and library. Include
criteria (that the user cannot see/edit) to retrieve libraries that are NOT in an state
of “obsolete” AND that include certain specific words in the library description.
The picker should show the product area name, not show its number, and also
include the library that contains the part.

Scope/Applicability/Assumptions
Let’s assume we need to launch a customized part picker from a JSP client which
would have the capability to define the soft type as a seed for searching and also
would respect seeded container’s to search in. We would be using our OOTB item
picker tag to launch it from a JSP page.

Intended Outcome
We should be able to launch an Item Picker which would be configured to search
in for a soft type of part. This would have a name field as criteria for the picker
where the user can filter results based on name of the part. The results table would
contain customized view for this picker where the container and the name of the
part would be shown. It would also respect seeded criteria which would filter the
query based on criteria such that the part belongs to library which has certain
words in the description and are not obsolete.

Solution
A custom JSP page would be written to launch this picker with appropriate seeded
criteria. We would be using the Item Picker tag to launch the picker.

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

17-14 Windchill Customizer’s Guide


Solution Elements
Element Type Description

PickerAttributes.xml XML Runtime location - \codebase\pickerAttributes.xml


Clear case location - \Windchill\DevModules\Search\
src_web\pickerAttributes.xml
This file is used to customize the search criteria at picker page.

SearchResultsTable.pro Xconf Runtime location - \codebase\com\ptc\netmarkets\search\


perties.xconf SearchResultsTable.properties.xconf
This file can be used to configure table view definition.

Procedure – Customizing picker to have user defined criteria and result view

Customizing the picker search criteria


The search criteria for a picker can be customized by defining the attributes in
PickerAttributes.xml file. This can be done by creating a new component id and
then defining the search criteria as 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>

Here we have defined a new component id as


“customizedItemPickerForSoftPart”. We have defined a single attribute to be
searchable i.e. the name of the soft type.

Launching the picker with custom component id and user defined object type
The picker can be launched by passing the above component id to customize the
search criteria as defined above.
<wctags:itemPicker id="customized_item_picker" objectType="WCTYPE|
wt.part.WTPart|org.r_and_d.mypart" componentId="
customizedItemPickerForSoftPart "/>

Seeding the picker with container criteria


We need to find objects within container based on some filter onto these
containers’s itself. Container’s may be passed to the picker tag and objects would
be queried within those containers only. The picker tag accepts a parameter
named containerRef which can be a comma separated list of containers within

Incorporating Pickers in JSP Clients 17-15


which we want to search. The container references can be passed as below. The
comma separate list of the container’s can be fetched by querying for container’s
in which the user wants to search.
<wctags:itemPicker id="genericPicker" objectType="WCTYPE|
wt.part.WTPart|org.r_and_d.mypart" label="Part Picker using
generic" containerRef="<container ref here>" componentId="
customizedItemPickerForSoftPart " showVersion="false"/>

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. Please refer [Crating
Table View] for details regarding creating and configuring a new view. Then we
can pass the view as below to the picker tab and search results table would be
rendered with this view.
<wctags:itemPicker id="genericPicker" objectType="WCTYPE|
wt.part.WTPart|org.r_and_d.mypart" label="Part Picker using
generic" containerRef="<%=containerRefs.toString()%>"
componentId="scenarioOnePicker"
searchResultsViewId="wt.part.WTPart.customizedSearchView"
showVersion="false"/>

The view id “wt.part.WTPart.customizedSearchView” should be configured to


lookup the java class associated with this id which would define the table view.
Please refer to configuring table views document.
An example to configure this in SearchResultTable.properties.xconf file could be
<Service context="default"
name="com.ptc.core.htmlcomp.tableview.ConfigurableTable">

<Option
serviceClass="com.ptc.netmarkets.search.views.CustomizedPartVie
w" requestor="java.lang.Object" selector="
wt.part.WTPart.customizedSearchView "/>

</Service>

A new java class com.ptc.netmarkets.search.views.CustomizedPartView should


be created which would define the view columns for this picker customization.

Sample Code
Launching the picker in <pickerlauncher>.jsp
<html>
<body>
<table>
<tr>
This is a customization where a hidden seed for container
refs is feeded to the picker.
</tr>
<tr>
<%-- launching Item Masterpicker--%>

17-16 Windchill Customizer’s Guide


<wctags:itemPicker id="customPartPicker"
objectType="WCTYPE|wt.part.WTPart|org.r_and_d.mypart"
label="Custom Part Picker"
containerRef="<%=containerRefs.toString()%>"
componentId="scenarioOnePicker"
searchResultsViewId="wt.part.WTPart.customizedSearchView"
showVersion="false"/>
</tr>
</table>
</body>
</html>

The containerRefs passed above can be a list of comma separate container’s from
which we want to fetch the results. This parameter is optional and if not provided
would launch picker to search in all containers.

Incorporating Pickers in JSP Clients 17-17


Configuring a Context Picker

Objective
You want to pick context(s) to be used in your application.

Background
The context picker is used when you have a requirement to perform an operation
that is based on certain context.

Scope/Applicability/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 context picker. After clicking Find… button, context picker will
be launched.

17-18 Windchill Customizer’s Guide


On clicking Find… button you should Context Picker for Project as:

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 RBINFO file customizations.
• Windchill xconfmanager concepts.

Incorporating Pickers in JSP Clients 17-19


Solution Elements

Element Type 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\
pickerAttributes.xml

searchClientResource.rbInfo RBINFO file You should use this file to localize the
contents of the pickers.
Runtime location: <WT_HOME>\src\com\
ptc\windchill\enterprise\search\client\
searchClientResource.rbInfo

contextPicker.tag Custom JSP tag file This file is contains the information about
the supported parameters for this tag.
Runtime location: <WT_HOME>\codebase\
WEB-INF\tags\itemPicker.tag

SearchableTypes.properties. xconf Properties file You should specify component Id and


xconf corresponding object types in this file and
then run xconfmanager.
Runtime location:
<WT_HOME>\codebase\com\ptc\
windchill\enterprise\search\server\
SearchableTypes.properties.xconf

custom.js JavaScript file You should specify custom pickerCallback


function for picker in this file.
Runtime location: <WT_HOME>\codebase\
netmarkets\jsp\search\custom.js

Note: You want to disable the type picker in the Context Picker.

Procedure – Including a Context Picker in a jsp page


Configure basic context picker:
<tr>
<wctags:contextPicker id="contextPickerId" />
</tr>

17-20 Windchill Customizer’s Guide


Customization Points
Parameter Default Value Possible Values Req? Description

id Anything that’s Yes An ID is associated with every picker


unique in a page 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 pickerSearch Any valid No componentId determines the


component id attributes that should appear in
specified in search criteria panel of the given
pickerAttributes.x picker.
ml

pickerCallback Generated at the Name of the No Name of the customized callback


runtime if user callback function function that a user would have to
has not specified implement. It’s recommended that
this parameter you should specify pickerCallback
function in custom.js file

defaultValue “” (blank) Any values No Default value for textbox rendered by


the picker.

defaultHiddenV “” (blank) Any values No Default value of the hidden textbox


alue associated with the picker.

pickedDataFetc <WebApp>/net URL location of No URL of the data fetcher file that will
her markets/jsp/sear the fetcher file be used by the AJAX call to process
ch/pickedData.js the selected results.
p.

label Context Picker Any value No Label of the picker.

displayAttribute name Any attribute No Name of the attribute that should be


the displayed in the picker textbox
after selecting result from the context
picker

containerRef “” (blank) Any container No Value of the containerRef in which a


user wants to restrict the search.

baseWhereClaus “” (blank) Any valid I*E No Additional where clause if you want
e where clause query to filter search results on some
specific criteria regardless of user
input. This where clause will just get
“ANDed” with the internal where
clause.

pickerTitle Contexts Any value No The title of picker.

Incorporating Pickers in JSP Clients 17-21


Parameter Default Value Possible Values Req? Description

editable true true/false No This attribute defines whether you


want to have “Find…”button along
with the textbox or not.

readOnlyPicker false true/false No This attribute defines whether the


TextBox picker text box should be editable or
not.

typeComponentI Foundation.cont Any valid No This parameter is passed to define set


d extPicker componentId of types that can be shown in Type
specified in Picker
SearchableTypes.p
roperties file

inline false true/false No You should specify this parameter


with value as true when you want to
launch picker from a table level
action or inline.

pickedAttributes name Any comma No This parameter contains a comma-


separated list of separated list of the attributes that a
valid attributes user wants a picker to fetch. This is
applicable only if inline is “true”.

showTypePicker true true/false No This parameter should be used to


enable type picker in the picker.

pickerType search 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
“picker” picker you will directly see
the results table without any search
criteria.

pickerTextBoxL 25 Any numeric value No This parameter defines the length of


ength the picker text box.

searchResultsVi “”(blank) Any valid view id No This parameter allows user to define
ewId custom view id for the picker search
results table.

customAccessC “” (blank) Any valid name No This parameter is used to define your
ontroller own custom access controller. This
parameter would accept the complete
class name as the value. To specify
multiple customAccessController
you can pass on comma (,) separated
list of the class names.

17-22 Windchill Customizer’s Guide


Parameter Default Value Possible Values Req? Description

excludeSubType “” (blank) Any valid subtypes No This parameter is used to exclude sub
s types from the search.

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*’)" />

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

Incorporating Pickers in JSP Clients 17-23


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/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 Find… button, item picker will be
launched.

17-24 Windchill Customizer’s Guide


On clicking Find… button you should 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 RBINFO file customizations.
• Windchill xconfmanager concepts.

Incorporating Pickers in JSP Clients 17-25


Solution Elements

Element Type 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\
pickerAttributes.xml

searchClientResource.rb RBINFO file You should use this file to localize the contents of the
Info pickers.
Runtime location: <WT_HOME>\src\com\ptc\
windchill\enterprise\search\client\
searchClientResource.rbInfo

itemPicker.tag Custom JSP tag file This file is contains the information about the
supported parameters for this tag.
Runtime location: <WT_HOME>\codebase\WEB-
INF\tags\itemPicker.tag

SearchableTypes.proper xconf Properties file You should specify component Id and corresponding
ties.xconf object types in this file and then run xconfmanager.
Runtime location:
<WT_HOME>\codebase\com\ptc\windchill\
enterprise\search\server\
SearchableTypes.properties.xconf

custom.js JavaScript file You should specify custom pickerCallback function


for picker in this file.
Runtime location: <WT_HOME>\codebase\
netmarkets\jsp\search\custom.js

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>

17-26 Windchill Customizer’s Guide


Customization Points

Possible
Parameter Default Value Values Req? Description

id Anything that’s Yes An ID is associated with every picker in


unique in a page 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 pickerSearch Any valid No componentId determines the attributes


component id that should appear in search criteria
specified in panel of the given picker.
pickerAttributes.x
ml

pickerCallba Generated at the Name of the No Name of the customized callback


ck runtime if user callback function function that a user would have to
has not specified implement. It’s recommended that you
this parameter should specify pickerCallback function
in custom.js file

defaultValue “” (blank) Any values No Default value for textbox rendered by


the picker.

defaultHidde “” (blank) Any values No Default value of the hidden textbox


nValue associated with the picker.

pickedDataF <WebApp>/net URL location of No URL of the data fetcher file that will be
etcher markets/jsp/sear the fetcher file used by the AJAX call to process the
ch/pickedData.js selected results.
p.

label Item Picker Any value No Label of the picker.

displayAttrib name Any attribute No Name of the attribute that should be the
ute displayed in the picker textbox after
selecting result from the item picker

containerRef “” (blank) Any container No Value of the containerRef in which a


user wants to restrict the search.

Incorporating Pickers in JSP Clients 17-27


Possible
Parameter Default Value Values Req? Description

baseWhereC “” (blank) Any valid I*E No Additional where clause if you want to
lause where clause filter search results on some specific
query criteria regardless of user input. This
where clause will just get “ANDed” with
the internal where clause. If you want to
specify different baseWhereClause for
say, Part and Document, then you can do
so using following syntax:
wt.part.WTPart$SEP$<where clause
that will get ANDed with internal
whereClause>$OBJ$wt.doc.WTDocum
ent$SEP$<where clause that will get
ANDed with internal whereClause>. If
you don’t specify the object type then
the one supplied will be used for all the
object type.

pickerTitle Item Any value No The title of picker.

editable true true/false No This attribute defines whether you want


to have “Find…”button along with the
textbox or not.

readOnlyPic false true/false No This attribute defines whether the picker


kerTextBox text box should be editable or not.

typeCompon Foundation.chan Any valid No This parameter is passed to define set of


entId geablePicker componentId types that can be shown in Type Picker
specified in
SearchableTypes.
properties file

inline false true/false No You should specify this parameter with


value as true when you want to launch
picker from a table level action or inline.

pickedAttrib name Any comma No This parameter contains a comma-


utes separated list of separated list of the attributes that a user
valid attributes wants a picker to fetch. This is
applicable only if inline is “true”.

showVersion true true/false No This parameter determines whether to


display version/iteration attributes in
search criteria or not.

objectType wt.fc.Persistable Any Windchill No This attribute determines the default


object type object type in the item picker.

showTypePi true true/false No This parameter should be used to enable


cker type picker in the picker.

17-28 Windchill Customizer’s Guide


Possible
Parameter Default Value Values Req? Description

pickerType search 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 “picker” picker you
will directly see the results table without
any search criteria.

pickerTextB 25 Any numeric No This parameter defines the length of the


oxLength value picker text box.

searchResult “”(blank) Any valid view id No This parameter allows user to define
sViewId custom view id for the picker search
results table.

customAcces “” (blank) Any valid name No This parameter is used to define your
sController own custom access controller. This
parameter would accept the complete
class name as the value. To specify
multiple customAccessController you
can pass on comma (,) separated list of
the class names.

excludeSubT “” (blank) Any valid No This parameter is used to exclude sub


ypes subtypes types from the 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*’)" />

Incorporating Pickers in JSP Clients 17-29


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

17-30 Windchill Customizer’s Guide


Configuring an Organization Picker

Objective

You want to pick organization(s) based on certain search criteria.

Background
The organization picker is used when you have a requirement to select specific organiza-
tion(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 orga-
nization and pass it on to the search criteria to perform search for parts.

Scope/Applicability/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 “/net-
markets/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 organization picker. After clicking Find… button, user picker will be launched.

Incorporating Pickers in JSP Clients 17-31


On clicking Find… button you should organization picker as:

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 RBINFO file customizations.
• Windchill xconfmanager concepts.

17-32 Windchill Customizer’s Guide


Solution Elements

Element Type 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\
pickerAttributes.xml

searchClientResource.rbInfo RBINFO file You should use this file to


localize the contents of the
pickers.
Runtime location:
<WT_HOME>\src\com\ptc\
windchill\enterprise\search\
client\
searchClientResource.rbInfo

organizationPicker.tag Custom JSP tag file This file is contains the


information about the
supported parameters for this
tag.
Runtime location:
<WT_HOME>\codebase\
WEB-INF\tags\userPicker.tag

custom.js JavaScript file You should specify custom


pickerCallback function for
picker in this file.
Runtime location:
<WT_HOME>\codebase\
netmarkets\jsp\search\
custom.js

Procedure – Including a Organization Picker in a jsp page


Configure basic organization picker:
<tr>
<wctags:organizationPicker id="organizationPickerId" />
</tr>

Incorporating Pickers in JSP Clients 17-33


Customization Points

Default Possible
Parameter Value Values Req? Description

id Anything that’s Yes An ID is associated with every picker in


unique in a page 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 pickerSear Any valid No componentId determines the attributes


ch component id that should appear in search criteria panel
specified in of the given picker.
pickerAttributes.
xml

pickerCallback Generated Name of the No Name of the customized callback function


at the callback function that a user would have to implement. It’s
runtime if recommended that you should specify
user has pickerCallback function in custom.js file
not
specified
this
parameter

defaultValue “” (blank) Any values No Default value for textbox rendered by the
picker.

defaultHiddenValu “” (blank) Any values No Default value of the hidden textbox


e associated with the picker.

pickedDataFetcher <WebApp URL location of No URL of the data fetcher file that will be
>/netmark the fetcher file used by the AJAX call to process the
ets/jsp/sear selected results.
ch/picked
Data.jsp.

label Organizati Any value No Label of the picker.


on Picker

displayAttribute Name Any attribute No Name of the attribute that should be the
displayed in the picker textbox after
selecting result from the organization
picker

containerRef “” (blank) Any container No Value of the containerRef in which a user


wants to restrict the search.

17-34 Windchill Customizer’s Guide


Default Possible
Parameter Value Values Req? Description

baseWhereClause “” (blank) Any valid I*E No Additional where clause if you want to
where clause filter search results on some specific
query criteria regardless of user input. This
where clause will just get “ANDed” with
the internal where clause.

pickerTitle Organizati Any value No The title of picker.


on

editable true true/false No This attribute defines whether you want to


have “Find…”button along with the
textbox or not.

readOnlyPickerTe false true/false No This attribute defines whether the picker


xtBox text box should be editable or not.

inline false true/false No You should specify this parameter with


value as true when you want to launch
picker from a table level action or inline.

pickedAttributes yesname Any comma No This parameter contains a comma-


separated list of separated list of the attributes that a user
valid attributes wants a picker to fetch. This is applicable
only if inline is “true”.

pickerType search 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 “picker” picker you will directly
see the results table without any search
criteria.

pickerTextBoxLen 25 Any numeric No This parameter defines the length of the


gth value picker text box.

searchResultsView “”(blank) Any valid view id No This parameter allows user to define
Id custom view id for the picker search
results table.

customAccessCont “” (blank) Any valid name No This parameter is used to define your own
roller custom access controller. This parameter
would accept the complete class name as
the value. To specify multiple
customAccessController you can pass on
comma (,) separated list of the class
names.

Incorporating Pickers in JSP Clients 17-35


Configuring Organization Picker with multi select option in results table
<wctags:organizationPicker id="orgPickerId" multiSelect="true" />

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

17-36 Windchill Customizer’s Guide


Configuring a Type Picker
The Type Picker common component is used for the display or assignment of the
item type upon creation, copying (save-as), registration, revision, searching, or
viewing information of type-able items. The component is available in three
formats i.e. as a drop down, as a table and as a tree, either of which can be used
depending on the need of application.It can be used in both single-item and multi-
item user interface designs.
The display or assignment of the type adheres to
• the defined hard-type items
• the soft-type items
• the application context
• and the access control policies of the system
The application developer can control following features of the picker
• Picker Default values population
• Picker Action Definition
• Selected elements population on Target element

How to Use Type Picker


Type Picker can be created by using the custom tag provided for the component.
The parameters that drive the behavior and content of the picker can be passed
either via attributes or by use of necessary sub-tags. It consists of Picker Label,
Picker Action and the Target element.

Drop Down Format


In the drop down format of type picker the picker label and the target element are
displayed. The Go button is optional. If you want the Go button you have to
configure it and define its behavior as per your application needs. You can select
one or more values as per the select parameter value configured for the picker.
Following example creates a type picker component by using the type picker tag.

Incorporating Pickers in JSP Clients 17-37


Example:

<p:typePicker id="document_type_picker" label="Type : "


mode="SEARCH">
<p:pickerParam name="select" value="single" />
<p:pickerParam name="format" value="dropdown" />
<p:pickerParam name="defaultType" value="All Types" />
<p:pickerParam name="type" value="BOTH" />
<p:pickerParam name="displayHierarchy" value="false" />
<p:pickerParam name="showRoot" value="true" />
</p:typePicker>

In the above example a simple drop down type picker is defined with.
Attributes:
• Id - This is required attribute used to distinguish between multiple Type-
Pickers
• Label - Picker Label
• Mode – Defines the mode in which the picker can be used. Default is
SEARCH.
There are other optional attributes for this picker which are listed at the end of this
section.
Parameters:
• Select – It has two possible values single and multi. Default is single.

17-38 Windchill Customizer’s Guide


• defaultType – Specifies the default value to be displayed. It accepts valid
logical or external representation of Windchill Type Identifiers. It supports
multiple values for multi select pickers and a single value for single select
pickers.
• Type – Possible values are
– ROOT_TYPES - only seeded types
– SOFT_TYPES - only soft types
– BOTH - Modeled and soft types (default value)
• displayHierarchy – It displays the picker elements in hierarchy. It is valid only
for drop down format. It is false by default.
• showRoot - Accepts String representation of Boolean value. Shows the
seedTypes as I level elements.</font></font>
There are other optional parameters for this picker which are listed at the end of
this section.

Tree Format
In the tree format implementation the Picker Label, the Target element and find
button are displayed. On the find button click event a popup window pops up with
Windchill Type Identifiers displayed in tree format. If one or more types are
selected and ok button is hit the selected value(s) are populated in to target
element. If any type identifiers are present in the target element and user hits the
find button then the type identifiers in the target element appear as pre-selected
values in the tree, provided that the types are valid logical or external
representation of Windchill Type Identifiers. If cancel button is hit in the popup

Incorporating Pickers in JSP Clients 17-39


window no selection is done from the popup window and the target element
contents remain unchanged.

Example:
<p:typePicker id="document_typePicker" label="Type : ">
<p:pickerParam name="format" value="tree" />
<p:pickerParam name="defaultType" value="wt.doc.WTDocument|
com.ptc.www.Agenda" />
<p:pickerParam name="defaultType" value="wt.doc.WTDocument|
com.ptc.www.Plan" />
<p:pickerParam name="defaultType" value="WCTYPE|
wt.pdmlink.PDMLinkProduct|Sub Product3" />
<p:pickerParam name="seedType" value="wt.doc.WTDocument" />
<p:pickerParam name="type" value="BOTH" />
<p:pickerParam name="showRoot" value="true" />
<p:pickerParam name="appOption" value="Mera Type$WCTYPE|
wt.pdmlink.PDMLinkProduct|Sub Product3" />
</p:typePicker>

17-40 Windchill Customizer’s Guide


Table Format
In the table format of type picker the type identifiers are displayed in tabular
format. The working of the Picker Label, the Target element and find button is
same as in the case of Tree format except that, on the find button click event a
popup window pops up with Windchill Type Identifiers displayed in tabular
format. User can select one or more values and hit OK / Cancel button.
Example:-
<p:typePicker id=" document_typePicker" label="Type : " >
<p:pickerParam name="defaultType" value="wt.doc.WTDocument" />
<p:pickerParam name="seedType" value="wt.doc.WTDocument" />
<p:pickerParam name="format" value="table" />
<p:pickerParam name="type" value="BOTH" />
<p:pickerParam name="showRoot" value="true" />
</p:typePicker>

Overview

The TypePicker is defined with the help of TypePicker Tag. The attribute and
parameter values supplied are used to populate an object of type TypeBean. This
bean is used to carry the user-supplied information across. The different phases
involved in a TypePicker component are as follows.

Incorporating Pickers in JSP Clients 17-41


Processing the TypePicker Tag
• Draw the Label if supplied
• Create the Target Element if not provided
• Populate the Target Element and Draws it
• If the format is table/tree:
– Creates the “Picker Action” and draws
– If “pickerCallBack” is not provided, puts the default function.

Picker Action button hit


• Pops up the TypePicker.jsp that contains Wizard having Ok/Cancel buttons
• Wizard’s first step is typePicker_step.jsp
• Depending on whether it’s a tree or table, it includes either
typePicker_tree.jspf or typePicker_table.jspf
• The jspf has got appropriate component defined in it to draw the picker as
configured.

Ok Wizard action
• If no element is selected, a JavaScript warning is displayed and the pop-up
stays.</font></font>
• If some element is selected then it makes an Ajax call to the jsp specified via
the “pickerDataFetcher”. The jsp will fetch all the selected elements that need
to be populated in the target element.
• Calls “pickerCallBack” available in the calling jsp
• Update Target Element
• Close the pop-up

Cancel Wizard action


• Close the pop-up

17-42 Windchill Customizer’s Guide


Customization Points
You can customize following areas of type picker.
• Target element Definition
• Picker Default values population
• Picker Action Definition
• Selected elements population on Target element
• Picker Element Content population

Target Element Definition


You can provide the target element using the “field” attribute. The values that the
target element can have are text field, drop down and list box. If you do not
specify the target element it will be created by the component. You can also
provide the rendering context using the ”renderContext” attribute.

Picker Default values population


You can define the values that can be populated as pre-selected values at the time
of configuring the TypePicker. Multiple values can be passed to the parameter
‘pickerDefaultTypes’. The type specified should be valid logical or external
representation of Windchill Type Identifiers. For single select only one type
should be provided. For multiple select multiple values can be provided.

Picker Action Definition


The picker action can be specified by using the Go / Find button. If the picker type
is dropdown list then the Go/Find button is optional and user has to define the
behavior if he wants. In case of table / tree format the picker action can be
specified using the object Type”& “actionName”parameters. The picker action is
specified in the object type in actions.xml. The action name is the name of the
action in actions.xml.
The Picker actions are not available for mode=”VIEW / EDIT”.

Selected elements population on Target element


Depending on the choice of select value (single/multiple) and the picker format
the target element is decided.

Select Format Drop Down List Tree Table

Single No Target element Text Box Text Box

Multi Not supported List Box List Box

Incorporating Pickers in JSP Clients 17-43


You can provide your own pickerCallBack function with following conditions
• The function signature should be “user_call_back_function(JSON_Object,
TypePicker_Id, TargetElement_Id)”.
• The function should be available where type picker component is inserted.
You can provide your own pickerDataFetcher function with following conditions
• It is to be a jsp file located in the <Windchill>/codebase and relative path is to
be provided.
• It is not applicable for drop down.

Picker Element Content population


You can specify one or more seed Types to the type picker using the parameter
“pickerSeedTypes”. If seed types are not provided it will throw an Exception. For
mode=”SEARCH” exception is not thrown. For search mode the root types are
defined in WT_HOME\codebase\com\ptc\windchill\enterprise\search\server\
SearchableTypes.properties file. So if no seed types are specified, the types will
be populated from SearchableTypes.properties file.

Attributes and Parameters supported by Type Picker


The Following table describes all the supported attributes of a Type Picker
Common Component

Attribute Example Description

id id="tp" A required value. Used to distinguish between


the multiple Type-Picker usages in a page

label label ="Type :" Picker Label

mode mode=”SEARCH” Defines in which mode the Type-Picker is going


to be used. It should be one of the value defined
in com.ptc.core.ui.resources.ComponentMode.
Default value is SEARCH

field field ="${target_element}" Target Element into which the picked element
attribute will be populated. It should be a
subclass of
com.ptc.core.components.rendering.AbstractG
uiComponent. Currently support TextBox and
ComboBox. If not supplied the component will
create a Target Element for the user

17-44 Windchill Customizer’s Guide


Attribute Example Description

renderContext renderContext ="${rcontext}" Object should be an instance of


com.ptc.core.components.rendering.Rendering
Context. If not supplied the component will
create one for the user

objectType objectType =" typepicker" This is the objecttype in which the picker action
is specified in *actions.xml (<Windchill>\
codebase\config\actions\EnterpriseUI-
actions.xml)

actionName actionName =" typePicker" This is the action name that is specified in
*actions.xml for the picker action

The Following table describes all the supported parameters of a Type Picker
Common Component.

Parameter Example Description

adminDomainRef value ="${adref}"value =" String representation of the administrative


wt.admin.AdministrativeDomain domain reference
:7" (wt.admin.AdminDomainRef). Used to
check access control rights.

containerRef value ="${container_Ref}" String representation of the container


reference
(wt.inf.container.WTContainerRef). Used
to populate types specified for this
container

lifeCycleState value ="RELEASED" String representation of State.


(wt.lifecycle.State). Used while checking
access control rights

seedType value =” wt.part.WTPart” Accepts valid logical or external


representation of Windchill Type
Identifiers Multiple values supported.
Required for mode =
CREATE/EDIT/VIEW

filterType value ="coolPart" 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

Incorporating Pickers in JSP Clients 17-45


Parameter Example Description

defaultType value =” wt.part.WTPart” For single select, it should be only one


value. Accepts valid logical or external
representation of Windchill Type
Identifiers. Multiple values supported. It
can support blank, "Select a Type" etc
values also

appOption value ="All Localized Display name and value


Types$wt.fc.Persistable" separated by a “$” delimiter. Multiple
values supported.

format value ="dropdown" It should be one of the enum constant value


defined in
com.ptc.windchill.enterprise.picker.type.s
erver.TypePickerFormat. Possible values
are dropdown, table, tree. Default value is
dropdown

select value ="single" Possible values are single and multi, the
former being the default.

type value ="BOTH" It should be one of the enum constant value


defined in
com.ptc.windchill.enterprise.picker.type.s
erver.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) · Default value is BOTH

displayHierarchy value=”true” Accepts String representation of Boolean


value. Valid only for dropdown format.
Presents picker elements in hierarchy.
Default value is false

showInstantiable value=”false” Accepts String representation of Boolean


value. If true - only instantiables will be
displayed. If false both instantiables and
non-instantiables will be displayed.
Default value is false

showRoot value=”true” Accepts String representation of Boolean


value. Shows the seedTypes as I level
elements

17-46 Windchill Customizer’s Guide


Parameter Example Description

componentId value=”” ComponentId is defined as 'APP_ID+.


+COMPONENT_NAME' . Valid
APP_IDs are ProjectLink, Foundation, or
PDMLink. Used for mode = "SEARCH" to
find the I level types from <Windchill>\
codebase\com\ptc\windchill\enterprise\
search\server\SearchableTypes.properties.
Passing null will default to
Foundation.allSearch (Default)

Source code location

Tag Definition
• \ClientArchitecture\CommonComponents\src_web\WEB-INF\tlds\picker.tld
• \wcEnterprise\EnterpriseUI\src_web\com\ptc\windchill\enterprise\tags\
picker\TypePickerTag.java

Picker Action, Wizard Step Definition


• \wcEnterprise\EnterpriseUI\src_web\config\actions\EnterpriseUI-actions.xml

Type Picker Service Entry


• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\enterpriseui-
service.properties.xconf

Java & Model Files


• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
type.cat
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
type.mData
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
typePickerResource.rbInfo
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
commands\commands.mData
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
commands\type.commands.cat
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
commands\TypePickerCommands.java

Incorporating Pickers in JSP Clients 17-47


• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
dataUtilities\type.dataUtilities.cat
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
dataUtilities\TypePickerNmObjectUtility.java
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
dataUtilities\TypePickerTreeHandler.java
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\server.mData
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\type.server.cat
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\StandardTypePickerService.java
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\TypePickerBean.java
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\TypePickerData.java
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\TypePickerFormat.java
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\TypePickerHelper.java
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\TypePickerServiceFwd.java
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\TypePickerService.java
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\TypePickerTreeModel.java
• \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\
server\TypePickerTypes.java

JSP files
• \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\
typePicker.jsp
• \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\
typePicker_dataFetcher.jsp
• \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\
typePicker_doer.jspf
• \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\
typePicker_includes.jspf

17-48 Windchill Customizer’s Guide


• \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\
typePicker_table.jspf
• \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\
typePicker_tree.jspf
• \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\
typePicker_step.jsp

Incorporating Pickers in JSP Clients 17-49


Configuring a User Picker

Objective
You want to pick User(s) based on certain search criteria.

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 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/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 user picker. After clicking Find… button, user picker will be
launched.

17-50 Windchill Customizer’s Guide


On clicking Find… button you should use a user picker as:

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 RBINFO file customizations.
• Windchill xconfmanager concepts.

Incorporating Pickers in JSP Clients 17-51


Solution Elements

Element Type 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\
pickerAttributes.xml

searchClientResource.rbInfo RBINFO file You should use this file to


localize the contents of the
pickers.
Runtime location:
<WT_HOME>\src\com\ptc\
windchill\enterprise\search\
client\
searchClientResource.rbInfo

userPicker.tag Custom JSP tag file This file is contains the


information about the
supported parameters for this
tag.
Runtime location:
<WT_HOME>\codebase\WEB-
INF\tags\userPicker.tag

custom.js JavaScript file You should specify custom


pickerCallback function for
picker in this file.
Runtime location:
<WT_HOME>\codebase\
netmarkets\jsp\search\
custom.js

Procedure – Including a User Picker in a jsp page


Configure basic user picker:
<tr>
<wctags:userPicker id="userPickerId" />
</tr>

17-52 Windchill Customizer’s Guide


Customization Points

Possible
Parameter Default Value values Req? Description

id Anything Yes An ID is associated with


that’s unique every picker in the calling
in a page 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 pickerSearch Any valid No componentId determines the


component id attributes that should appear
specified in in search criteria panel of the
pickerAttribut given picker.
es.xml

pickerCallback Generated at the Name of the No Name of the customized


runtime if user has callback callback function that a user
not specified this function would have to implement.
param It’s recommended that you
should specify
pickerCallback function in
custom.js file

defaultValue “” (blank) Any values No Default value for textbox


rendered by the picker.

defaultHiddenValue “” (blank) Any values No Default value of the hidden


textbox associated with the
picker.

pickedDataFetcher <WebApp>/netmar URL location No URL of the data fetcher file


kets/jsp/search/pick of the fetcher that will be used by the
edData.jsp. file AJAX call to process the
selected results.

label User Picker Any value No Label of the picker.

displayAttribute fullName Any attribute No Name of the attribute that


should be the displayed in the
picker textbox after selecting
result from the user picker

containerRef “” (blank) Any container No Value of the containerRef in


which a user wants to restrict
the search.

Incorporating Pickers in JSP Clients 17-53


Possible
Parameter Default Value values Req? Description

baseWhereClause “” (blank) Any valid I*E No Additional where clause if


where clause you want to filter search
query results on some specific
criteria regardless of user
input. This where clause will
just get “ANDed” with the
internal where clause.

pickerTitle User Any value No The title of picker.

editable true true/false No This attribute defines


whether you want to have
“Find…”button along with
the textbox or not.

readOnlyPickerTextB false true/false No This attribute defines


ox whether the picker text box
should be editable or not.

inline false true/false No You should specify this


parameter with value as true
when you want to launch
picker from a table level
action or inline.

pickedAttributes fullName Any comma No This parameter contains a


separated list comma-separated list of the
of valid attributes that a user wants a
attributes picker to fetch. This is
applicable only if inline is
“true”.

pickerType search 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
“picker” picker you will
directly see the results table
without any search criteria.

pickerTextBoxLength 25 Any numeric No This parameter defines the


value length of the picker text box.

searchResultsViewId “”(blank) Any valid No This parameter allows user to


view id define custom view id for the
picker search results table.

17-54 Windchill Customizer’s Guide


Possible
Parameter Default Value values Req? Description

customAccessControll “” (blank) Any valid No This parameter is used to


er name define your own custom
access controller. This
parameter would accept the
complete class name as the
value. To specify multiple
customAccessController you
can pass on comma (,)
separated list of the class
names.

showUserType ActiveOnly ActiveOnly No This parameter is used to


restrict the user search to
DeletedOnly
active/deleted/active and
ActiveAndDel deleted users only.
ete

showRoles false true/false No 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.

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

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 “fullName” is the displayAttribute requested

Incorporating Pickers in JSP Clients 17-55


var displayAttr = eval("myJSONObjects[i].fullName");
updateHiddenField.value=oid;
updateDisplayField.value=displayAttr;
}
}

17-56 Windchill Customizer’s Guide


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

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.

Incorporating Pickers in JSP Clients 17-57


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

actionClass Tag Attribute Name of the action class that


needs to be invoked for
processing the selected
Participants.

actionMethod Tag Attribute Name of the action method that


needs to be invoked for
processing the selected
Participants.

select Tag Attribute This can take values "single" /


"multi". When this is set to
"single", one can select only
one Participant at a time.
Default is "multi". If this
attribute is not passed or set to
"multi", Picker will enable to
select multiple Participants.

participantType Tag Attribute Use this to set the default to any


Participant type. The class
com.ptc.core.components.bean
s.
PrincipalBean has four string
constants defined, which one
can be pass to this attribute. The
constants are
ALL_PARTICIPANT, USER,
GROUP and ORG.

17-58 Windchill Customizer’s Guide


Element Type Description

singleParticipantType Tag Attribute 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 in the attribute
participantType. When set to
false or left unspecified, the
picker supports participant
types ALL_PARTICIPANT,
USER, GROUP, ORG.

associationMap Tag Attribute 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.

defaultAssociation Tag Attribute The association you desire to be


pre selected in the dropdown
should be passed in this
attribute.

associationLabel Tag Attribute The localized string for Display


Label of the association.

emailAllowed Tag Attribute Set this to "true" to get email


Textbox rendered. You can
type any comma or space
separated emails that you desire
to invite.

Incorporating Pickers in JSP Clients 17-59


Element Type Description

contextMap Tag Attribute 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.

defaultContext Tag Attribute The context you desire to be pre


selected in the dropdown
should be passed in this
attribute.

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

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 the Sample Code section 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.

17-60 Windchill Customizer’s Guide


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

Customization Points

Possible
Parameter Default Value Values Req? Description

select “multi” "single" / "multi" No There is a need to have the picker


return only a single Principal, thus,
the Apply button does not appear.

emailAllowed “false” “true”/ “false” No Not all clients will allow an email
string to be returned from the
picker, some clients will only allow
Principal objects to be returned.

Incorporating Pickers in JSP Clients 17-61


Possible
Parameter Default Value Values Req? Description

associationMap Empty See Solution No Some clients want users to be able


defaultAssociation Elements on to assign Principals to create an
page 17-58 assignment when selecting
Empty No principals (such as role assignment,
associationLabel task assignment, etc.) If an
assignment is desired along with
the principal choice, there is a need
Empty No to show this list. The client must be
able to specify the label name,
dropdown list choices, and default
value for the dropdown.

singleParticipantT Empty “true”/ “false” No Not all clients that will use the
ype picker will need the same set of
Principal types. Some clients may
only except certain types to be
returned from the picker

contextMap Empty See Solution No In Administrative clients it’s


Elements on necessary to be able to select a
page 17-58 specific context and have the
defaultContext Empty No Principals returned from that
context, and from it’s parent
contexts (i.e. the organization and
site that contain the specified
container)
If there is only a single “Search In”
context, the value should be
displayed as read-only text (no
dropdown).

serviceMap Empty See Solution No A specific parameter will have to


Elements on be set by the application using the
page 17-58 picker to specify that this attribute
should be shown. This attribute is
used to pick a specific LDAP to
find Principals in. This attribute is
primarily used by/in
Administrative user interfaces
where the end user knows which
LDAP server they are interested in
searching against. Label should be
“Service:” when this is displayed.

17-62 Windchill Customizer’s 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 ).
<%@ 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.NmPrincipalCommands2"
actionMethod="addPrincipal"
participantType="<%= PrincipalBean.GROUP %>"
</jca:participantPicker>

This will render a basic participant picker as show below.

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.

Incorporating Pickers in JSP Clients 17-63


public class NmPrincipalCommands2 implements Externalizable {
public static ArrayList addPrincipal( NmCommandBean cb )
throws WTException {
ArrayList list = new ArrayList();
String users =
cb.getTextParameter(PrincipalBean.PARAM_SELECTED_PRINCIPALS);
if (users != null) {
int start = 0;
int pos = users.indexOf("#", start);
while (pos != -1) {
String user = users.substring(start, pos);
list.add(user);
start = pos+1;
pos = users.indexOf("#", start);
}
}
}
}

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

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. Key’s 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.NmPrincipalCommands2"

17-64 Windchill Customizer’s Guide


actionMethod="addPrincipal"
participantType="${participantType}"
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 NmPrincipalCommands2 implements Externalizable {
public static ArrayList addPrincipal( NmCommandBean cb )
throws WTException {
ArrayList list = new ArrayList();
String users =
cb.getTextParameter(PrincipalBean.PARAM_SELECTED_PRINCIPALS);
if (users != null) {
int start = 0;
int pos = users.indexOf("#", start);
while (pos != -1) {
String user = users.substring(start, pos);
list.add(user);
start = pos+1;
pos = users.indexOf("#", start);
}
String role =
cb.getTextParameter(PrincipalBean.PARAM_ASSOCIATION);
ArrayList result = NmRoleHelper.service.addUsersToRole(cb,
role, list);
}
return result;
}
}

You can extract the selected association from text parameter as highlighted in the
above code.

Adding Email subscription


The tag to get email subscription the code will look like this.
<jca:participantPicker
actionClass="com.ptc.netmarkets.principal.NmPrincipalCommands2"

Incorporating Pickers in JSP Clients 17-65


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.

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>

17-66 Windchill Customizer’s Guide


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


• \Windchill\codebase\netmarkets\jsp\roleAccess\ profile_addMembers.jsp
• \Windchill\codebase\netmarkets\jsp\subscription\ subscrPrincipalPicker.jsp
• \Windchill\codebase\netmarkets\jsp\team\ addUsersToRole.jsp
• \Windchill\codebase\netmarkets\jsp\object\ findParticipant.jsp

Incorporating Pickers in JSP Clients 17-67


17-68 Windchill Customizer’s Guide
18
JSP Customization Scenarios

This chapter details various customization scenarios.

Topic Page
Configuring a Picker to Offer Only Specific Soft Types Based on User-specified
Criteria including Restricted Life Cycle States.................................................18-2
Building a Picker that Enables Users to Select Projects from an External Project
DB .....................................................................................................................18-8
Pickers from table toolbar ...............................................................................18-13
Generating HTML Tags for ProductView Visualization Within a JSP Page .18-16

18-1
Configuring a Picker to Offer Only Specific Soft Types
Based on User-specified Criteria including Restricted Life
Cycle States

Objective
Configure a picker to only display a specific soft-type of parts (Datecode
Release). Allow user to enter criteria which includes name, library and lifecycle
state. The states shown to the user must only be ones that represent a state that the
objects can have, not all LC states in the system. The user to be able to pick a
value for the attribute "Release Stream" (Windchill 8.0, 9.0, etc). The picker
should show the datecode name, not show its number, and also include the library
that contains the part. The picker will be used in the process to create Affected
Data relationships for a Change Request.
Associated requirements:
• Invoking a picker with customized seeded criteria.
• Customizing the columns of a table

Background
Problem scenario represents common customization scenario for Item Picker.
Picker is common UI component used for searching for referenced objects and
selecting one or more of them on calling application. You can customize criteria
attributes and result table columns shown in picker. You can configure Item
Picker to search for single or multiple object types. You can restrict search to only
in particular container or container types.

Scope/Applicability/Assumptions
• Item Picker can be launched from any JSP page using ItemPicker tag.
• Picker returns picked objects as a Jason object by calling JavaScript function
on calling page.
• It is the responsibility of calling page to further act on this Jason object.
• Soft type of Part is Date code so it’s fully qualified external form would be
like WCTYPE|wt.part.WTPart|org.r_and_d.DatecodeRelese

Intended Outcome
Datecode Release picker with Name, context and State as criteria attributes:

18-2 Windchill Customizer’s Guide


Solution
A custom JSP tag with appropriate parameters would be used to launch
customized Item Picker. To choose the Library, Library Picker would be used.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Using JSP tags
• Using xconfManager
• Updating XML document.
• Using rbInfo files

Solution Elements

Element Type Description

PickerAttributes.xml Xml Location: <Windchill>\ codebase

SearchableTypes.propertis Xconf properties Location: <Windchill>\ codebase\


.xconf file com\ptc\windchill\ enterprise\
search\server\
SearchableTypes.properties.xc onf

JSP Customization Scenarios 18-3


Element Type Description

JavaScript file Add your callback function in this


file.

itemPicker.tag JSP tag Location: <Windchill>\ codebase\


WEB-INF\tags\ itemPicker.tag

To choose Library, Library Picker is shown.

Procedure – Launch Item Picker with custom criteria and result table to pick DateCodeRelease
objects

Using Item Picker Tag


To show Item Picker you can use ItemPicker tag as shown below:
<%@ taglib prefix="wctags" tagdir="/WEB-INF/tags" %>

<tr>

<%-- launching Item picker--%>

<wctags:itemPicker id="myItemPicker" label="Custom Item


Picker" pickerTitle="Datecode Release" showVersion="false"
objectType=" WCTYPE|wt.part.WTPart|org.r_and_d.myPart "
showTypePicker="false" componentId="test.Customization"
typeComponentId="Foundation.customization"
searchResultsViewId="wt.part.WTPart.customizedSearchView"/>

</tr>

….

The important parameter are described below:


• ObjectType – Fully qualified external form name of the object.
• ComponentId – componentId to be used for configuring criteria attributes.
See section below for details
• TypeComponentId - used for defining set of types and container types to be
searched for. In our case this parameter is used to constraint our search only
within Library containers.

Defining ComponentId for configuring criteria attributes


This section describes, adding new componentId.
<wctags:itemPicker id="myItemPicker" label="Custom Item Picker"
pickerTitle=" Datecode Release" showVersion="false"
objectType="WCTYPE|wt.part.WTPart|org.r_and_d.myPart "
showTypePicker="false" componentId="test.Customization"
typeComponentId="Foundation.customization"
searchResultsViewId="wt.part.WTPart.customizedSearchView"/>

18-4 Windchill Customizer’s Guide


ComponentId is resolved from pickerAttributes.xml file to pick up the list of
attributes to be shown in picker criteria. Update pickerAttributes.xml as below:
<PickerAttributes>

<ComponentID id="test.Customization">

<ObjectType id="WCTYPE|wt.part.WTPart|
org.r_and_d.myPart">

<SearchCriteriaAttributes>

<Attributes>

<Name>name</Name>

<DisplayName>NAME_LABEL</DisplayName>

<IsSearchable>true</IsSearchable>

</Attributes>

<Attributes>

<Name>containerRef</Name>
<DisplayName>CONTEXT_LABEL</DisplayName>
<IsSearchable>false</IsSearchable>

</Attributes>

<Attributes>

<Name>state.state</Name>

<DisplayName>STATE_LABEL</DisplayName>

<IsSearchable>true</IsSearchable>

</Attributes>

</SearchCriteriaAttributes>

</ObjectType>

</ComponentID>

</PickerAttributes>

Here we have defined search criteria attributes as name, context and state.
DisplayName is resolved from rbInfo file : com\ptc\windchill\enterprise\search\
client\searchClientResource.rbInfo

Defining typeComponentId for constraining search to given container types


As per problem statement, we need to search only with in Library containers. This
is achieved by passing typeComponentId. To configure typeComponentId add
below property to <Windchill>\codebase\com\ptc\windchill\enterprise\search\
server\SearchableTypes.properties.xconf

JSP Customization Scenarios 18-5


<Property name="Foundation.customization.containerType.0"
default="wt.inf.library.WTLibrary"/>

And run xconfManager to propagate.

Customizing the search result table view


Search result tables use the Windchill R9.0 table common component and hence
the column display can be configured by creating a new table view. Please refer
[Crating Table View] for details regarding creating and configuring a new view.
Then we can pass the view as below to the picker tab and search results table
would be rendered with this view.
<wctags:itemPicker id="genericPicker" objectType="WCTYPE|
wt.part.WTPart|org.r_and_d.mypart" label="Part Picker using
generic" containerRef="<%=containerRefs.toString()%>"
componentId="scenarioOnePicker"
searchResultsViewId="wt.part.WTPart.customizedSearchView"
showVersion="false"/>

The view id “wt.part.WTPart.customizedSearchView” should be configured to


lookup the java class associated with this id which would define the table view.
Please refer to configuring table views document.
An example to configure this in SearchResultTable.properties.xconf file could be
<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>

A new java class com.ptc.netmarkets.search.views.CustomizedPartView should


be created which would define the view columns for this picker customization.

Customization Points
Please refer [Item Picker Best Practice] for further customizing Item Picker.

Limitations
As per current implementation, Lifecycle State is not limited only to states that the
object can have.

Sample Code
<%@ taglib prefix="wctags" tagdir="/WEB-INF/tags" %>

<HTML>

<BODY><TABLE>

<tr>

<%-- launching Item picker--%>

18-6 Windchill Customizer’s Guide


<wctags:itemPicker id="myItemPicker" label="Custom Item
Picker" pickerTitle=" Datecode Release" showVersion="false"
objectType=" WCTYPE|wt.part.WTPart|org.r_and_d.myPart "
showTypePicker="false" componentId="test.Customization"
typeComponentId="Foundation.customization"
searchResultsViewId="wt.part.WTPart.customizedSearchView"/>

</tr>

</BODY></TABLE>

</HTML>

JSP Customization Scenarios 18-7


Building a Picker that Enables Users to Select Projects
from an External Project DB
To configure a picker to fetch ProjDB data, by accepting criteria for name / id.

Background
Configure a picker to talk to a non-Windchill database to fetch and display data. A
user should be able to search the ProjDB database from Windchill to search for
projects. It’s only expected to get back the Project Id, Name and Title OR Short
Description

Scope/Applicability/Assumptions
Since we are dealing with non-Windchill objects here, there are a number of
points that we need to take care of while implementation.
• First thing is an assumption that user will be able to write a task or a webject
which will fetch data from a non-Windchill database and yet return an IE
Group. The framework requires an IE Group to render results.
• Since the records returned are not Windchill objects, the user will have to
build a few attributes which are not exactly related to the data like “NmOid”.
• A user would have a JSP client from which to launch this picker

Intended Outcome
You should see a text box and Find Button along with the specified label after
using the tags for user picker.

Since we need an object type for launching a generic picker as a required attribute
we would be using wt.fc.Persistable. However this doesn’t interfere with the
working of the picker. It’s just given to launch a generic picker.

18-8 Windchill Customizer’s Guide


a) On Click of the Find button the picker will get launched in a new window as
shown in the screen shot below.

Solution
Use the ProjDb Picker Common Component in your JSP file to include ProjDB
Picker in your application.

Prerequisite knowledge
To achieve this objective, you need to have a thorough understanding of the
following:
• Basic development involving HTML forms, JSP, XML.
• Knowledge of writing a task and a webject to get data from a non-Windchill
database
• Picker common components
• Table common component
• View creation
• Knowledge of Customizing the view to display and use data correctly from
non-Windchill objects
• Knowledge of writing a data utility to fetch NmOid object

JSP Customization Scenarios 18-9


Solution Elements

Element Type Description

PickerAttributes.xml XML Runtime location - \codebase\


pickerAttributes.xml
This file is used to customize the
search criteria at picker page.

SearchResultsTable.properties.xc Xconf Runtime location - \codebase\com\


onf ptc\netmarkets\search\
SearchResultsTable.properties.xconf
This file can be used to configure table
view definition.

Procedure – Launching and configuring a Generic Picker for searching non-Windchill data like
ProjDB Projects

Launching a picker with a single search criteria


A generic picker can be launched from any JSP page using the following tag. Here
we are launching a picker for ProjDB data
<wctags:genericPicker id="projDBPicker"
objectType="wt.fc.Persistable" componentId="projDBPickerId"
pickedDataFetcher="/Windchill/netmarkets/jsp/search/projDataFetche
r.jsp" displayAttribute="projId" label="ProjDB Picker using
generic" pickerTitle="ProjDB"
searchResultsViewId="wt.fc.Persistable.defaultPickerSearchView"/>

These attributes to the tag contain configuration information like, which view is
configured for this picker search result table, what is the data fetcher jsp to be
called etc.

Customizing the picker search criteria


The search criteria for a picker can be customized by defining the attributes in
PickerAttributes.xml file. This can be done by creating a new component id and
then defining the search criteria as below. For our ProjDb Picker, we can
configure the ProjectId or Name here, as search criteria
<ComponentID id="projDBPickerId">

<ObjectType id="wt.fc.Persistable">

<SearchCriteriaAttributes>

<Attributes>

<Name>projId</Name>

<DisplayName>Project ID</DisplayName>

<IsSearchable>true</IsSearchable>

</Attributes>

18-10 Windchill Customizer’s Guide


</SearchCriteriaAttributes>

</ObjectType>

</ComponentID>

Configuring the customized view for results table


Search result tables use the Windchill R9.0 table common component and hence
the column display can be configured by creating a new table view. Please refer
Creating Table View Documentation for details of how to create and configure a
new view. You can then pass the view as shown here to the picker tab to render
search results table with this view.
<wctags:genericPicker id="projDBPicker"
objectType="wt.fc.Persistable" componentId="projDBPickerId"
pickedDataFetcher="/Windchill/netmarkets/jsp/search/projDataFetche
r.jsp" displayAttribute="projId" label="ProjDB Picker using
generic" pickerTitle="ProjDB"
searchResultsViewId="wt.fc.Persistable.defaultPickerSearchView"/>

The view id “wt.fc.Persistable.defaultPickerSearchView” should be configured


in SearchResultTable.properties.xconf file to lookup the java class associated with
this ID.
Example:
<Service context="default"
name="com.ptc.core.htmlcomp.tableview.ConfigurableTable">
<Option
serviceClass="com.ptc.netmarkets.search.views.ProjDbPickerResultTa
bleView" requestor="java.lang.Object"
selector="wt.fc.Persistable.defaultPickerSearchView"/>
</Service>

A new java class


com.ptc.netmarkets.search.views.ProjDbPickerResultTableView should be
created which would define the view columns for this picker customization

Writing a data utility to get NmOid column in the results table to display a check box for selection
Since we are dealing with non-Windchill objects here, we need to populate this
NmOid column by writing a special data utility. This data utility will have to be
configured in the components.datautilities.properties file, for the specified
searchResultsViewId as follows –
<!—ProjDB Picker Results Table -->
<Option serviceClass="
com.ptc.netmarkets.search.utils.ProjDbPickerNmObjectDataUtility "
requestor="java.lang.Object"

selector=" wt.fc.Persistable.defaultPickerSearchView" //This value corresponds to the


searchResultsTableViewId in the picker tag.

cardinality=" duplicate "/>

JSP Customization Scenarios 18-11


Writing a data fetcher for displaying the selected value in the calling text box
You can configure a specific picked data fetcher for getting more information
about the data displayed. In this file, from the selected OID, one needs to
construct a string to be passed to the Json Object, used in Picker Callback
function. A user gets a comma separated string from the request parameter
“attributes” as follows “projId,oid”. Here the projId, is the display attribute
configured in the picker tag. A user can passed multiple attribute names, and Click
of “OK” button on the picker would return these in the request object, in the
dataFetcher.jsp. The picker will also return the selected Oid’s, as a comma
separated string, if multiselect is true, or as a single oid value if the picker is single
select.
The final string that needs to be constructed for the JSON object is as follows –
“{"pickedObject":
[{"oid":"MyTestOidFOrProjDB","<displayAttributeName>":"<selctedoid>"}]}”

Sample Code

Launching Picker from any JSP


<html>
<body>
<table>
<tr>
This is a ProjDB picker.
</tr>
<tr>
<%-- launching Proj DB Picker --%>
<wctags:genericPicker id="projDBPicker"
objectType="wt.fc.Persistable" componentId="projDBPickerId"
pickedDataFetcher="/Windchill/netmarkets/jsp/search/projDataFetche
r.jsp" displayAttribute="projId" label="ProjDB Picker using
generic" pickerTitle="ProjDB"
searchResultsViewId="wt.fc.Persistable.defaultPickerSearchView"/>
</tr>
</table>
</body>
</html>

18-12 Windchill Customizer’s Guide


Pickers from table toolbar

Objective
You want to a picker from table toolbar actions.

Background
The pickers from table toolbar are used when you have a requirement to launch
pickers from some table level action and accordingly populate the tables or do
some processing based on the results.

Scope/Applicability/Assumptions
Say you want to launch <your picker> from your table. It is assumed that your
action jsp file <MyPage>.jsp file in which you are putting picker tag includes
“/netmarkets/jsp/begin.jspf” or “/netmarkets/jsp/beginPopuf.jspf” file and
“/netmarkets/jsp/end.jspf” files.

Intended Outcome
On click of the action, you should see the corresponding picker getting launched.

Solution
Use the specific picker Common Component in your JSP file to include the 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 RBINFO files customization.
• Windchill xconfmanager concepts.

JSP Customization Scenarios 18-13


Solution Elements
Element Type 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\
pickerAttributes.xml

searchClientResource.rbInf RBINFO file You should use this file to localize


o the contents of the pickers.
Runtime location:
<WT_HOME>\src\com\ptc\
windchill\enterprise\search\
client\
searchClientResource.rbInfo

<your picker>.tag Custom JSP tag file This file is contains the
information about the supported
parameters for this tag.
Runtime location:
<WT_HOME>\codebase\ WEB-
INF\tags\<your picker>.tag

custom.js JavaScript file You should specify custom


pickerCallback function for
picker in this file.
Runtime location:
<WT_HOME>\codebase\
netmarkets\jsp\search\ custom.js

Procedure – Including a <your picker> in a jsp page


Configure basic picker:
<tr>

<wctags:<your picker name> id="myPickerId" inline=”true”


pickedAttributes=”<name of the attribute>” pickerCallback=”<your
pickerCallback function>” />

</tr>

Customization Points
Please refer to the <specific picker> Best Practice document for details regarding
the parameters.

18-14 Windchill Customizer’s Guide


For pickers that are launched from table toolbar they should have at least
following parameters in the tags.
inline=”true”

pickedAttributes=”<comma separated list of attribute names to be


fetched>

pickerCallback=”<name of pickerCallback function>”

multiSelect=”true”

JSP Customization Scenarios 18-15


Generating HTML Tags for ProductView Visualization
Within a JSP Page
To generate HTML code for the ProductView visualization components in a JSP
page, use the com.ptc.wvs.common.ui.VisualizationHelper class. See this class
entry in your installed Windchill Javadoc for more information.
General flow of logic:
The VisualizationHelper can be instantiated via the newVisualizationHelper()
factory method.
getCreateDialogWindow() is required to generate the Javascript fragment
required by the results returned from getDefaultVisualizationData(String,
Boolean, Locale). This code must be embedded somewhere in the HTML returned
by the JSP page.
getDefaultVisualizationData(String, Boolean, Locale) method returns an array of
String values. Each value corresponds to a different component within the
ProductView Visualization Service. Elements in the array can be accessed
directly through the indexes returned by the following methods:
getIndexOfVisLink(String, String), clipboardLinkIndex(), printLinkIndex(),
viewRepsLinkIndex(). Each String is the base HTML code for the ProductView
visualization component and can be embedded into the HTML returned by the
JSP page. It may be an '<A HREF .. /A>' code tag or other simple unformated
HTML tags.

Note: The getDefaultVisualizationData(String, Boolean, Locale) method returns


the basic HTML components necessary for accessing the ProductView
visualization components. Most likely the results will need to be used within
proper HTML tags. The responsibility of designing the user interface and properly
using the values returned by these methods belongs to the implementer.

Example usage:
// comp.ptc.wvs.common.ui.VisualizationHelper is assumed to be imported.
VisualizationHelper visHelper = newVisualizationHelper();
if (visHelper.isWVSEnabled()) //only execute code if WVS is enabled
{
// Embed the create dialog JavaScript somewhere in returned HTML.
// The below is just an example of calling it. Placement within
// HTML is the responsibility of the implementer.
out.println(visHelper.getCreateDialogWindow());

//ObjectReference object or and locale object is assumed to be obtained prior to


the following line
String visData[] = visHelper.getDefaultVisualizationData(or.toString(),new
Boolean(false), locale);
//Obtain array indices for thumbnail, clipboard link, print link, and
representations link
int thumbnailIndex = visHelper.getIndexOfVisLink(
VisualizationHelper.THUMBNAILS_PROP_PAGE_PREF_KEY,
VisualizationHelper.DEFAULT_THUMBNAILS_PROP_PAGE_PREF_VALUE);

18-16 Windchill Customizer’s Guide


int clipboardIndex = visHelper.clipboardLinkIndex();
int printIndex = visHelper.printLinkIndex();
int repsOrMarkupsIndex = visHelper.viewRepsLinkIndex();
/**
* Print the various HTML code fragments generated for each component.
* Any HTML formatting code must be wrapped around each of the following lines
**/
out.println(visData[thumbnailIndex]);
out.println(visData[clipboardIndex]);
out.println(visData[printIndex]);
out.println(visData[repsOrMarkupsIndex]);
}

JSP Customization Scenarios 18-17


18-18 Windchill Customizer’s Guide
19
Customizing the Product
Structure Explorer (PSE)

This chapter describes how to customize the Product Structure Explorer (PSE).

Topic Page
Customizing PSE Menus, Toolbars and Popup Menus.....................................19-2
Customizing PSE Table Display .......................................................................19-8
Customizing PSE for Soft Types.....................................................................19-13
Customizing PSE to Handle Modeled Subclasses ..........................................19-24
Customizing PSE Structure Queries................................................................19-31
Customizing Attribute Displays within Section Headings..............................19-35
Customizing Tabs - Configure Existing Tabs with Subtabs ...........................19-43
Allow Additional Steps During New Object Creation....................................19-45
Type Picker Display Customization................................................................19-47
Disabling Actions by Object Type ..................................................................19-49
Creating a Requirements Tab ..........................................................................19-51
Configurable Link Tables................................................................................19-67

19-1
Customizing PSE Menus, Toolbars and Popup Menus

Objective
You want to change the content of a PSE menu, toolbar or popup menu.

Background
The definition of the PSE Menus, Toolbars and popup menus are interconnected.
The definition of the user interface actions that appear in the toolbars and popup
menus is inherited from the ActionAccess definition of the Menu Bar.
The Menu Bar and Menu Items that are displayed do not change based on the
mode (“edit”, “draft” or “annotate”) in which PSE is working, though items may
become disabled if they are not relevant for the mode. The Toolbar does change
based on the mode, as do the popup menus exposed in the tables. Only menu items
that have an icon associated can appear in a toolbar.
In the Task Tabs of PSE, a number of tables are defined, which have tool bars and
popup menus. These are implemented in the exact same way as the main menu bar
via ActionAccess definitions, but the menus are not displayed.

Scope/Applicability/Assumptions

Intended Outcome
You may want to change the content of the toolbar for a given mode; for example
you may want to add the “New Query” Icon to the toolbar (before the Help icon)
that is displayed in Draft Mode for the main PSE window, and also to add the
actions “Insert Existing” and “Insert New” to the Uses Tab popup menu:

19-2 Windchill Customizer’s Guide


Solution
Change the appropriate element in
<Windchill>/codebase/config/logicrepository/xml/explorer/produc
tstructure/PDMLinkExplorerMenus.xml

to add the New Query Action to the Toolbar, and


<Windchill>/codebase/config/logicrepository/xml/explorer/struct
ureexplorer/ExplorerMenusForUsesTab.xml

to add the popup menu entries to the Uses Tab.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Management of XML file customizations

Solution Elements

Element Type Description

PDMLinkExplorerMenus.xml XML file Holds the definition of the main PSE Application
Menus, toolbars and popup menus that appear in
the tree displays.
Located in:
<Windchill>/codebase/config/logicreposito
ry/xml/explorer/productstructure

ExplorerMenuItems.xml XML file Holds Menu Item definitions, referenced from the
main application menu
(PDMLinkExplorerMenus.xml) and
ExplorerMenus.xml
Located in:
<Windchill>/codebase/config/logicreposito
ry/xml/explorer/structureexplorer

ExplorerMenus.xml XML file Holds Menu definitions for sub-menus referenced


from the main application menu
(PDMLinkExplorerMenus.xml)
Located in:
<Windchill>/codebase/config/logicreposito
ry/xml/explorer/structureexplorer

Customizing the Product Structure Explorer (PSE) 19-3


Element Type Description

ExplorerMenusForAttributeTa XML file Holds the definition of the toolbars and popup
ble.xml menus for the Attribute Table on the Information
Tab.
Located in:
<Windchill>/codebase/config/logicreposito
ry/xml/explorer/structureexplorer

ExplorerMenusForDocuments XML file Holds the definition of the toolbars and popup
Tab.xml menus for the tables on the Documents Tab.
Located in:
<Windchill>/codebase/config/logicreposito
ry/xml/explorer/structureexplorer

ExplorerMenusForReplacemen XML file Holds the definition of the toolbars and popup
tsTab.xml menus for all tables on the Replacements Tab.
Located in:
<Windchill>/codebase/config/logicreposito
ry/xml/explorer/structureexplorer

ExplorerMenusForUsesTab.x XML file Holds the definition of the toolbars and popup
ml menus for all tables on the Uses Tab.
Located in:
<Windchill>/codebase/config/logicreposito
ry/xml/explorer/structureexplorer

ActionAccess XML Holds the definition of a MenuBar, related Menus


element and MenuItems. Each ActionAccess element (i.e.,
MenuBar definition) must include all the actions
that will be used in the related Toolbars and Popup
Menus.

Note: Adding new actions to the MenuBar


definition is not supported.

Contained in PDMLinkExplorerMenus.xml and


ExplorerMenus*.xml

ModeToolBar XML Defines a toolbar for a specific mode. Specifies the


element ApplicationMode (via an Import) and a list of
MenuItemIdentifiers.

ModePopupMenu XML Defines a popup menu for a specific mode. Simply


element specifies the mode and a list of
MenuItemIdentifiers.

19-4 Windchill Customizer’s Guide


Element Type Description

ExplorerMode XML Sub-element of ModeToolBar or


element ModePopupMenu. Specifies the mode.

MenuItemIdentifier XML Sub-element of ModeToolBar or


element ModePopupMenu. Identifies (through the id
parameter) a defined Action.

Procedure – Customizing the Toolbar


It is possible to change the content of the Toolbar for a given mode. Adding
existing, deleting and re-ordering the items in the definitions are supported.
Consider the Toolbar that is displayed in Draft Mode for the main PSE window.
For the example of adding the action to create a “New Query” to the toolbar,
simply insert the MenuItemIdentifier for that entry into the XML
<ModeToolBar id="ToolBarB">
<Import id="ptc.wnc.exp.DraftAppMode"/>
<MenuItemIdentifier id="FileNewPartMI"/>
<MenuItemIdentifier id="FileOpenPartMI"/>
<Separator/>
<MenuItemIdentifier id="FileSaveChangesMI"/>
<MenuItemIdentifier id="FileAnnotationValidationMI"/>
<MenuItemIdentifier id="ptc.wnc.exp.CloseMI"/>
<MenuItemIdentifier id="ptc.wnc.exp.LaunchNewPSEMI"/>
<MenuItemIdentifier id="SetConfigSpecMI"/>
<Separator/>
<MenuItemIdentifier id="ptc.wnc.exp.InfoPageMI"/>
<MenuItemIdentifier id="ptc.wnc.exp.CutMI"/>
<MenuItemIdentifier id="ptc.wnc.exp.CopyMI"/>
<MenuItemIdentifier id="ptc.wnc.exp.PasteMI"/>
<Separator/>
<MenuItemIdentifier
id="ptc.wnc.exp.CopyToWindchillClipboardMI"/>
<MenuItemIdentifier
id="ptc.wnc.exp.CopyFromWindchillClipboardMI"/>
<Separator/>
<MenuItemIdentifier id="SelectedAddChildMI"/>
<MenuItemIdentifier id="SelectedAddNewChildMI"/>
<MenuItemIdentifier id="SelectedAddInsertNewMI"/>
<Separator/>
<MenuItemIdentifier id="SelectedReplaceExistingMI"/>
<MenuItemIdentifier id="SelectedReplaceCreateAndReplaceMI"/>
<MenuItemIdentifier id="SelectedReplaceNewMI"/>
<MenuItemIdentifier id="SelectedReplaceAlternateMI"/>
<Separator/>
<MenuItemIdentifier id="FileSpecEditorLaunchMI"/>
<MenuItemIdentifier id="ptc.wnc.exp.ReviseMI"/>
<MenuItemIdentifier id="SelectedRemoveMI"/>
<Separator/>
<MenuItemIdentifier id="ptc.wnc.exp.SelectParentMI"/>
<MenuItemIdentifier id="ptc.wnc.exp.ExpandAllMI"/>
<Separator/>

Customizing the Product Structure Explorer (PSE) 19-5


<MenuItemIdentifier id="EditEditModeMI"/>
<Separator/>
<MenuItemIdentifier id="ptc.wnc.exp.FindInStructureMI"/>
<MenuItemIdentifier id="NewQueryMI"/>
<Separator/>
<MenuItemIdentifier id="HelpTopicsMI"/>
</ModeToolBar>

This results in the New Query icon appearing in the toolbar as shown in Section
Intended Outcome.

Customization Points

Customizing a Popup Menu


It is possible to change the content of a Popup Menu for a given mode. Adding
existing actions, deleting and re-ordering the items in the definitions are
supported.
Consider the Uses Tab. The popup menu for the table does not, out-of-the-box;
include the actions Insert Existing and Insert New in Draft mode. To add these
to the popup menu, simply change the XML in ExplorerMenusForUsesTab.xml
such that these MenuItemIdentifier is inserted.
<ModePopupMenu id="PopupMenuB">
<Import id="ptc.wnc.exp.DraftAppMode"/>
<Import id="ptc.wnc.exp.AnnotateAppMode"/>
<MenuItemIdentifier id="ptc.wnc.exp.CutAssocMI"/>
<MenuItemIdentifier id="ptc.wnc.exp.CopyAssocMI"/>
<MenuItemIdentifier id="ptc.wnc.exp.PasteAssocMI"/>
<Separator/>
<MenuItemIdentifier id="AddChildMI"/>
<MenuItemIdentifier id="NewChildMI"/>
<Separator/>
<MenuItemIdentifier id="ReplaceExistingMI"/>
<MenuItemIdentifier id="CreateAndReplaceMI"/>
<MenuItemIdentifier id="ReplaceNewMI"/>
<MenuItemIdentifier id="ReplaceAlternateMI"/>
<Separator/>
<MenuItemIdentifier id="ptc.wnc.exp.RevertAssocMI"/>
<MenuItemIdentifier id="ptc.wnc.exp.CommentAssocMI"/>
</ModePopupMenu>

The results in the “Replace with Alternate/Substitute” appearing in the popup in


the Uses Tab as shown the Intended Outcome section on 19-2.

Limitations
Adding new MenuItems to Menus, Toolbar or Popup menus for actions that are
not defined is not supported, as PSE currently has no supported API to allow
custom actions to be created. Also adding actions to tables for which they are not
designed is not supported.

19-6 Windchill Customizer’s Guide


Other Resources

Related Customization Documentation


• Managing Customizations chapter on page 5-1

Customizing the Product Structure Explorer (PSE) 19-7


Customizing PSE Table Display

Objective
You wish to change the default display order of columns in a PSE table, whether a
specific column is mandatory or optional, or whether a column is frozen.

Background
With Windchill PDMLink Rev 9, PSE now provides the capability for users to
customize the display of columns in tables. For example the Columns Details for
the Uses Tab.

However, what a user can do is controlled within the bounds set in the PSE XML
files that define the columns in each table.

Scope/Applicability/Assumptions
As these changes are being made to the PSE XML files, they will apply to all
users of PSE.

Intended Outcome
The Rev 9 default display is that Number is a frozen mandatory column that is
frozen (so it does not scroll) in the Uses Tab. Lets consider that we wish that
Name is a mandatory attribute to display, that it and Reference Designator Range
are frozen columns, Number is not frozen and is displayed though optional, Line
Number is available but not displayed. As Number is optional, it will be removed
from the tabular input search.

19-8 Windchill Customizer’s Guide


This is how the PSE User Interface will appear:

Solution
The CellDefinition element used in the PSE XML files has a number of attributes
that control the display of columns in a table and dictate to what extent a user can
change the table’s appearance and behavior.

Attribute Description

mandatory If mandatory, the user may not hide the column

displayWhenNoPreferenceSet Whether the column will be displayed, if it is


not mandatory

pinnable Whether the column may be frozen by the user

pinned Whether the column appears frozen by default

usedByTabularInput In Draft and Annotate modes specifies if the


cell will be used in Data Entry search.

Many of the PSE Tables including the Uses Tab Table are defined in the file
<Windchill>/codebase/config/logicrepository/xml/explorer/structure
explorer/ExplorerForTablesAndPanels.xml

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Management of XML file customizations

Customizing the Product Structure Explorer (PSE) 19-9


Solution Elements
Element Type Description

ExplorerForTablesAndPanels.xml XML file Holds the definition of the tables and panels.
Located in:
<Windchill>/codebase/config/logicrepo
sitory/xml/structureexplore

Table XML element Defined the table and contents

CellDefinition XML element The attribute with its appropriate behavior to


be displayed in the AttributeTable.

Procedure
The Table id ptc.wnc.exp.PartUsesLinkTabTable in the file:
<Windchill>/codebase/config/logicrepository/xml/explorer/structureexplorer/Exp
lorerForTablesAndPanels.xml
is used to show the Uses Table BOM, when showing occurrences
ptc.wnc.exp.PartUsesOccTabTable us used.
By change the order of the CellDefinitions for the Table, and specifying
appropriate values for mandatory, displayWhen NoPreferenceSet, pinnable,
pinned and usedByTabularInput, the desired table can be formed.
<Table id="ptc.wnc.exp.PartUsesLinkTabTable"
selectionMode="multi-non-contiguous" displayMode="view">

<CellDefinition id="name" pinned="true" mandatory="true"


usedByTabularInput="true" displayModeOverride="edit">
<AttributeDefinition attributeId="name">
<Import id="ptc.wnc.exp.SurfaceAttrAction"/>
</AttributeDefinition>
</CellDefinition>

<CellDefinition id="referenceDesignatorRange"
pinned="true" mandatory="false" displayModeOverride="edit">
<Label>
<Resource key="referenceDesignatorRangeLabel"/>
</Label>
<AttributeDefinition
attributeId="referenceDesignatorRange">
<Import id="ptc.wnc.exp.RefDesRangeAttrAction"/>
</AttributeDefinition>
</CellDefinition>

<CellDefinition id="number" pinned="false"


mandatory="false" displayWhenNoPreferenceSet="true"
usedByTabularInput="false" displayModeOverride="edit">
<AttributeDefinition attributeId="number">
<Import id="ptc.wnc.exp.SurfaceAttrAction"/>

19-10 Windchill Customizer’s Guide


</AttributeDefinition>
</CellDefinition>

<CellDefinition id="usedLineNumber" pinned="false"


mandatory="false" displayWhenNoPreferenceSet="false"
displayModeOverride="edit">
<Label>
<Resource key="lineNumberLabel"/>
</Label>
<AttributeDefinition attributeId="usedLineNumber"

rendererClass="com.ptc.windchill.explorer.structureexplorer.render
er.component.LineNumberComponent">
<Import id="ptc.wnc.exp.LineNumberAttrAction"/>
</AttributeDefinition>
</CellDefinition>

After this change has been made, the method server has to be re-started. The client
UI may still not appear correct, this is because a user preference is used to hold the
current table layout. To clear this use the File->Preference action and reset the
column/window layout preferences. When PSE is restarted, the Uses Tab table
should appear as shown in the Intended Outcome section on 19-8.

Customization Points
The definition of the PSE Structure with id “ptc.pdm.pse.ExplorerTreeTable” is to
be found in:

Customizing the Product Structure Explorer (PSE) 19-11


<Windchill>/codebase\config\logicrepository\xml\explorer\
productstructure\PDMLinkExplorerForTablesAndPanels.xml

Also, if Windchill Supplier Management is installed, its tables are defined in:
<Windchill>/codebase\config\logicrepository\xml\explorer\
productstructure\ExplorerForTablesAndPanelsForSUMA.xml

Other Resources

Related Customization Documentation


• Managing Customizations chapter on page 5-1

19-12 Windchill Customizer’s Guide


Customizing PSE for Soft Types

Objective
You have used the Attribute and Type Manager to define soft types of WTPart
and possibly added attributes to WTPartUsageLink. Although these types and
attributes typically appear in PSE without customization, you wish to control the
display of these attributes in the PSE UI.

Background
The selection of a type of Part in PSE typically automatically detects if soft types
have been defined with the Type Manager. Attributes will automatically be
prompted for, and displayed. This is achieved in the PSE XML files by entries
referencing attribute definitions with id’s of:
• ALL_SOFT_SCHEMA_ATTRIBUTES
• ALL_SOFT_CLASSIFICATION_ATTRIBUTES
• ALL_SOFT_USAGE_LINK_SCHEMA_ATTRIBUTES
Although these entries are useful, it is not possible to control the order of display.
Also, some values may get set programmatically on the server, and so the user
should not be allowed to specify values.
Consider the simple example where WTPart has had an IBA myDescription added
to the base definition. A myMechanical Part has been defined in the Type
Manager with attributes of myCost and myWeight, WTPartUsageLink has been
extended to have an IBA of myColor.
The steps to insert a new myMechanical Part into an assembly would result in
these screens.

Customizing the Product Structure Explorer (PSE) 19-13


The Insert New wizard would present a drop down of instantiable types. The user
selects “myMechanical” part.

After the Name and other properties have been specified, the last step in the
wizard will prompt for the IBA’s, although the Attribute column can be sorted, the
default order is not controlled.

The info Tab for myMechanical Part presents all attributes, but not in any sort of
order. The attributes in the upper part of the display represent the fixed set
applicable to identify that object; some of these may not be relevant. The
attributes in the lower editable table include attributes inherited from WTPart and
are in no controlled order.

19-14 Windchill Customizer’s Guide


The myColor attribute would not appear in the Uses Tab, but it might be useful for
the user to see the value with the other UsageLink attributes.
By customizing the PSE XML files, it is possible to explicitly define those
attributes to be presented to the user. This typically impacts the Information Tab,
and Part Creation and Insert wizards.

Scope/Applicability/Assumptions
As these changes are being made to the PSE XML files, they will apply to all
users of PSE.

Intended Outcome
Considering the example described above.

When specifying the attributes of the New Part, the attributes in the last step of the
wizard appear in the order defined in the PSE XML.

Customizing the Product Structure Explorer (PSE) 19-15


files.

The attributes in the lower table of the Information Tab can also be ordered.

The Uses BOM Table can be configured to show the Usage Link attribute.

Solution
For the dataType, defined a new ExplorerElementGroup with the context
application of “ptc.wnc.StructureExplorer”. Within this element define the
contents of the Attribute Tables.
It is likely that if you are doing this customization you have many types of
WTPart defined. Although these element definitions can be added to the file

19-16 Windchill Customizer’s Guide


<Windchill>/codebase/config/logicrepository/xml/explorer/structureexplorer/Exp
lorerForTablesAndPanels.xml
This file is getting large, and it is difficult to identify customer extensions. So the
suggestion is to create a file per soft part type to hold the customization.
The AttributeTables with id’s ptc.wnc.exp.CreatPartTab3,
ptc.wnc.exp.CreatePartNoUsageLinkTab3 and ptc.wnc.exp.EditPropertiesTable
would be defined for each dataType.
The addition of the attributes in the Uses Tab is achieved by including the
appropriate CellDefinition for the table with id ptc.wnc.exp.PartUsesLinkTable in
ExplorerForTablesAndPanels.xml

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
The management of XML file customizations

Solution Elements

Element Type Description

ExplorerForTableAndPanels.xml XML file Holds the definition of the PSE Tables and
panels
Located in:
<Windchill>/codebase/config/logicrepo
sitory/xml/structureexplore

LogicContext XML element Specifies the application and data type that the
definition is to be applied

AttributeTable XML element Defined the attribute table and contents

CellDefinition XML element The attribute with its appropriate behavior to


be displayed in the AttributeTable.

Placement remove=”true” XML element Remove=true is used to stop a property from


appearing due to inheritance.

Procedure
Either create a new file representing the Soft Part (myMechanical.xml) in the
directory:
Windchill>/codebase/config/logicrepository/xml/explorer/structuree
xplorer

and insert the following lines, or add the ExplorerElementGroup to

Customizing the Product Structure Explorer (PSE) 19-17


Windchill>/codebase/config/logicrepository/xml/explorer/structuree
xplorer/ExplorerForTablesAndPanels.xml

<?xml version="1.0" standalone="no" ?>


<!DOCTYPE LogicRepository SYSTEM
"/config/logicrepository/dtd/LogicRepository.dtd">
<LogicRepository>

<ExplorerElementGroup>
<LogicContext application="ptc.wnc.StructureExplorer"
dataType="com.aprilia.www.myMechanical"/>

<AttributeTable id="ptc.wnc.exp.CreatePartTab3">
<Table id="Table" displayMode="edit">
<!-- These 3 entries remove the inherited entries from
WTPart -->
<CellDefinition id="ALL_SOFT_SCHEMA_ATTRIBUTES">
<Placement remove="true"/>
</CellDefinition>
<CellDefinition id="ALL_SOFT_CLASSIFICATION_ATTRIBUTES">
<Placement remove="true"/>
</CellDefinition>
<CellDefinition
id="ALL_SOFT_USAGE_LINK_SCHEMA_ATTRIBUTES">
<Placement remove="true"/>
</CellDefinition>

<!-- Add the entries for attributes on Parts and


UsageLink in the specific order -->
<CellDefinition id="myDescription">
<AttributeDefinition
attributeId="com.aprilia.www.myDescription"
imageName="wtcore/images/part.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
<CellDefinition id="myColor">
<AttributeDefinition
attributeId="com.aprilia.www.myColor"
imageName="com/ptc/windchill/explorer/config/images/usesTab.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
<CellDefinition id="myCost">
<AttributeDefinition
attributeId="com.aprilia.www.myCost"
imageName="wtcore/images/part.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
<CellDefinition id="myWeight">
<AttributeDefinition
attributeId="com.aprilia.www.myWeight"
imageName="wtcore/images/part.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
</Table>

19-18 Windchill Customizer’s Guide


<Import id="ptc.wnc.exp.NewObjectAttrTableAA"/>
</AttributeTable>

<AttributeTable
id="ptc.wnc.exp.CreatePartNoUsageLinkTab3">
<Table id="Table" displayMode="edit">

<!-- These 2 entries remove the inherited entries from


WTPart -->
<CellDefinition id="ALL_SOFT_SCHEMA_ATTRIBUTES">
<Placement remove="true"/>
</CellDefinition>
<CellDefinition id="ALL_SOFT_CLASSIFICATION_ATTRIBUTES">
<Placement remove="true"/>
</CellDefinition>

<!-- Add the entries for attributes on Parts in the


specific order -->
<CellDefinition id="myDescription">
<AttributeDefinition
attributeId="com.aprilia.www.myDescription"
imageName="wtcore/images/part.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
<CellDefinition id="myCost">
<AttributeDefinition
attributeId="com.aprilia.www.myCost"
imageName="wtcore/images/part.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
<CellDefinition id="myWeight">
<AttributeDefinition
attributeId="com.aprilia.www.myWeight"
imageName="wtcore/images/part.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
</Table>
<Import id="ptc.wnc.exp.NewObjectAttrTableAA"/>
</AttributeTable>

<AttributeTable id="ptc.wnc.exp.EditPropertiesTable">
<Table id="Table" displayMode="edit">

<!-- These 3 entries remove the inherited entries from


WTPart -->
<CellDefinition id="source">
<Placement remove="true"/>
</CellDefinition>
<CellDefinition id="partType">
<Placement remove="true"/>
</CellDefinition>
<CellDefinition id="ALL_SOFT_SCHEMA_ATTRIBUTES">
<Placement remove="true"/>
</CellDefinition>
<CellDefinition id="ALL_SOFT_CLASSIFICATION_ATTRIBUTES">

Customizing the Product Structure Explorer (PSE) 19-19


<Placement remove="true"/>
</CellDefinition>
<CellDefinition>
id="ALL_SOFT_USAGE_LINK_SCHEMA_ATTRIBUTES">
<Placement remove="true"/>
</CellDefinition>

<!-- Add the entries for attributes on Parts and


UsageLink in the specific order -->
<CellDefinition id="myDescription">
<AttributeDefinition
attributeId="com.aprilia.www.myDescription"
imageName="wtcore/images/part.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
<CellDefinition id="myColor">
<AttributeDefinition
attributeId="com.aprilia.www.myColor"
imageName="com/ptc/windchill/explorer/config/images/usesTab.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
<CellDefinition id="myCost">
<AttributeDefinition
attributeId="com.aprilia.www.myCost"
imageName="wtcore/images/part.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
<CellDefinition id="myWeight">
<AttributeDefinition
attributeId="com.aprilia.www.myWeight"
imageName="wtcore/images/part.gif">
<Import id="ptc.wnc.exp.CreatePanelAttrAction"/>
</AttributeDefinition>
</CellDefinition>
</Table>
<Import id="ptc.wnc.exp.EditPropertiesTableAA"/>
</AttributeTable>

</ExplorerElementGroup>

</LogicRepository>

This results in the attributes being requested in the Wizard and Information Tab as
shown in Section Intended Outcome.
To add the IBA to the Uses Tab, edit:
Windchill>/codebase/config/logicrepository/xml/explorer/structuree
xplorer/ExplorerForTablesAndPanels.xml

Locate the Table entry with id ptc.wnc.exp.PartUsesLinkTabTable and add:


<CellDefinition id="myColor" displayModeOverride="edit">
<AttributeDefinition attributeId="com.aprilia.www.myColor">
<Import id="ptc.wnc.exp.AssocAttrAction"/>

19-20 Windchill Customizer’s Guide


</AttributeDefinition>
</CellDefinition>

The method server will need to be re-started in order that these changes are
applied.

Further customization
To extend the above example, consider adding the “myDescription” attribute to
the Uses Tab. When editing this String attribute, the user may want to specify
many characters, however to perform this in the space of the cell in a table is not
easy. So, it is possible to associate a different renderer to this attribute that will
popup a dialog when editing the value, allow the user to enter many lines of text.
Edit:
Windchill>/codebase/config/logicrepository/xml/explorer/structuree
xplorer/ExplorerForTablesAndPanels.xml

Locate the Table entry with id ptc.wnc.exp.PartUsesLinkTabTable and add


<CellDefinition id="myDescription" displayModeOverride="edit">
<AttributeDefinition attributeId="com.aprilia.www.myDescription"
rendererClass="com.ptc.windchill.explorer.structureexplorer.renderer.component.Mult
ilineStringComponent">
<Import id="ptc.wnc.exp.AssocAttrAction"/>
</AttributeDefinition>
</CellDefinition>

Just using the Golf Cart as an example, this will result in the following dialog
being presented when the “…” button is selected in the
cell.

This renderer could also be applied to the attributes in the Information Tab.

Customizing the Product Structure Explorer (PSE) 19-21


Customization Points
In section Background there are a number of special attributes that are defined in
LogicalAttributes.xml that allow PSE to display a number of attributes for a single
definition. These include:

Logical Form Description

ALL_SOFT_ATTRIBUTES All IBAs persisted on the object

ALL_SOFT_CLASSIFICATION_A All IBAs associated with the


TTRIBUTES classification of the object.

ALL_SOFT_NON_SCHEMA_ATT All IBAs persisted on the object that


RIBUTES are not associated with the type of the
object.

ALL_SOFT_SCHEMA_ATTRIBUT All IBAs associated with the type of


ES the object.

ALL_SOFT_NON_CLASSIFICATI All IBAs associated with the type of


ON_SCHEMA_ATTRIBUTES the object that are not also associated
with the classification of the object.

ALL_SOFT_NON_CLASSIFICATI All IBAs persisted on the object that


ON_ATTRIBUTES are not associated with the
classification of the object

ALL_SOFT_USAGE_LINK_SCHE In the context of a part, all IBAs on the


MA_ATTRIBUTES part usage link(s) that are associated
with the type of the part usage link

ALL_SOFT_SCHEMA_ATTRIBUT All IBAs associated with the type


ES_FOR_INPUT_TYPE specified in the filter, which may be a
supertype of the actual object

In Rev 9, PSE uses ALL_SOFT_SCHEMA_ATTRIBUTES",


"ALL_SOFT_CLASSIFICATION_ATTRIBUTES" and
ALL_SOFT_USAGE_LINK_SCHEMA_ATTRIBUTES" in the definition of
Information Tab attribute table (and also in the Create Wizard. In the Information
Tab)
Using “ALL_SOFT_ATTRIBUTES” instead of
ALL_SOFT_SCHEMA_ATTRIBUTES or adding an entry for
ALL_SOFT_NON_SCHEMA_ATTRIBUTES would allow attributes
programmatically populated from CAD to be displayed.

19-22 Windchill Customizer’s Guide


Other Resources

Related Customization Documentation


• Managing Customizations chapter on page 5-1

Customizing the Product Structure Explorer (PSE) 19-23


Customizing PSE to Handle Modeled Subclasses

Objective
You have created a custom modeled business object; you want to customize the
PSE so that it will fully support your modeled subclass.

Scope/Applicability/Assumptions
You have separately created your modeled subclass.

Intended Outcome
Instances of your modeled subclass will be detected and presented by PSE in the
same manner as out-of-the-box modeled objects.

Solution
Make changes in the following three areas:
• LogicalAttributes.xml
• PSE Tables and Panels
• Customized command delegates

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• The management of XML file customizations
• The management of RBINFO file customizations

Solution Elements

Element Type Description

LogicalAttributes.xml XML file Used to configure modeled attribute


mappings from a "logical form" to its
"external form".

Procedure – Customizing PSE to Handle Modeled Subclasses


This section contains the following topics:
• LogicalAttributes.xml
• PSE Tables and Panels
• Customized command delegates

19-24 Windchill Customizer’s Guide


LogicalAttributes.xml
A LogicalAttributes.xml file, located in
<Windchill>/codebase/LogicalAttributes.xml, is used to configure modeled
attribute mappings from a "logical form" to its "external form". A mapping is
required for all modeled attributes that represent an association from one object to
another. For example some of the entries defined for the WTPart to
WTPartMaster reference are:
<Class name="wt.part.WTPart">
<Property>
<LogicalForm>defaultUnit</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
wt.part.WTPartMaster~MBA|defaultUnit</ExternalForm>
</Property>
<Property>
<LogicalForm>masterReference</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
wt.part.WTPartMaster</ExternalForm>
</Property>
<Property>
<LogicalForm>name</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
wt.part.WTPartMaster~MBA|name</ExternalForm>
</Property>
<Property>
<LogicalForm>number</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
wt.part.WTPartMaster~MBA|number</ExternalForm>
</Property>
<Property>
<LogicalForm>organizationReference</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
wt.part.WTPartMaster~MBA|organizationReference^WCTYPE|
wt.org.WTOrganization</ExternalForm>
</Property>
<Property>
<LogicalForm>organizationName</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
wt.part.WTPartMaster~MBA|organizationReference^WCTYPE|
wt.org.WTOrganization~MBA|name</ExternalForm>
</Property>
<Property>
<LogicalForm>usedLineNumber</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
wt.part.WTPartMaster~MBA|uses@WCTYPE|
wt.part.WTPartUsageLink~MBA|
lineNumber.value</ExternalForm>
</Property>
<Property>
<LogicalForm>usedLink</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
wt.part.WTPartMaster~MBA|uses@WCTYPE|
wt.part.WTPartUsageLink</ExternalForm>
</Property>
</Class>

Customizing the Product Structure Explorer (PSE) 19-25


Using the example that "ext.cust.CustPart" extends wt.part.WTPart, and
"ext.cust.SubPartMaster" extends wt.part.WTPartMaster, the following should be
added to the site-specific file called
<Windchill>/codebase/LogicalAttributesSite.xml:
<Class name="ext.cust.CustPart">
<Property>
<LogicalForm>defaultUnit</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
ext.cust.SubPartMaster~MBA|defaultUnit</ExternalForm>
</Property>
<Property>
<LogicalForm>masterReference</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
ext.cust.SubPartMaster</ExternalForm>
</Property>
<Property>
<LogicalForm>name</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
ext.cust.SubPartMaster~MBA|name</ExternalForm>
</Property>
<Property>
<LogicalForm>number</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
ext.cust.SubPartMaster~MBA|number</ExternalForm>
</Property>
<Property>
<LogicalForm>organizationReference</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
ext.cust.SubPartMaster~MBA|organizationReference^WCTYPE|
wt.org.WTOrganization</ExternalForm>
</Property>
<Property>
<LogicalForm>organizationName</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
ext.cust.SubPartMaster~MBA|organizationReference^WCTYPE|
wt.org.WTOrganization~MBA|name</ExternalForm>
</Property>
<LogicalForm>usedLineNumber</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
ext.cust.SubPartMaster~MBA|uses@WCTYPE|
wt.part.WTPartUsageLink~MBA|
lineNumber.value</ExternalForm>
</Property>
<Property>
<LogicalForm>usedLink</LogicalForm>
<ExternalForm>MBA|masterReference^WCTYPE|
ext.cust.SubPartMaster~MBA|uses@WCTYPE|
wt.part.WTPartUsageLink</ExternalForm>
</Property>
</Class>

19-26 Windchill Customizer’s Guide


PSE Tables and Panels
You do not need to add new modeled attributes to the LogicalAttributes.xml file,
but you must add them to the appropriate PSE configuration XML files. Refer to
Customizing PSE for Soft Types on page 19-13 for additional information.

Note: When specifying new modeled attributes that are defined only for subclass
objects, the corresponding "AttributeGroup" or “AttributeTable” or "Table”
defined in a "wt.part.WTPart" context should be copied to the appropriate
subclass context.

Only new modeled attributes need to be listed. Existing attributes will be


inherited. For example, name and number will be inherited from WTPart.
To remove attributes from a sub-classed panel that are inherited, use "<Placement
remove="true"/>", E.g.
<AttributeDefinition id="containerName”>
<Placement remove="true"/>"
</AttributeDefinition>

A good practice when adding element groups for customized objects is to put all
customized changes in a separate file, rather than edit existing files. Name them
consistently, e.g. CustomExplorerForTablesAndPanels.xml.
Using the previous example of "ext.cust.CustPart" extends "wt.part.WTPart", the
following AttributeGroup
<ExplorerElementGroup>
<LogicContext application="ptc.wnc.StructureExplorer"
dataType="wt.part.WTPart"/>
<AttributeGroup id="ptc.wnc.exp.ViewPropertiesPanel" displayMode="view">
<CellDefinition id="number">
<AttributeDefinition attributeId="number"/>
</CellDefinition>
<CellDefinition id="organizationIdentifier">
<AttributeDefinition attributeId="organizationIdentifier"/>
</CellDefinition>
<CellDefinition id="name">
<AttributeDefinition attributeId="name"/>
</CellDefinition>
<CellDefinition id="versionIterationView">
<AttributeDefinition attributeId="versionIterationView"/>
</CellDefinition>
...
</AttributeGroup>
</ElementGroup>
should be copied under the LogicContext for "ext.cust.CustPart" like this:
<ExplorerElementGroup>
<LogicContext application="ptc.wnc.StructureExplorer"
dataType=" ext.cust.CustPart "/>
<AttributeGroup id="ptc.wnc.exp.ViewPropertiesPanel" displayMode="view">
<!-- name and number will inherit from WTPart -->

<!-- adding new modeled attributes here -->

Customizing the Product Structure Explorer (PSE) 19-27


<CellDefinition id="intMBA">
<AttributeDefinition attributeId="intMBA"/>
</CellDefinition>
...
</AttributeGroup>
</ElementGroup>

Customized command delegates


PSE uses a Command/CommandDelegate mapping to control some of its
operations. The most notable example is the "Duplicate Action". To "duplicate" a
customized class, you need to subclass the appropriate copy delegate. In the case
of "CustPart", you need to create a class that is a subclass of
wt.enterprise.CopyWTPartDelegate and handle the copying of your customized
modeled attributes.

Writing a Copy Delegate for A Custom Class


When an out of the box business object (such as part) is customized to create a
modeled sub-class, it is necessary to create and configure a custom copy delegate
class so that when the part is copied (or saved as), additional modeled attributes
are handled properly.

This document illustrates the steps with a simple example: a custom part class
“MyPart” that extends wt.part.WTPart with a single string attribute “myAttr”.

Creating a Copy Delegate


As illustrated in the figure, you can simply extend
wt.enterprise.CopyWTPartDelegate and override its newCopy() method. The
purpose is to handle any custom attributes, in this particular case, myAttr. Here’s
how this method is implemented:
public final RevisionControlled newCopy( RevisionControlled object
)throws WTException {

19-28 Windchill Customizer’s Guide


//##begin newCopy%461E645C0050f.body preserve=yes
if (object == null) return null;
MyPart new_copy = (MyPart) super.newCopy(object);
MyPart original = (MyPart) object;
String my_attr = original.getMyAttr();
if (my_attr != null) {

try {
new_copy.setMyAttr(original.getMyAttr());

}
catch (WTPropertyVetoException e) {
throw new WTException(e);
}

}
return new_copy;
//##end newCopy%461E645C0050f.body

Configuring a Copy Delegate


To instruct Windchill to use the custom copy delegate CopyMyPartDelegate as
the copy delegate class for MyPart, the following line needs to be inserted into
configuration file <windchill-install-
directory>/codebase/wt/enterprise/EnterpriseServerDelegate.properties.
wt.services/svc/default/wt.enterprise.CopyDelegate/null/<my-
package>.MyPart/0=<mypackage>.

CopyMyPartDelegate/singleton

Customization Points

Customizing Localizable Labels and Enumerations

Caution: When working with RBINFO files, follow the practices recommended
in the Managing Customizations chapter starting on page 5-1, for example
Changing Displayed Text Found in RBINFO Files.

Each modeled object has an associated RBINFO file, created during generation,
that contains localized strings that are used as the labels for attributes and columns
in PSE. If the label needs to be changed, the corresponding RBIFNO file should
be edited. For example, in the file CustPartModelRB.rbInfo, to change the label
for the attribute "booleanMBA", edit the following line:
CustPart.booleanMBA.value=New Label for booleanMBA

Modeled enumerations will display the internal values of the enumerations, when
rendered as a drop-down menu in PSE. To change the labels displayed in a drop-
down menu, the corresponding RBINFO file for the enumeration should be
edited. For example, if you generate a class, "public final class MyEnum extends

Customizing the Product Structure Explorer (PSE) 19-29


EnumeratedType" with values "apple", "dog", "cat" and you wish to change the
display value in the drop-down menu, edit the file MyEnumRB.rbInfo like this:
# Entry Contents
apple.value=Apples
dog.value=Dogs
cat.value=Cats

More information can be found in the Enumerated Types chapter on page 34-1.

Other Resources
• Customizing PSE Table Display on page 19-8

19-30 Windchill Customizer’s Guide


Customizing PSE Structure Queries

Objective
You want to customize the PSE New Query dialog to include soft types of
WTPart and allow queries to be created referencing IBA’s of the soft type.

Background
The dialog launched from the View->Query->New Query menu entry allows the
user to construct a query that will locate objects in the structure that match the
specified criteria. The out-of-the-box configuration allows specific attributes of
WTPart to be queried.

Customers will create their own soft types of WTPart with their own attributes. In
order to allow these to be used in the query, customization of the PSE XML files
is required.

Scope/Applicability/Assumptions
As these changes are being made to the PSE XML files, they will apply to all
users of PSE.

Intended Outcome
You may want to include the soft WTPart “myPart” in the searchable Types, and
allow the attributes “myCost” and “myDescription” to be queried. As “End Item”,

Customizing the Product Structure Explorer (PSE) 19-31


“Generic” and “Reference Designator” are not relevant to this type, these are
removed from the Property drop-down.

Solution
Add the appropriate element group in
<Windchill>/codebase/config/logicrepository/xml/explorer/structure
explorer/ExplorerSearchableTypes.xml

The element group will define CellDefinitions (both additions and removals) for
the AttributeGroup with id="ptc.wnc.exp.QuerySearchableAttrs " for the
“myPart” type.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• The management of XML file customizations

19-32 Windchill Customizer’s Guide


Solution Elements
Element Type Description

ExplorerSearchableTypes.xml XML file Holds the definition of types and attributes that
will be exposed in the New Query dialog.
Located in:
<Windchill>/codebase/config/logicreposi
tory/xml/structureexplore

LogicContext XML element Specifies the application and data type that the
definition is to be applied

AttributeGroup XML element PSE locates all the attribute groups with id
ptc.wnc.exp.QuerySearchableAttres, and uses
the type inheritance to find all the properties
(CellDefinitions) that will be displayed.

CellDefinition XML element The id of the property that will appear.

Placement remove=”true” XML element Remove=true is used to stop a property from


appearing due to inheritance.

Procedure
Edit the file ExplorerSearchableTypes.xml, before the final line
</LogicRepository> insert the following lines:
<!-- New Query definition for soft type myPart -->
<ExplorerElementGroup>
<LogicContext application="ptc.wnc.StructureExplorer"
dataType="com.aprilia.www.myPart"/>
<AttributeGroup id="ptc.wnc.exp.QuerySearchableAttrs" displayMode="view">
<!-- Remove the following that would otherwise be inherited from WTPart
Definition -->
<CellDefinition id="endItem">
<Placement remove="true"/>
</CellDefinition>
<CellDefinition id="genericType”>
<Placement remove="true"/>
</CellDefinition>
<CellDefinition id="referenceDesignator">
<Placement remove="true"/>
</CellDefinition>
<!-- Add the specific attributes of myPart -->
<CellDefinition id="myCost">
<AttributeDefinition attributeId="com.aprilia.www.myCost"/>
</CellDefinition>
<CellDefinition id="myDescription">
<AttributeDefinition attributeId="com.aprilia.www.myDescription"/>
</CellDefinition>
</AttributeGroup>
</ExplorerElementGroup>

Customizing the Product Structure Explorer (PSE) 19-33


After the method server is restarted, this results in “myPart” appearing in the Type
drop-down, with Property entries “End Item”, “Generic” and “Reference
Designator removed, and “myCost” and “myDescription” added, as shown in
Section Intended Outcome.
Alternatively, if the changes are to be made to other aspects of the PSE UI via
XML customization, these additional lines can be added to an XML file that holds
all the “myPart” customization.

Customization Points
It is valid to remove the WTPart definition from ExplorerSearchableTypes.xml,
so Part does not appear in the type drop-down. However, no definitions of the
properties will be inherited by the soft type definitions, so these will have to be
added.

Other Resources

Related Customization Documentation


• Managing Customizations chapter on page 5-1

19-34 Windchill Customizer’s Guide


Customizing Attribute Displays within Section Headings
You can control the display of attributes by customizing the SectionHeading tag.
This section contains the following topics:
• Customizing the Display of Attributes in Groups on page 19-35
• Expanding/Collapsing the Display Groupings on page 19-40
• Customizing the Number of Columns to Display on page 19-41

Customizing the Display of Attributes in Groups


There is a clause in the SectionHeading element that allows you to edit the detail
of a group of attributes. Using this clause you can hide or show specific attribute
from panels in the display, such as the Create Part Wizard, Insert Child Wizard, or
the Information Tab.
In the following sample code "allowAttrDetails=true" clauses have been added
to the SectionHeading element of the CreateChildPartTab2 attribute group that is
used by the Insert Child Wizard.
Sample Code:
<AttributeGroup id="ptc.wnc.exp.CreateChildPartTab2"
scrollable="true" displayMode="edit">
<SectionHeading allowAttrDetails="true">
<Label>
<Resource key="Properties Top"/>
</Label>
</SectionHeading>
<CellDefinition id="name">
<AttributeDefinition attributeId="name"/>
</CellDefinition>
<CellDefinition id="number">
<AttributeDefinition attributeId="number"

rendererClass="com.ptc.windchill.explorer.structureexplorer.render
er.component.PartNumberComponent"/>
</CellDefinition>
<SectionHeading allowAttrDetails="true">
<Label>
<Resource key="Properties 1"/>
</Label>
</SectionHeading>
<CellDefinition id="view">
<AttributeDefinition attributeId="view"

rendererClass="com.ptc.windchill.explorer.structureexplorer.render
er.component.ViewComponent"/>
</CellDefinition>
<CellDefinition id="folder">
<AttributeDefinition attributeId="folder"

rendererClass="com.ptc.windchill.explorer.structureexplorer.render
er.component.DefaultContainerFolderBrowserComponent"/>

Customizing the Product Structure Explorer (PSE) 19-35


</CellDefinition>
<CellDefinition id="source">
<AttributeDefinition attributeId="source"/>
</CellDefinition>
<CellDefinition id="partType">
<AttributeDefinition attributeId="partType"/>
</CellDefinition>
<SectionHeading allowAttrDetails="true">
<Label>
<Resource key="Properties 2"/>
</Label>
</SectionHeading>
<CellDefinition id="usedQuantityAmount">
<AttributeDefinition attributeId="usedQuantityAmount"/>
</CellDefinition>
<CellDefinition id="usedQuantityUnit">
<AttributeDefinition attributeId="usedQuantityUnit"/>
</CellDefinition>
<CellDefinition id="usedTraceCode">
<AttributeDefinition attributeId="usedTraceCode"/>
</CellDefinition>
<CellDefinition id="effPropagationStop">
<AttributeDefinition attributeId="effPropagationStop"/>
</CellDefinition>
<CellDefinition id="jobAuthorizationNumber">
<AttributeDefinition
attributeId="jobAuthorizationNumber"/>
<EnabledDependency inverted="false">
<Assembly assembly="wadm"/>
</EnabledDependency>
</CellDefinition>
<CellDefinition id="contractNumber">
<AttributeDefinition attributeId="contractNumber"/>
<EnabledDependency inverted="false">
<Assembly assembly="wadm"/>
</EnabledDependency>
</CellDefinition>
<CellDefinition id="phase">
<AttributeDefinition attributeId="phase"/>
<EnabledDependency inverted="false">
<Assembly assembly="wadm"/>
</EnabledDependency>
</CellDefinition>
</AttributeGroup>

Adding the "allowAttrDetails=true" clauses produces the following output in


the UI.
• Adding a SectionHeading creates the box around the group of attributes that
follow the SectionHeading.
• The Label clause of the SectionHeading gives the text for the box.

19-36 Windchill Customizer’s Guide


• The allowAttrDetails="true" clause enables the Details icon to show after the
label and also enables a popup menu for the panel.

Customizing the Product Structure Explorer (PSE) 19-37


This is the Details dialog that displays after you click the Details icon after the
label. The user can hide or show individual attributes, but cannot change the order
of the attributes.

For example, the user can choose to hide the Location attribute within the
Properties 1 section. This is now saved as a preference for this user and will stay
this way the next time the user loads PSE.

19-38 Windchill Customizer’s Guide


Customizing the Product Structure Explorer (PSE) 19-39
Expanding/Collapsing the Display Groupings
If multiple groups are displayed on a tab or in a step in a wizard, this could cause
the contents of the frame to scroll. This might be annoying to a user, especially if
they only want to enter the minimum number of attributes. You can customize the
Title to allow the user to expand/collapse the set of attributes displayed. This
setting will be remembered from session to session.
This is an example of what the UI might look like. The "Responsibilities" group is
collapsed, so the + icon is available to expand it. The "Production Data" group is
expanded so the - icon is available to collapse it.

Sample Code:
<AttributeGroup id="ptc.wnc.exp.CreateChild" displayMode="edit">
<SectionHeading id="ptc.wnc.exp.CreateChild.Responsibilities"
allowAttrDetails="true" allowCollapsable="true">
<Label>
<Resource key="responsibilitiesSectionLabel"/>
</Label>
</SectionHeading>

… cell definitions for the group here…

</AttributeGroup>

19-40 Windchill Customizer’s Guide


Customizing the Number of Columns to Display
You can customize the number of columns to display within the SectionHeading
tag. You can create layouts like the following example.

If you specify a SectionHeading before a group of attributes, those attributes will


be enclosed in a border with a title specified by the <Label> tag. See Customizing
the Display of Attributes in Groups on page 19-35 for more information on the
<Label> tag.
If the numberOfColumns is set to “1”, a single column of attributes will display; if
set to “2” two columns of attributes will display.
In the example screenshot above, URL0: is a single attribute that happens to have
two fields for input. Note that if any of the attribute in a section is required, the
label on the border is also marked as required.
Sample Code:
<AttributeGroup id="ptc.wnc.exp.CreatePartTab4"
scrollable="true" displayMode="edit">
<SectionHeading numberOfColumns="1">
<Label>
<Resource key="checkoutInfoStateLabel"/>
</Label>
</SectionHeading>
<CellDefinition id="String0">
<AttributeDefinition attributeId="IBA|String0"/>
</CellDefinition>
<CellDefinition id="URL0">
<AttributeDefinition attributeId="IBA|URL0"/>
</CellDefinition>

Customizing the Product Structure Explorer (PSE) 19-41


<SectionHeading numberOfColumns="2">
<Label>
<Resource key="serialNumberValueLabel"/>
</Label>
</SectionHeading>
<CellDefinition id="Boolean0">
<AttributeDefinition attributeId="IBA|Boolean0"
required="true"/>
</CellDefinition>
<CellDefinition id="Integer0">
<AttributeDefinition attributeId="IBA|Integer0"
required="true"/>
</CellDefinition>
<CellDefinition id="Real0">
<AttributeDefinition attributeId="IBA|Real0"/>
</CellDefinition>
<CellDefinition id="DateTime0">
<AttributeDefinition attributeId="IBA|DateTime0"/>
</CellDefinition>
</AttributeGroup>

19-42 Windchill Customizer’s Guide


Customizing Tabs - Configure Existing Tabs with Subtabs
This process consists of customizing the sub-tab and then changing the
Information tab that makes use of the customization.
To customize your XML to show sub-tabs, a <Tab> tag may now include a
<TabSet>. For example the Information Tab used to Import a Panel tag. Now it
includes a <TabSet> that contains four <Tab>s.
All the standard tab actions (hiding/showing tabs, moving tabs, pop-up menus,
and preferences that remember tab settings) are available for the main tabs are
also available for subtabs.
• The Identity tab displays thumbnail and read-only attributes.

• The Object Attributes tab shows only those attributes that are attached
directly to the selected part, not the link attributes.

Customizing the Product Structure Explorer (PSE) 19-43


• The Usage Attributes tab only shows the link attributes. Note that the tab is
not enabled when the top node is selected, because there is not a usage link so
there cannot be any link attributes.

The Classification tab is only visible if the PartsLink module is installed. It


displays all the classification attributes.

19-44 Windchill Customizer’s Guide


Allow Additional Steps During New Object Creation
The PSE create wizards are defined in ExplorerForTablesAndPanels.xml. The
"create new object" wizard is defined by the WizardList segment with the id of
ptc.wnc.exp.CreateWizardList and the "insert new child" wizard is defined by the
WizardList segment with the id of ptc.wnc.exp.CreateChildWizardList.
It is recommended that you customize these wizards in separate xml files rather
than editing ExplorerForTablesAndPanels.xml. The current steps allowed in the
WizardList are AttributeGroup and AttributeTable.
To add a new AttributeGroup or AttributeTable redefine the WizardList in your
customization file and include your new steps along with placements segments.
For example:
<WizardList id="ptc.wnc.exp.CreateChildWizardList">
<AttributeGroup id="ptc.custom.exp.CustomCreatePartTab2A">
<Placement insertKey="after"
insertId="ptc.wnc.exp.CreateChildPartTab2"/>
<CellDefinition id="endItem">
<AttributeDefinition attributeId="endItem"/>
</CellDefinition>
</AttributeGroup>
</WizardList>

The first line duplicates the id of the WizardList you want to modify. The second
line shows the addition of a new AttributeGroup inline, it could also be defined in
another place then imported here similar to the original WizardList definition.
The Placement segment indicates that your new AttributeGroup is to be shown
after CreateChildPartTab2.
You can also remove an AttributeGroup or AttributeTable from the original
WizardList that you don't want to use. For example, the following xml removes
the last step of the wizard (the AttributeTable that shows all the soft attributes):
<WizardList id="ptc.wnc.exp.CreateChildWizardList">
<AttributeTable id="ptc.wnc.exp.CreatePartTab3">
<Placement remove="true"/>
</AttributeTable>
</WizartList>

The ExplorerForTablesAndPanels.xml contains many good examples of how to


create AttributeGroups or AttributeTables. Within either of these segments,
define the list of CellDefinitions for each attribute you want to show.
You could also redefine the existing AttributeGroups or AttributeTables and add
or remove Celldefinitions using Placement segments. For example:
<AttributeGroup id="ptc.wnc.exp.CreatePartTab2">
<CellDefinition id="partType">
<AttributeDefinition attributeId="partType"/>
<Placement insertKey="before" insertId="endItem"/>
</CellDefinition>
<CellDefinition id="genericType">
<AttributeDefinition attributeId=" genericType"/>

Customizing the Product Structure Explorer (PSE) 19-45


<Placement remove="true"/>
</CellDefinition>
</AttributeGroup>

This example takes the existing AttributeGroup defined for the CreatePartTab2
step and adds the partType attribute before the endItem and removes the
genericType attribute. Note that CreatePartTab2 is imported into both the
CreateWizardList and the CreateChildWizardList so you will be modifying both
wizards.

19-46 Windchill Customizer’s Guide


Type Picker Display Customization
In the Explorer.dtd, the parameter hideSingleValueTypePicker has been added to
the <AttributeGroup> element, the default value is false. This flag controls
whether or not the Type Picker will be displayed if it has only one value in the list.
By default it will be displayed if it has only one value.
Customizing for a User Searching for an Existing Type
To configure this for situations where the user is searching for an existing type,
and the Type Picker is being populated with a list of Types to choose from, e.g.
File >> Open >> Part…
1. Locate the following XML file:
ExplorerForSearch.xml
ExplorerForSearchForSuma.xml

2. Locate the <ExplorerElementGroup> for which you want to configure this


setting. The dataType attribute of the <LogicContext> element will define the
Types this change will be effective for.
3. Locate the <AttributeGroup> element with
id=”ptc.wnc.exp.SearchCriteriaPanel”
4. Add the parameter hideIfListSizeIsOne with true/false value. E.g.:
<AttributeGroup id=”ptc.wnc.exp.SearchCriteriaPanel”
hideSingleValueTypePicker =”false”>

Note: This change will be effective for ALL instances of the GUI panel for
the Type defined in the <LogicContext> element.

Customizing for a User Creating a New Instance of a Type


To configure this for situations where the user is creating a new instance of a
Type, and the Type Picker is being populated with a list of Types to choose from,
e.g. File >> New >> Part…
1. Locate the following XML file:
ExplorerForTablesAndPanels.xml

2. Locate the <ExplorerElementGroup> for which you want to configure this


setting. The dataType attribute of the <LogicContext> element will define the
Types this change will be effective for.
3. Locate the <AttributeGroup> element with
id=”ptc.wnc.exp.CreatePartTab1”
4. Add the parameter hideIfListSizeIsOne with true/false value. E.g.:
<AttributeGroup id=” ptc.wnc.exp.CreatePartTab1”
hideSingleValueTypePicker =”false”>

Customizing the Product Structure Explorer (PSE) 19-47


Note: This change will be effective for ALL instances of the GUI panel for
the Type defined in the <LogicContext> element.

Note: Dropdowns in the Find In Structure dialog and Create/Edit Query


Wizard are not impacted by this change and will remain as they were.

19-48 Windchill Customizer’s Guide


Disabling Actions by Object Type
To disable an action in PSE by object type, follow these instructions:
1. Edit the ExplorerStructures.xml file.
Create a <TypeDefinition> element for the type(s) you will disable the
action(s) for. E.g. for the types org.my.MyTypeA , org.my.MyTypeB and
org.my.MyTypeD which are children of WTPart you would define the
following elements:
<TypeDefinition id="com.my.MyTypeATD"
typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeA"/>

<TypeDefinition id="com.my.MyTypeBTD"
typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeB"/>

<TypeDefinition id="com.my.MyTypeDTD"
typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeD"/>

2. Edit the ExplorerValidators.xml file.


Create a <ValidatorDefinition> element for the group of types you wish to
disable actions for. This will return false if the the type of the selected part
matches one of the types referenced in the validator definition. E.g. for the
three types above, you would define a validator as follows:
<ValidatorDefinition id="com.my.IsNotEqualToTypesABDVAL"
validatorClass="com.ptc.windchill.explorer.structureexplorer.va
lidators.IsValidTypeValidator" inverted="true">
<Import id="com.my.MyTypeATD"/>
<Import id="com.my.MyTypeBTD"/>
<Import id="com.my.MyTypeDTD"/>
</ValidatorDefinition>

Note: It is important that the value for the validatorClass attribute of


ValidatorDefinition be the exact class listed above, and that the the inverted
attribute be set to “true”.

3. Edit the ExplorerActions.xml file.


Add a <ValidatorEntry> element to the actions you wish to have disabled
for the specified types.
<ActionDefinition id="ptc.wnc.exp.EditCommonAttrsAction" ... >
...
<ValidatorEntry>
<Import id="com.my.IsNotEqualToTypesABDVAL"/>
</ValidatorEntry>
...
</ActionDefinition>

This configuration will disable the Edit Common Attributes action in the PSE
application whenever an part of type A, B or D is selected.

Customizing the Product Structure Explorer (PSE) 19-49


Validator isValidTypeValidator
The validator isValidTypeValidator is implemented by the class:
com.ptc.windchill.explorer.structureexplorer.validators.IsValidTypeValidator.
For a given set of type definitions, this validator will return ‘true’ if the type of the
currently selected part is in the aformentioned set. For example, if an instance of
this validator is defined with type definitions for types A, B and D. When a part
of type A, B or D is selected, the validator will return true. If a part of any other
type, e.g. C, is selected, it will return false.
A <ValidatorDefinition> which would return true if the selected type is A, B or D
would be defined in the following way:
<ValidatorDefinition id="com.my.IsEqualToOneOfTypesABDVAL"
validatorClass="com.ptc.windchill.explorer.structureexplorer.va
lidators.IsValidTypeValidator">
<Import id="com.my.MyTypeATD"/>
<Import id="com.my.MyTypeBTD"/>
<Import id="com.my.MyTypeDTD"/>
</ValidatorDefinition>

Conversely, a <ValidatorDefinition> which would return false if the selected type


is A, B or D would be defined in the following way (note the inclusion of the
‘inverted’ attribute):
<ValidatorDefinition id="com.my.IsNotEqualToTypesABDVAL"
validatorClass="com.ptc.windchill.explorer.structureexplorer.va
lidators.IsValidTypeValidator" inverted="true">
<Import id="com.my.MyTypeATD"/>
<Import id="com.my.MyTypeBTD"/>
<Import id="com.my.MyTypeDTD"/>
</ValidatorDefinition>

The <Import> elements refer to <TypeDefinition> elements which would be


defined as follows (assuming that each type is a direct child of WTPart):
<TypeDefinition id="com.my.MyTypeATD"
typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeA"/>

<TypeDefinition id="com.my.MyTypeBTD"
typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeB"/>

<TypeDefinition id="com.my.MyTypeDTD"
typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeD"/>

19-50 Windchill Customizer’s Guide


Creating a Requirements Tab
This section contains instructions for displaying a Requirements tab in PSE.
Following these instructions will create a Requirements tab which will be
displayed in PSE and will only be enabled when a part of a specified type is
selected in the structure tree. The tab will display the Requirement objects which
are associated with the selected object and provide some operations for working
with Requirements as well.
This documentation describes changes to existing files. It is suggested that you
create a separate customer file to contain all new elements created.
The following instructions are provided:
• Updating the <TabSet> element to include the Requirements tab on page
19-51
• Define a <Tab> element for the Requirements tab on page 19-52
• Define the <AssociationTable> element for the Requirements tab on page
19-53
• Define the <StructureAuthorDefinition> element for the association table on
page 19-53
• Define the <StructureDefinitionSimple> element for the part to requirement
association on page 19-54
• Define the <Table> element for the Requirement type on page 19-54
• Define the menus for the Requirements tab on page 19-56
• Define the labels, tool tips and mnemonics for the Requirements tab on page
19-59
• Define <ActionDefinition> elements referred to in the <MenuItem> elements
on page 19-60
• Implement an 'enabled decider' class to control when the tab is enabled on
page 19-62

Updating the <TabSet> element to include the Requirements tab


This will add a reference to a Requirements tab to the defined TabSet.
1. Open the PDMLinkExplorerMain.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc
tstructure

2. Locate the <TabSet> element and add an import for the new Requirements
tab, and place it in the desired location:
<TabSet id="ptc.pdm.pse.ExplorerTaskTabSet" tabPlacement="top"
tabIdWithFocus="ptc.wnc.exp.PropertiesTab">

Customizing the Product Structure Explorer (PSE) 19-51


<Import id="ptc.wnc.exp.PropertiesTab"/>
<Import id="ptc.wnc.exp.StructureChildrenTab"/>
<Import id="mycom.wnc.exp.RequirementsTab"/>
<Import id="ptc.wnc.exp.GpsParamTab"/>
<Import id="ptc.wnc.exp.GpsConstraintsTab"/>
<Import id="ptc.wnc.exp.ViewTab"/>
<Import id="ptc.wnc.exp.DocTab"/>
<Import id="ptc.wnc.exp.ReplacementsTab"/>
<Import id="ptc.wnc.exp.UsedByTab"/>
</TabSet>

Define a <Tab> element for the Requirements tab


This will define the Requirements tab element.
1. Open the PDMLinkExplorerMain.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc
tstructure

2. After the <TabSet> element, define a <Tab> element for the Requirements
tab:
<TabSet id="ptc.pdm.pse.ExplorerTaskTabSet" ... >
...
</TabSet>

<Tab id="mycom.wnc.exp.RequirementsTab"
tabClass="com.ptc.windchill.explorer.structureexplorer.explorer
.tabs.ShowTablesTab"
enabledDeciderClass="com.mycom.windchill.explorer.structureexpl
orer.deciders.RequirementsEnabledDecider">
<Label imageName="wtcore/images/change_action.gif">
<Resource key="requirementsTabLabel"/>
</Label>
<Panel>
<Import id="mycom.pdm.pse.RequirementAssocTable"/>
</Panel>
</Tab>

Note:

• The id attribute for the Tab element must match the id specified in the import
sub-element of the <TabSet> element defined above.
• The class defined for the enabledDeciderClass attribute of the Tab element,
controls what types this tab will be enabled for when parts are selected in the
structure tree. This must be implemented by the customer.
• The imageName attribute of the <Label> sub-element defines the icon to
display on the tab.
• The <Resource> sub-element of <Label> refers to the defined text label for
the tab.
• The <Panel> element contains an import to the defined table to be displayed.

19-52 Windchill Customizer’s Guide


Define the <AssociationTable> element for the Requirements tab
This will define the AssociationTable element used by the Requirements tab.
1. Open the PDMLinkExplorerMain.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc
tstructure

2. After the <Tab> element definition for the Requirements tab, define the
<AssociationTable> element.
<Tab id="mycom.wnc.exp.RequirementsTab" ... >
...
</Tab>

<AssociationTable
id="mycom.pdm.pse.mycom.pdm.pse.RequirementAssocTable">
<Label>
<Resource key="requirementsLabel"/>
</Label>
<Import id="mycom.wnc.exp.RequirementSAD"/>
<Import id="mycom.wnc.exp.ChangeActionTabTable"/>
<Import id="mycom.wnc.exp.ChangeActionAssocTableAA"/>
</AssociationTable>

Note:

– The id attribute for the <AssociationTable> must match the id specified in


the import sub-element of the <Tab> element defined above.
– The <Resource> sub-element of the <Label> element refers to the text
label defined in the resource file to be used for the table.

Define the <StructureAuthorDefinition> element for the association table


This defines the StructureAuthorDefinition element used by the AssociationTable.
1. Open the ExplorerStructures.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/struct
ureexplorer

2. Find the section in the file where the structure author definitions are defined.
After the last <StructureAuthorDefinition> element, add the following
definition for the Requirements:
<StructureAuthorDefinition id="mycom.wnc.exp.RequirementSAD">
<Import id="mycom.wnc.exp.PartToRequirementSD"/>
</StructureAuthorDefinition>

Note:

Customizing the Product Structure Explorer (PSE) 19-53


• The id attribute for the <StructureAuthorDefinition> must match the id
specified in the import sub-element of the <AssociationTable> element
defined above.

Define the <StructureDefinitionSimple> element for the part to requirement


association
This defines the StructureDefinitionSimple element used by the
StructureAuthorDefinition element.
1. Open the ExplorerStructures.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/struct
ureexplorer

2. Find the section in the file where the structure definitions are defined. After
the last <StructureDefinition> element, add the following definition:
<StructureDefinitionSimple
id="mycom.wnc.exp.PartToRequirementSD"
parentToChild="addressedPartMasterReference"
childDisplayId="number">
<Import id="ptc.wnc.exp.WTPartTD"/>
</StructureDefinitionSimple>

Note:

• The id attribute for the <StructureDefinitionSimple> must match the id


specified in the import sub-element of the <StructureAuthorDefinition>
element defined above.

Define the <Table> element for the Requirement type


This will define a table to display Requirements (Change Actions) associated with
the selected part in the Structure Tree. The following data will be displayed in
columns:
• The number of the Requirement
• The effectivity range of the Requirement
• The status of the Requirement
• The number of the ChangeDirective owning this requirement
• The identifier of the part which fulfills this Requirement
• The number of this Requirement's predecessor Requirement
To define the <Table> element for the Requirement type
1. Open the PDMLinkExplorerForTablesAndPanels.xml file from the
following location:

19-54 Windchill Customizer’s Guide


<Windchill>/codebase/config/logicrepository/xml/explorer/produc
tstructure

2. At the end of the file:


a. Create the following <ExplorerElementGroup> as a sub-element of the
<LogicRepository> element.
b. Define a <LogicContext> sub-element of the <ExplorerElementGroup>
with the data type of the Requirement.
c. Define the <Table> element and the columns, <CellDefinition> elements,
to be displayed in the table.
<LogicRepository>
...
<ExplorerElementGroup>
<LogicContext
application="ptc.pdm.ProductStructureExplorer"
dataType="wt.change2.ChangeAction"/>

<Table id="airbus.wnc.exp.ChangeActionTabTable"
selectionMode="multi-non-contiguous" displayMode="view">
<CellDefinition id="number" mandatory="true"
pinned="true">
<Label>
<Resource key="reqNumberLabel"/>
</Label>
<AttributeDefinition attributeId="number"/>
</CellDefinition>
<CellDefinition id="effVector" mandatory="true">
<Label>
<Resource key="reqValidityLabel"/>
</Label>
<AttributeDefinition
attributeId="displayEffectivity"/>
</CellDefinition>
<CellDefinition id="theActionState" mandatory="true">
<Label>
<Resource key="reqStatusLabel"/>
</Label>
<AttributeDefinition attributeId="theActionState"/>
</CellDefinition>
<CellDefinition id="owningChangeDirective"
mandatory="true">
<Label>
<Resource key="relatedCINLabel"/>
</Label>
<AttributeDefinition attributeId="MBA|
owningChangeDirectiveReference^WCTYPE|
wt.change2.WTChangeDirective~MBA|number"
rendererClass="com.ptc.windchill.explorer.structureexplorer.ren
derer.component.TypeIconifiedStringComponent"/>
</CellDefinition>
<CellDefinition id="satisfyPartMaster"
mandatory="true">

Customizing the Product Structure Explorer (PSE) 19-55


<Label>
<Resource key="fulfillingDSLabel"/>
</Label>
<AttributeDefinition attributeId="MBA|
satisfyPartMasterReference^WCTYPE|wt.part.WTPartMaster~MBA|
masterReference@WCTYPE|wt.part.WTPart~SCA|displayIdentifier"
rendererClass="com.ptc.windchill.explorer.structureexplorer.ren
derer.component.TypeIconifiedStringComponent"/>
</CellDefinition>
<CellDefinition id="oldActionReference"
displayWhenNoPreferenceSet="false">
<Label>
<Resource key="reqPredecessorLabel"/>
</Label>
<AttributeDefinition attributeId="MBA|
oldActionReference^WCTYPE|wt.change2.ChangeAction~MBA|number"
rendererClass="com.ptc.windchill.explorer.structureexplorer.ren
derer.component.TypeIconifiedStringComponent"/>
</CellDefinition>
</Table>
</ExplorerElementGroup>
</LogicRepository>

Note:

• The dataType attribute of the <LogicContext> element defines the type of


part which will be displayed in the table defined.
• The id attribute for the <Table> must match the id specified in the import sub-
element of the <AssociationTable> element defined above.
• The attributeId attribute of the <CellDefinition> element defines the qualified
attribute data to be displayed in that cell.
• The rendererClass attribute of the <CellDefinition> element is optional and
overrides the default renderer for the cell.
• The <Resource> sub-element of the <Label> element refers to the text label
defined in the resource file to be used for column header.

Define the menus for the Requirements tab


This will define the menus and toolbar for the Requirements tab. A toolbar will
be defined with the following structure:
• The standard Info button
• A Generate Requirements button. This button will trigger an action to
generate requirements for the currently selected part in the structure.
• A Fulfill Requirement button. This button will present the user with a list of
candidate parts from which to select and designate as fulfilling the currently
selected Requirement.

19-56 Windchill Customizer’s Guide


• A View Effectivity Log button. This button will open a browser window and
display the effectivity log for the currently selected Requirement.
• The standard Revert button
• The standard Comment button
• The standard Revert button
• The standard Comment button
Popup menus are also defined for the table which contain menu items for the three
new operations:
• Generate Requirements
• Fulfill Requirement
• View Effectivity Log
To define menus for the Requirements tab
1. Open the PDMLinkExplorerMenusForRequirementsTab.xml file from
the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc
tstructure

2. Add the following content to the file:

<?xml version="1.0" standalone="no" ?>


<!DOCTYPE LogicRepository SYSTEM
"/config/logicrepository/dtd/LogicRepository.dtd">
<LogicRepository>

<ExplorerElementGroup>
<LogicContext
application="ptc.pdm.ProductStructureExplorer"/>

<ActionAccess id="mycom.wnc.exp.ChangeActionAssocTableAA">
<MenuBar id="MenuBar">
<Menu id="Menu">
<Import id="ptc.wnc.exp.InfoPageAssocMI"/>
<Separator/>
<MenuItem id="GenerateReqsMI">
<Label
imageName="com/ptc/windchill/explorer/config/images/child_creat
e.gif">
<Resource key="generateReqsLabel"/>
</Label>
<ToolTip>
<Resource key="generateReqsToolTip"/>
</ToolTip>
<Import
id="mycom.wnc.exp.GenerateRequirementsAction"/>
</MenuItem>
<MenuItem id="FulfillReqMI">

Customizing the Product Structure Explorer (PSE) 19-57


<Label
imageName="com/ptc/windchill/explorer/config/images/child_add.g
if">
<Resource key="fulfillReqLabel"/>
</Label>
<ToolTip>
<Resource key="fulfillReqToolTip"/>
</ToolTip>
<Import
id="mycom.wnc.exp.FulfillRequirementAction"/>
</MenuItem>
<MenuItem id="ViewEffLogMI">
<Label
imageName="com/ptc/windchill/explorer/config/images/child_repor
t.gif">
<Resource key="viewEffLogLabel"/>
</Label>
<ToolTip>
<Resource key="viewEffLogToolTip"/>
</ToolTip>
<Import
id="mycom.wnc.exp.ViewEffectivityLogAction"/>
</MenuItem>
<Separator/>
<MenuItem id="RevertMI">
<Label
imageName="com/ptc/windchill/explorer/config/images/revert.gif"
>
<Resource key="revertLabel"/>
</Label>
<ToolTip>
<Resource key="revertToolTip"/>
</ToolTip>
<Import
id="ptc.wnc.exp.RevertForAltAssocAction"/>
</MenuItem>
<Import id="ptc.wnc.exp.CommentAssocMI"/>
</Menu>
</MenuBar>

<ModeToolBar id="ToolBarA">
<Import id="ptc.wnc.exp.EditAppMode"/>
<MenuItemIdentifier
id="ptc.wnc.exp.InfoPageAssocMI"/>
<Separator/>
<MenuItemIdentifier id="GenerateReqsMI"/>
<MenuItemIdentifier id="FulfillReqMI"/>
<MenuItemIdentifier id="ViewEffLogMI"/>
</ModeToolBar>

<ModeToolBar id="ToolBarB">
<Import id="ptc.wnc.exp.DraftAppMode"/>
<Import id="ptc.wnc.exp.AnnotateAppMode"/>
<Import id="ptc.wnc.exp.ReadOnlyAppMode"/>
<MenuItemIdentifier
id="ptc.wnc.exp.InfoPageAssocMI"/>
<Separator/>

19-58 Windchill Customizer’s Guide


<MenuItemIdentifier id="GenerateReqsMI"/>
<MenuItemIdentifier id="FulfillReqMI"/>
<MenuItemIdentifier id="ViewEffLogMI"/>
<Separator/>
<MenuItemIdentifier id="RevertMI"/>
<MenuItemIdentifier
id="ptc.wnc.exp.CommentAssocMI"/>
</ModeToolBar>

<ModePopupMenu id="PopupMenuA">
<Import id="ptc.wnc.exp.EditAppMode"/>
<MenuItemIdentifier id="GenerateReqsMI"/>
<MenuItemIdentifier id="FulfillReqMI"/>
<MenuItemIdentifier id="ViewEffLogMI"/>
</ModePopupMenu>

<ModePopupMenu id="PopupMenuB">
<Import id="ptc.wnc.exp.DraftAppMode"/>
<Import id="ptc.wnc.exp.AnnotateAppMode"/>
<MenuItemIdentifier id="GenerateReqsMI"/>
<MenuItemIdentifier id="FulfillReqMI"/>
<MenuItemIdentifier id="ViewEffLogMI"/>
<Separator/>
<MenuItemIdentifier id="RevertMI"/>
<MenuItemIdentifier
id="ptc.wnc.exp.CommentAssocMI"/>
</ModePopupMenu>
</ActionAccess>

</ExplorerElementGroup>

</LogicRepository>

Note:

• The id attribute for the <ActionAccess> element must match the id specified
in the import sub-element of the <AssociationTable> element defined above.
• The <Resource> sub-element of the <Label> and <Tooltip> elements refers to
the text label defined in the resource file to be used for column header.

Define the labels, tool tips and mnemonics for the Requirements tab
Define the text for the labels, tool tips and mnemonics used in the Requirements
tab.
1. Open the ConfigurationResource.rbInfo file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc
tstructure

2. Add the following to the end of the file:


#
# Tabbed Pane - Requirements
#

Customizing the Product Structure Explorer (PSE) 19-59


requirementsTabLabel.value=Requirements

# Change Item to Requirements table


requirementsLabel.value=Requirements
reqNumberLabel.value=Number
reqValidityLabel.value=Effectivity
reqStatusLabel.value=Status
relatedCINLabel.value=Originating From
fulfillingDSLabel.value=Fulfilled By
reqPredecessorLabel.value=Predecessor

generateReqsLabel.value=Generate Requirements
generateReqsToolTip.value=Generate Requirements

fulfillReqLabel.value=Fulfill Requirement
fulfillReqToolTip.value=Fulfill Requirement

viewEffLogLabel.value=View Effectivity Calculation Log


viewEffLogToolTip.value=View Effectivity Calculation Log

Note:

• The property name defined in the file, e.g. <property name>.value, must
match the key attribute of the <Resource> element in the XML configuration
files.

Define <ActionDefinition> elements referred to in the <MenuItem> elements


These are instructions for presenting the actions on the Requirements tab in PSE.
These instructions will provide an action to correspond with the menu and toolbar
item entries for the Fulfill Requirement action defined in the customization
instructions for setting up the Requirements Tab.
1. Open the PDMLinkExplorerActions.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc
tstructure

2. Locate the <ExplorerElementGroup> element with a sub-element


<LogicContext> with the application attribute value of
'ptc.pdm.ProductStructureExplorer'. The ActionDefinition elements will be
added after the LogicContext element.
3. Define the appropriate element using the steps found in the following
sections.

Define the ActionDefinition Element for the Fulfill Requirements Action


This will define the Action Definition element for the Fulfill Requirements action.
As detailed above, locate the <ExplorerElementGroup> element with a sub-
element <LogicContext> with the application attribute value of
'ptc.pdm.ProductStructureExplorer'. After the LogicContext element, add an
ActionDefinition element like the following:

19-60 Windchill Customizer’s Guide


<ActionDefinition id="mycom.wnc.exp.FulfillRequirementAction"

actionClass="com.ptc.windchill.explorer.structureexplorer.panel
.actions.FulfillChangeActionForStructureWithIntermediateNodeAct
ion">
<StructureAuthorAction>
<Import id="mycom.wnc.exp.PartToRequirementSD"/>
</StructureAuthorAction>
<Import id="ptc.wnc.exp.IsValidInAllWithReadVAL"/>
</ActionDefinition>

Note:

• The id attribute defined in the <ActionDefinition> must match the import id


defined for the FulfillReqMI menu item defined in
PDMLinkExplorerMenusForRequirementsTab.xml.
• The actionClass attribute will be defined based on the node structure for
Change Items and Design Solutions. If the set of Design Solutions are
immediately under the Change Item node, then the following class should be
specified:
com.ptc.windchill.explorer.structureexplorer.panel.actions.FulfillChangeActi
onAction. If the set of Design Solutions are located two levels down from
their Change Item node, then the following class should be specified:
com.ptc.windchill.explorer.structureexplorer.panel.actions.FulfillChangeActi
onForStructureWithIntermediateNodeAction.
• The import id in the <StructureAuthorAction> element must match the id of
the structure definition defined in the ExplorerStructures.xml file.
• All parts located at the level defined by the actionClass will be considered
potential Design Solutions for fulfillment and presented to the user in a
picklist.

Define the ActionDefinition Element for the Generate Change Actions Action
This will define the Action Definition element for the Generate Change Actions
action.
As detailed above, locate the <ExplorerElementGroup> element with a sub-
element <LogicContext> with the application attribute value of
'ptc.pdm.ProductStructureExplorer'. After the LogicContext element, add an
ActionDefinition element like the following:
<ActionDefinition id="mycom.wnc.exp.GenerateRequirementsAction"
actionClass="com.ptc.windchill.explorer.structureexplorer.panel
.actions.GenerateChangeActionsAction">
<Action/>
<Import id="ptc.wnc.exp.IsValidInAllVAL"/>
</ActionDefinition>

Customizing the Product Structure Explorer (PSE) 19-61


Note: The id attribute defined in the <ActionDefinition> must match the import
id defined for the GenerateReqsMI menu item defined in
PDMLinkExplorerMenusForRequirementsTab.xml.

Define the ActionDefinition Element for the View Effectivity Log Action
This will define the Action Definition element for the View Effectivity Log
action.
As detailed above, locate the <ExplorerElementGroup> element with a sub-
element <LogicContext> with the application attribute value of
'ptc.pdm.ProductStructureExplorer'. After the LogicContext element, add an
ActionDefinition element like the following:
<ActionDefinition id="mycom.wnc.exp.ViewEffectivityLogAction"
actionClass="com.ptc.windchill.explorer.structureexplorer.panel
.actions.AssociationUrlAction">
<UrlAction selectionMode="single"
urlBaseName="servlet/TypeBasedIncludeServlet?">
<UrlParameter value="oid={selected_oid}"/>
</UrlAction>
<Import id="ptc.wnc.exp.IsValidForHTMLLaunchMasterOkVAL"/>
</ActionDefinition>

The id attribute defined in the <ActionDefinition> must match the import id


defined for the ViewEffLogMI menu item defined in
PDMLinkExplorerMenusForRequirementsTab.xml.

Implement an 'enabled decider' class to control when the tab is enabled


This creates a new class which will control when the Requirements tab is enabled
and disabled. Only when a part is selected in the structure tree, which matches
one of the types specified in the enabled decider class, will the Requirements tab
be enabled and operational.
1. Create the RequirementsEnabledDecider.java file from the following
location:
<Windchill>/codebase/com/mycom/windchill/explorer/structureexpl
orer/deciders

2. Modify the following implementation as necessary:


– Modify the common_ancestry string so that it matches the parent type
hierarchy of the parts for which you want to view Requirements.
– In the static code block, add an entry to the type_id_list for each part type
which you want to view the Requirements
package
com.mycom.windchill.explorer.structureexplorer.deciders;

import java.util.ArrayList;
import java.util.List;

19-62 Windchill Customizer’s Guide


import
wt.services.applicationcontext.implementation.DefaultServicePro
vider;

import
com.ptc.core.foundation.struct.common.StructureConstants;
import com.ptc.core.meta.common.AssociationIdentifier;
import com.ptc.core.meta.common.AssociationTypeIdentifier;
import com.ptc.core.meta.common.AttributeTypeIdentifier;
import com.ptc.core.meta.common.IdentifierFactory;
import com.ptc.core.meta.common.TypeIdentifier;
import com.ptc.core.meta.common.TypeInstanceIdentifier;
import com.ptc.core.meta.type.common.TypeInstance;
import
com.ptc.windchill.explorer.structureexplorer.config.AbstractCon
fig;
import
com.ptc.windchill.explorer.structureexplorer.deciders.EnabledDe
cider;
import
com.ptc.windchill.explorer.structureexplorer.utility.CommonData
;

public class RequirementsEnabledDecider implements


EnabledDecider
{
private static IdentifierFactory identifierFactory =
(IdentifierFactory)
DefaultServiceProvider.getService(IdentifierFactory.class,
"logical"); //$NON-NLS-1$

private static List<TypeIdentifier> type_id_list = new


ArrayList<TypeIdentifier>();
private static String common_ancestry = "WCTYPE|
wt.part.WTPart|com.mycom.MyPart|"; //$NON-NLS-1$

static {
try
{
type_id_list.add(

(TypeIdentifier)identifierFactory.get(common_ancestry +
"com.mycom.CustomPartA")); //$NON-NLS-1$
type_id_list.add(

(TypeIdentifier)identifierFactory.get(common_ancestry +
"com.mycom.CustomPartB")); //$NON-NLS-1$
type_id_list.add(

(TypeIdentifier)identifierFactory.get(common_ancestry +
"com.mycom.CustomPartC")); //$NON-NLS-1$
type_id_list.add(

(TypeIdentifier)identifierFactory.get(common_ancestry +
"com.mycom.CustomPartD")); //$NON-NLS-1$
}
catch(Exception e)

Customizing the Product Structure Explorer (PSE) 19-63


{
e.printStackTrace();
}
}

public boolean isItemEnabled(TypeInstance node_ti,


TypeInstance parent_node_ti, AbstractConfig item_config,
CommonData common_data)
{
boolean enabled = true;

if (node_ti != null)
{
enabled = isValidPart(node_ti);
}

return enabled;
}

/**
* is this node a generic part or a configurable generic
part?
**/
public static boolean isValidPart(TypeInstance node_ti)
{
if (node_ti == null)
{
return false;
}
TypeInstanceIdentifier node_tii = (TypeInstanceIdentifier)
node_ti.getIdentifier();
if (node_tii == null)
{
return false;
}
try
{
if (IsMastered(node_ti))
{
return false;
}

TypeIdentifier type_id = trimTypeId((TypeIdentifier)


node_tii.getDefinitionIdentifier());

for(TypeIdentifier spec_type_id : type_id_list)


{
if(type_id.isDescendedFrom(spec_type_id))
{
return true;
}
}

return false;
}
catch (Exception e)

19-64 Windchill Customizer’s Guide


{
return false;
}
}

/**
* Assumes an iteration...
*
* isMastered is an unpersisted Iteration and a persisted
Master.
* @param ti
* @return
*
*/
private static boolean IsMastered(TypeInstance ti)
{
try
{
TypeInstanceIdentifier tii = (TypeInstanceIdentifier)
ti.getIdentifier();
if (tii instanceof AssociationIdentifier)
{
tii = ((AssociationIdentifier) tii).getTail();
}
if (!tii.isInitialized())
{
AttributeTypeIdentifier master_ati =
(AttributeTypeIdentifier)

identifierFactory.get(StructureConstants.MASTER_REFERENCE_ID_ST
R, tii.getDefinitionIdentifier());
Object object = ti.getSingle(master_ati);
TypeInstanceIdentifier master_tii = null;
if (object instanceof TypeInstanceIdentifier)
{
master_tii = (TypeInstanceIdentifier) object;
}
if (master_tii.isInitialized())
{
return true;
}
}
}
catch (Exception ex)
{
return false;
}

return false;
}

private static TypeIdentifier trimTypeId(TypeIdentifier


type_id)
{
if (type_id instanceof AssociationTypeIdentifier)
{

Customizing the Product Structure Explorer (PSE) 19-65


return ((AssociationTypeIdentifier) type_id).getTail();
}
return type_id;
}
}

19-66 Windchill Customizer’s Guide


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 Manager" 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/configurableLink
ExamplesResource.class
The .rbinfo file ties the registry of the 3rd level navigation table to the link type
that is implemented for the table, the table header, and the action title.
• %WT_HOME%/codebase/com/ptc/windchill/enterprise/ConfigurableLinkExam
ples.xconf
• %WT_HOME%/codebase/com/ptc/windchill/enterprise/ConfigurableLinkExam
ples-wt.properties.xconf

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 19-68 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:

Customizing the Product Structure Explorer (PSE) 19-67


xconfmanager -i
%WT_HOME%/codebase/com/ptc/windchill/enterprise/ConfigurableLin
kExamples.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 third-level navigation menus on


the info page 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/ConfigurableLinkExamples-actionmodels.xml
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.

19-68 Windchill Customizer’s Guide


Customizing Configurable Link Tables
This sectiom 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 2
sections:
• Configurable Link Soft Types: The first part defines the Configurable Link
Soft Types. The name, description and Logical Identifier for each link type
must be defined here. The nodeName that is defined here 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
19-71).
The following fields - nodeName, description, displayName,
heirarchyDisplayName, and logicalIdentifier must be filled-in 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 left-hand-side of
the link, and "Role B" is the object that constitutes the right-hand-side. The
linkType is the nodeName 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.
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 ConfigurableLinkExamples-actions.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 drop-
down menu. 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.

Customizing the Product Structure Explorer (PSE) 19-69


– 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 19-71). 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.
The relationship tables for configurable links should be defined in the 3rd
level navigation. steps 3a and 3b describe how to create a model, and then
display it. The end result is that the UI for the 3rd level navigation will have a
new menu option. The drop-down for this 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 resource bundle that
contains the key-value pairs of the display names (see Creating labels
for the table header and action title on page 19-71).
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 intended
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 3rd level
navigation of the info 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 3rd level navigation for these 2 objects, and this is described
below.
b. Displaying the model

19-70 Windchill Customizer’s Guide


The model "third_level_nav_part" contains the list of 3rd level navigation
menus available for parts. OOTB, this model is defined in PartManagement-
actionmodels.xml, and the menu options are "general", "relatedItems",
"history", "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.
The same steps in step 3b would have to be followed to display the new menu
option for configurable link tables in the 3rd level navigation menus of an info
page 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 a key-value pair in an rbinfo file. In the OOTB
example, this is done in the configurableLinkExamplesResource.rbinfo
file.
This file ties the registration of the 3rd level navigation table 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 "nodeName" 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
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
Depending on the table being registered - Role A (parent) or Role B (child)
(i.e., depending on the selector), the corresponding validator -
ConfigurableLinkParentTableActionValidator or

Customizing the Product Structure Explorer (PSE) 19-71


ConfigurableLinkChildTableActionValidator should be used respectively as
the serviceClass.
6. 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 6 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 PartManagement-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 7) 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 6, or placed before
the OOTB model definitions, then the OOTB behavior will be observed for
the specific 3rd level navigation menus.
7. Collecting the registrations in Steps 5 and 6 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.
This file references the files created in steps 5 and 6 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 19-67.

19-72 Windchill Customizer’s Guide


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

Customizing the Product Structure Explorer (PSE) 19-73


<grantPermissionSet>
<AccessPermissionSet>
<permissionField name="READ"/>
<permissionField name="MODIFY"/>
<permissionField name="CREATE"/>
<permissionField name="DELETE"/>
</AccessPermissionSet>
</grantPermissionSet>
</AccessControlRule>

19-74 Windchill Customizer’s Guide


20
Customizing Windchill
MPMLink

This chapter describes how to customize Windchill MPMLink.

Topic Page
Customizing Windchill MPMLink Overview...................................................20-2
General Windchill MPMLink Customizations..................................................20-5
Customizing the Process Plan Explorer ............................................................20-7
Customizing the Manufacturing Product Structure Explorer..........................20-23

20-1
Customizing Windchill MPMLink Overview
Windchill MPMLink is an add-on module to Windchill PDMLink and all
Windchill MPMLink explorers are built using the Product Structure Explorer
(PSE) infrastructure. Many of the customizations that can be done to Windchill
PDMLink, in particular customizations affecting the PSE, are propagated to
Windchill MPMLink. For more information on customizing Windchill PDMLink
and the PSE, refer to the relevant sections in this guide.
Additionally, many aspects of the way Windchill MPMLink appears and behaves
can be customized by using the Preferences Manager. Windchill MPMLink
preferences are located in the Product Structure Explorer section of the
Preferences Manager.
Any changes made to the XML configuration changes are applied when the
Method Server is restarted. To avoid having to restart the method server after each
configuration change activate the following property using Windchill Shell:
xconfmanager -d
com.ptc.windchill.explorer.monitorXmlConfigChanges=true -t
codebase/wt.properties

This property will automatically rebuild the jar that contains all XML
configurations. However you will need to restart your applet and clear your client
Java cache.
Any error in an XML file will prevent the jar from being built properly. To enable
logging in the Method Server console add the following line to the file codebase\
WEB-INF\log4jMethodServer.properties.
log4j.logger.com.ptc.core.logic.LogicRepository=DEBUG

Note: When moving to new versions of Windchill, changes in the XML files will
NOT be automatically migrated. Changes in these files should be clearly
documented. See Setting Up a Directory Structure for Managing Customized
Files and Text Tailoring in Chapter 5, "Managing Customizations" for more
detailed recommendations.

20-2 Windchill Customizer’s Guide


XML Configuration Files
Windchill MPMLink configuration files are located in the following directory:
codebase/config/logicrepository/xml/explorer
The following table lists the main Windchill MPMLink Explorer configuration
files. Additional configuration files pertaining to more specific customizations are
listed in various sections in this chapter.

File Description

<explorer>Main.xml Defines the general application layout


(tree, tabs)

<explorer>Structures.xml Defines the navigation model for the


application (tree hierarchy, selection
to tabs).

<explorer>Action*.xml Defines the actions.

<explorer>TablesAndPanels.xml Defines what are the visible attributes


in the tree, tables and on panels
(wizards).

<explorer>ForSearch.xml Defines the attributes that appear in


your search criteria as well as the ones
to display in your search results.

<explorer>MenuItems.xml Defines the different menu items and


their associated action.

<explorer>Menus/MenusFor*.xml Defines the menus and toolbars.

<explorer>Validators.xml Defines the different validators. A


validator is used to enable/disable
(grayed/not grayed) an action or a user
interface element.

Tip: The following files are the default files recommended for customizing
Windchill MPMLink. New customization files can be created provided these files
use the same application ID:

codebase\config\logicrepository\xml\explorer\customization

Customizing Windchill MPMLink 20-3


When creating customization files for a specific explorer it is recommended that
you use the following locations:
• CustAssociativeBOMExplorerMain.xml: The default file for
Manufacturing Product Structure Explorer customizations. You can use other
files, but the application ID for all XML segments must be:
ptc.cust.ProductStructureExplorer
• CustManufacturingStandardExplorerMain.xml: The default file for
Manufacturing Standards Explorer customizations. You can use other files
but the application ID for all XML segments must be:
ptc.cust.StandardExplorer
• CustMfgResourceExplorerMain.xml: The default file for Manufacturing
Resource Explorer customizations. You can use other files but the application
ID for all XML segments must be: ptc.cust.ResourceExplorer
• CustProcessPlanExplorerMain.xml: The default file for Process Plan
Explorer customizations. You can use other files but the application ID for all
XML segments must be: ptc.cust.ProcessPlanExplorer

20-4 Windchill Customizer’s Guide


General Windchill MPMLink Customizations
The following customizations describe typical changes you may want to apply to
Windchill MPMLink explorers.

Changing the Availability of Windchill MPMLink Explorers


When installed all Windchill MPMLink users have access to all explorers;
• Product Structure Explorer
• Manufacturing Product Structure Explorer
• Manufacturing Resource Explorer
• Manufacturing Standards Explorer
• Process Plan Explorer
• Manufacturing Gantt Explorer
In certain configurations you may want to limit access to an explorer. For
example, so that only manufacturing users can have access to the Manufacturing
Product Structure Explorer, with all other users having access to the Product
Structure Explorer.
To set this configuration at the Product or Library level navigate to the Team

tab and click the configure actions for roles icon.


To set this configuration at the Site or Organization level:
• Create a profile for manufacturing users, using the Profile tab,
• Add the individual users you wish to give access to the explorer to that
profile.

Changing Default Units of Measure


Windchill MPMLink objects are defined with a set of attributes for such things as
time, cost and dimension.
The default system of measurement is metric. To change this, for example to the
US system, modify the following preference using the Preference Manager:
Attribute Handling > Measurement System

To change the default unit for an individual attribute, such as time, cost or
dimension, use the Type and Attribute Manager.

Customizing Windchill MPMLink 20-5


• To change the base unit of measurement for a given system, for example to
change all times to minutes, use the Measurement System Manager tab.

• To change the default unit for a given attribute use the Attribute Definition
Manager tab. Navigate to the attribute you would like to change, and enter
the new value in the Override field.

20-6 Windchill Customizer’s Guide


Customizing the Process Plan Explorer
Process plans are the detailed description of what needs to be done on the shop
floor in order to produce, inspect, repair, or maintain a given part or assembly.
They contain the operations to be performed, the order in which they must be
done, the physical resources, plants and skills required, document references, text
description, and time and cost requirements.
Using Windchill MPMLink Process Plans you can define:
• The operations needed to carry out the manufacturing of a product.
• The sequences in which these operations are carried out.
• The time, costs, and constraints for each operation.
• The physical resources and skills required to carry out operations.
• The parts required to manufacture the product, as well as where and how they
are used during the manufacturing process.
In Windchill MPMLink Process plans are also used to create shop-floor Work
Instructions. Work instructions are the step by step instructions that are used on
the shop floor when producing, inspecting, repairing or maintaining parts. A work
instruction is a dynamically generated HTML document that combines process
plan information (sequences, operations, part allocations, resource allocations,
time, etc.) and all related documents such as drawings, images and 3D sessions
with annotations.

Creating Custom Formulas


A formula set is used to relate a set of attributes with the corresponding formulas
or equations that are to be used to calculate their value. The components that make
up a formula set are as follows:
• FormulaSet identifies the set
• FormulaMetaData defines the name and description for a Java formula
• FormulaValuatedLink relates an attribute name to a formula definition

Customizing Windchill MPMLink 20-7


The following graphic is an example of data that needs to be created in order to
add custom formulas:

The Formula Sets tab is used to select pre-defined formula sets that can be used
to calculate the time and cost associated with an operation. For example, a
standard time and cost formula set, and a periodic time and cost formula set.
These formula sets take into account the number of parts to be produced in the
operation and use the specifications defined for work center (For example, setup
time, queue time). Formulas and formula sets are used when the Calculate Time
and Cost action has been selected, and when you are loading process plans and
operations into the Manufacturing Gantt Explorer.
While multiple formula sets can be associated with a work center, one formula set
can be designated as the default formula set for the work center. It is this formula
set that is assigned to an operation when the work center is allocated to that
operation.

Note: Formulas must be assigned to a Formula set. If you do not have an existing
formula set, you must define one before you can define a custom formula. The
PSE can be customized to allow you to use the PSE to add additional values to
your customized formula sets. For more information, see the PSE documentation.

20-8 Windchill Customizer’s Guide


To create a custom formula, use the following procedure:
1. Using the LoadFromFile utility, load an XML-based load file where
<csvname> is unique to the system. This load file must contain all of the
following elements:
• csvFormulaSet - This creates a FormulaSet object.
• csvFormulaMetaData - This creates a FormulaMetaData object.
• csvAddFormulaMetaData - This links the FormulaMetaData to the
FormulaSet.
<csvFormulaSet
handler="com.ptc.windchill.mpml.formula.LoadFormula.createFormulaS
et">
<csvuser></csvuser>
<csvname>Standard Time and Cost</csvname>
<csvdescription>This formula Set is used to calculate the
time and cost of an Operation</csvdescription>
<csvfolder>/Default/Design</csvfolder>
<csvparentContainerPath></csvparentContainerPath>
<csvorganizationName></csvorganizationName>
</csvFormulaSet>

2. Create a formula metadata by linking to a java class name that implements


Formula interface and returns a calculated value. For example,
FloatingPointWithUnits.
Using the LoadFromFile utility, load and XML-based load file where
<csvname> is unique to the system and where <csvformulaClassName> is the
Java Class implementing formula interface.
<csvFormulaMetaData
handler="com.ptc.windchill.mpml.formula.LoadFormula.createFormu
laMetaData">
<csvuser></csvuser>
<csvname>StandardAttributeValueFormulaTime</csvname>
<csvdescription>Standard Attribaute Value
Formula</csvdescription>
<csvtype>time</csvtype>

<csvformulaClassName>com.ptc.windchill.mpml.formula.Standard
AttributeValueFormula</csvformulaClassName>
<csvfolder>/Default/Design</csvfolder>
<csvparentContainerPath></csvparentContainerPath>
<csvorganizationName></csvorganizationName>
<csvorganizationID></csvorganizationID>
</csvFormulaMetaData>

3. Link the formula metadata to the formula set by using an attribute name.
For example, when the service to calculate the formula is called, all the
formula metadata associated to the formula set will be executed and a map of
all calculated values will be returned using the attribute name as the key.

Customizing Windchill MPMLink 20-9


Using the LoadFromFile utility, load and XML-based load file where
<csvattributeName> is the time and cost IBA attribute on the MPMOperation
object.
<csvAddFormulaMetaData
handler="com.ptc.windchill.mpml.formula.LoadFormula.addFormulaM
etaDataToFormulaSet" >
<csvformulaSetName>Standard Time and
Cost</csvformulaSetName>
<csvformulaMetaDataName>StandardAttributeValueFormula
Time</csvformulaMetaDataName>
<csvattributeName>IBA|MPM_Attr_MPMOperationSetupTime
</csvattributeName>
</csvAddFormulaMetaData>

When creating a java class that implements Formula interface, these inputs are
accessible out-of-the-box in the inputs map.
• FormulaHelper.FORMULAVALUATED: the object on which the formula
set is linked and that casts to ForumlaValuated.
• FormulatHelper.FORMULAVALUATED_TI: the object type instance on
which the formula set is linked and that casts to TypeInstance. It can be null.
• FormulaHelper.FORMULAVALUATED_ATTRIBUTE_NAME: the
attribute name used to link the formula meta data to the formula set and that
casts to String. This will be used as the key in the results map.
• FormulaHelper.LOT: the lot value specified by the user in the context of the
Calculate Time and Cost action. It casts to Double.
The following is an example of a formula java class:
import com.ptc.core.meta.common.AttributeIdentifier;
import com.ptc.core.meta.common.AttributeTypeIdentifier;
import com.ptc.core.meta.common.TypeinstanceIdentifier;
import
com.ptc.core.meta.container.common.AttributeContainerSpec
import com.ptc.core.meta.server.TypeIdentifierUtility;
import com.ptc.core.meta.type.common.TypeInstance;
import com.ptc.core.meta.type.common.TypeInstanceFactory;
import com.ptc.windchill.mpml.MPMLinkHelper;
import java.text.NumberFormat;
import java.util.HashMap;
import wt.units.FloatingPointWithUnits;
import wt.util.WTContext;
import util.WTException;

public class StandardAttributeValueFormula implements


Formula{
private static final String RESOURCE =
"com.ptc.windchill.mpml.formula.formulaResource";
private static NumberFormat numberFormat =
NumberFormat.getInstance(WTContext.getContext().getLocale());
/** Creates a new instance of StandardAttributeValueFormula */
* This Formula simply return the value of the attribute.

20-10 Windchill Customizer’s Guide


public StandardAttributeValueFormula() {
}
public FloatingPointWithUnits calculate(HashMap inputs)throws
InvalidFormulaInputException, WTException{
//Get the object on which the formula is call
Object object = inputs.get(FormulaHelper.FORMULAVALUATED);
//Get the TI on which the formula is call
TypeInstance ti
=(TypeInstance)inputs.get(FormulaHelper.FORMULAVALUATED_TI);
//Get the attribute that is calculated by the formula
String attribute_name =
(String)inputs.get(FormulaHelper.FORMULAVALUATED_ATTRIBUTE_NAME);
if(object == null)
throw new InvalidFormulaInputException( RESOURCE,
formulaResource.REQUIRED_FORMULA_INPUT_MISSING, new
Object[]{FormulaHelper.FORMULAVALUATED} );;
TypeInstanceIdentifier tii = null;

//Get the TI of the object if null


if(ti==null){
tii =
TypeIdentifierUtility.getTypeInstanceIdentifier(object);
ti = TypeInstanceFactory.newTypeInstance(tii);
}else
tii = (TypeInstanceIdentifier)ti.getIdentifier();
//Get ATI for the attribute to calculate
AttributeTypeIdentifier ati =
(AttributeTypeIdentifier)MPMLinkHelper.getIdentifierFactory().get(
attribute_name,tii.getDefinitionIdentifier());
AttributeIdentifier[] ais = ti.getAttributeIdentifiers(ati);
//If the attribute value is not in the TI, update it to get the
value
if(ais.length<1){
AttributeContainerSpec fl = new AttributeContainerSpec();
fl.putEntry(ati);
ti = MPMLinkHelper.updateTypeInstance(new TypeInstance[]
{ti}, fl, null)[0];
ais = ti.getAttributeIdentifiers(ati);
}
//Get the attribute value
Object value = null;
if(ais.length>0)
value = ti.get(ais[0]);
//Return the value of the attribute if it’s a
FloatingPointWithUnits
if(value instanceof FloatingPointWithUnits)
return (FloatingPointWithUnits)value;
// value is null
return
FloatingPointWithUnits.valueOf(numberFormat.format(0));
}
}

Note: It is also possible to add more input to the formula by creating a new action
and then using formula services to call the execution of the formula set. For more
information on creating new actions, see the PSE documentation.

Customizing Windchill MPMLink 20-11


Changing Units of Measure for Cumulated Time and Cost
The Cumulated Time and Cost function of the Process Plan Explorer does not
use the Measurement System default units.
To change the units for the time & cost roll-up, the following properties must be
modified:
com.ptc.windchill.mpml.CumulatedTimeAndCostActionTimeUnit

com.ptc.windchill.mpml.CumulatedTimeAndCostActionCostUnit

These properties can be located in the following location:


codebase/com/ptc/windchill/mpml/xconf/mpmlin.properties.xconf

The default values are “min” and “$”, respectively.

Customizing Work Instructions


The work instruction template installed with Windchill MPMLink can be
customized to fit your needs. To customize work instructions you should have a
basic knowledge of JSPs and Info*Engine.
Info*Engine tasks are used to gather the information that is to be displayed in the
work instruction, while the JSPs are used to arrange and format the display of that
information.:

Location Description

<WT_Home>\codebase\netmarkets\jsp\ Location of the JSPs used in work


mpml instructions.

<WT_Home>\tasks\com\ptc\windchill\ Location of the Info*Engine tasks


mpml\workinstructions used to collect work instruction
data.

<WT_Home>\codebase\com\ptc\ Location of work instruction


windchill\mpml\xconfs\ properties.
mpmlink.properties.xconf

<WT_Home>codebase\ Location of the work instruction


netmarkets/css/workInstructionStyles.css style sheet. This file can be used to
change the fonts used in work
instructions, as well as the color of
report titles.

20-12 Windchill Customizer’s Guide


JSPs Used in Work Instructions
The following table lists and describes the JSPs used to configure work
instructions.

JSP Description

headerWorkInstruction.jsp Creates the logo image shown in the top


corner of the work instructions report. Right
next to the logo, it creates a table showing
information about the process plan for the
operations shown in the report. At the far
right, it creates the assembly table
information for which this process plan was
associated.

configSpecWorkInstruction.jsp Creates the configuration specification


table used in the work instructions report.
Three types of configuration specifications
are valid for this report: standard, baseline,
and effectivity. The values shown are the
ones for the expansion criteria that were
applied to the data when the work
instructions report was launched.

operationHeaderWorkInstruction Displays the information created in the


.jsp sequenceHeaderWorkInstruction.jsp in the
left margin. Creates the label number of the
operation or sub-operation and places it
next to the sequence number. Below the
label number, it creates a table showing the
name, number, version, and short
description of that operation.

operationDetailHeaderWorkInstr Creates the table below the operations


uction.jsp header. It shows details of the operation,
including work centers used, times and
costs.

Customizing Windchill MPMLink 20-13


JSP Description

operationDetailWorkInstruction. Creates the tables with the operation long


jsp description, its associated parts, its
allocated resources, and its associated
documents. If the value of the Displayed
column in the documents table is Yes, the
associated document is a recognized image
to be displayed in the work instructions
panel on the left of these detail tables.
Image files that can be shown in work
instructions must end with an extension
specified by the following property:
com.ptc.windchill.mpml.WorkInstruct
ionIllustrationFileExtensionAllowed

sequenceHeaderWorkInstruction When operations are part of a sequence, this


.jsp JSP creates links to the branching and
return operations. If the operation is a sub-
operation of another operation, this JSP
creates links to the parent operation.

footerWorkInstruction.jsp Creates the footer area shown at the end of


each operation section. This displays the
present state of the operation, its status, its
inspection, when it was first created, who
updated the operation last, and the last date
and time of the update.

coreWorkInstruction.jsp The core JSP that constructs the work


instructions report. Processes the URL
parameters and calls the Info*Engine tasks
used to gather the data related to the
operations found in a process plan. If the
JSP is launched from a process plan, it calls
processPlanLogicWorkInstruction.jsp

If launched from an operation it calls


operationLogicWorkInstruction.jsp

This JSP also computes the parent and child


relationship between operations, and the
sequence branching and return operations.
For each operation, it will call the JSPs that
create the tables and displays the data
returned by the Info*Engine tasks.

20-14 Windchill Customizer’s Guide


JSP Description

operationLogicWorkInstruction.j Launches Info*Engine tasks that find all


sp operations and standard procedures under
an operation. Operations are sorted by
operation label number. This JSP does not
display items in the report.

processPlanLogicWorkInstructio Launches Info*Engine tasks that find all


n.jsp operations, sequences, and standard
procedures under an operation. The
operations found are sorted by operation
label number. This JSP does not display
items in the report.

Info*Engine Tasks Used in Work Instructions


The following table lists and describes the Info*Engine tasks used to gather the
data used in work instructions.

Info*Engine Task Description

describeAttributes.xml Each webject in this task creates a group where


the values of the attributes are localized. These
localized values are then displayed in the work
instructions report.

Customizing Windchill MPMLink 20-15


Info*Engine Task Description

getOperationData.xml The webjects in this task query an operation for


the data that is displayed in the work
instructions report. The following data sets are
collected: work center, process, parts,
manufacturing capabilities, resources, and
documents. Each set of data is stored in an
Info*Engine group.

getOperationsAndStProcedur The webjects in this task create a group


esUnderAnOperation.xml containing all the first depth sub-operations
and standard procedures found under a
particular operation.

getProcessPlanAndAssembly The webjects in this task create a group


Information.xml containing information on the assembly
associated to the process plan.

getSequencesAndStProcedure The webjects in this task create a group


sUnderAProcessPlan.xml containing all the first depth sequences and
standard procedures found under a process
plan.

sortingOperations.xml The webjects in this task create a group


containing the sub-operations and standard
procedures found under a particular operation.
It also sorts the operations and standard
procedures in each level. Currently, the
algorithm is not recursive; it goes up to a depth
of 3 levels. That is, it will only find 3 levels of
sub-operations and then stop regardless if there
are more sub-operations. To get to deeper
levels, follow the pattern applied in this task
and add more levels accordingly.

sortingSequences.xml The webjects in this task create a group


containing the sub-sequences and standard
procedures found under a particular sequence.
It also sorts the sequences and standard
procedures in each level. Currently, the
algorithm is not recursive; it goes up to a depth
of 3 levels. That is, it will only find 3 levels of
sub-sequences and then stop regardless if there
are more sub-sequences. To get to deeper
levels, follow the pattern applied in this task
and add more levels accordingly.

20-16 Windchill Customizer’s Guide


Work Instruction Properties
The following table lists and describes the properties used to configure work
instructions.

Property Description

com.ptc.windchill.mpml.WorkInstruc Pattern that defines which


tionIllustrationNamePattern representations should be displayed in
work instructions. The name of the
ProductView representations meant to
be displayed in work instructions must
start with the pattern specified in this
property. The default is
wi_illustration.

com.ptc.windchill.mpml.WorkInstruc Property used in the URL of work


tionIllustrationPpValue instructions when the process plan
OID is not available. The default is
Value_Not_Considered.

com.ptc.windchill.mpml.WorkInstruc Date format used in the effectivity


tionEffectivityDateFormat configuration specification. The
default is mm/dd/yyyy.

com.ptc.windchill.mpml.WorkInstruc Configures the list of image extension


tionIllustrationFileExtensionAllowed types that can be seen in work
instructions. The default is
.jpeg,.png,.tif,.gif,.bmp,.jpg

Customizing Windchill MPMLink 20-17


Work Instruction Customizations
Work instructions can be customized for a number of reasons, including to replace
the header and logo with your own information, or to provide simpler work
instructions.
The following table lists some common work instruction customizations.

Customizations Description

To change the time units of an Modify the following JSP:


operation: timeUnit in
coreWorkInstruction.jsp

For example, to change from seconds


to minutes, change to m.

To change the time units for the steps Modify the following JSPs, as
in an operation: required:
setupTimeUnit

processingTimeUnit

laborTimeUnit

queueTimeUnit,

teardownTimeUnit,

waitTimeUnit,

moveTimeUnit

For example, to change from seconds


to minutes, change to m.

To relocate a table in the work Navigate to the end of the following


instruction: JSP:
coreWorkInstruction.jsp

Then re-design the HTML display.

20-18 Windchill Customizer’s Guide


Customizations Description

To display the processing cost of an Navigate to the following tasks:


operation in a work instruction:
• getOperationsAndStProceduresUnde
rAnOperation.xml
• sortingOperations.xml
Add the following attribute to the
above tasks:
MPM_Attr_MPMOperationProcessing
Cost

Then create the column and display


data in the following JSP:
operationDetailHeaderWorkInstru
ction.jsp

To change the font, size, or color of the Modify the following CSS file and the
titles in a work instruction: JSPs that use the definitions in the
CSS file:
workInstructionStyles.css

To change the logo at the top of the Use the following procedure:
work instruction, or in the operation xconfmanager -d
table:
com.ptc.windchill.mpml.WorkInst
ructionLogo=<logo> -t

codebase/wt.properties

where <logo> is the full path to the


logo .gif file found in the following
folder:
codebase\netmarkets\jsp\mpml.
The default value is:
../../images/ptcLogo_workInstructions
.gif corresponding to folder codebase\
netmarkets\images

To add an image extension type: Add the extension type to the


following property:
com.ptc.windchill.mpml.WorkInst
ructionIllustrationFileExtensio
nAllowed

To re-arrange, remove, or add new Modify the following JSP:


tables: coreWorkInstructions.jsp

Customizing Windchill MPMLink 20-19


Customizing a Windchill MPMLink Explorer
Use the following procedures to customize Windchill MPMLink Explorers. This
procedure introduces new XML fragments that modify the default behavior of an
explorer.

Adding Custom Attributes to a Creation Wizard


Use the following procedure to add additional attributes to a creation wizard, such
as the Insert New Operation wizard:
1. Navigate to the following directory:
codebase\config\logicrepository\xml\explorer\customization

2. Edit the following file:


CustProcessPlanExplorerMain.xml

3. Add the following XML fragments:

Note: In this example inspectionNeeded and inspectionInterval are the


attributes that are being added to the Insert New Operation wizard. Modify
the code to suit the wizard you would like to customize, and to add your own
customized attributes.

<ExplorerElementGroup>
<LogicContext application="ptc.cust.ProcessPlanExplorer"

20-20 Windchill Customizer’s Guide


dataType="com.ptc.windchill.mpml.processplan.operation.MPMOpera
tion"/>
<AttributeGroup id="ptc.mpm.exp.CreateTab2"
scrollable="true" displayMode="edit">
<CellDefinition id="inspectionNeeded">
<Label>
<Resource key="inspectionNeededLabel"/>
</Label>
<AttributeDefinition
attributeId="inspectionNeeded"/>
</CellDefinition>
<CellDefinition id="inspectionInterval">
<Label>
<Resource key="inspectionIntervalLabel"/>
</Label>
<AttributeDefinition
attributeId="inspectionInterval"/>
</CellDefinition>
</AttributeGroup>
</ExplorerElementGroup>

4. Clear your Java cache and restart the Process Plan Explorer.
In this example note that:
• The application ID used for this XML fragment is
ptc.cust.ProcessPlanExplorer. This is the one recommended application ID
for customizing the Process Plan Explorer.
• The default second creation wizard for the MPMOperation object,
ptc.mpm.exp.CreateTab2, is defined in:
• codebase\config\logicrepository\xml\explorer\mpmexplorer\
MPMExplorerForTablesAndPanels.xml.
• To add more attributes to the same creation wizard, the same AttributeGroup
ID, ptc.mpm.exp.CreateTab2, must be used.
• Only the cell definitions for the new attributes are added in this XML
segment.

Tip: By default cell definitions need to be added after the default cell definitions.
To specify a different location use the Placement tag.

<Placement insertKey="after|before"
insertId="attributeName"replace="true|false"/>

For example:
<CellDefinition id="inspectionNeeded">
<Label>
<Resource key="inspectionNeededLabel"/>
</Label>
<AttributeDefinition
attributeId="inspectionNeeded"/>
<Placement insertKey="after" insertId="folder"/>

Customizing Windchill MPMLink 20-21


</CellDefinition>

Note: Folder is the ID of the attribute after which the inspectionNeeded


attribute is added.

Changing Operation Numbering


Windchill MPMLink numbers operations in sequential increments of 10. For
example operation 10, operation 20, and so on. However, you may wish to
configure your operations so that automatically increment by a different
numbering scheme.
To change the numbering scheme modify the following properties:
• wt.operationLabelIncrement
• wt.operationLabelNumberOfCharacters
For example, to have operation labels with three characters and which are
increased by 5 (005, 010), put the following in site.xconf, and then run
xconfmanager -pF:
• <Property name="wt.operationLabelIncrement" overridable="true"
targetFile="codebase/wt.properties" value="5"/>
• <Property name="wt.operationLabelNumberOfCharacters"
overridable="true" targetFile="codebase/wt.properties" value="3"/>

20-22 Windchill Customizer’s Guide


Customizing the Manufacturing Product Structure Explorer
The primary deliverables for a design engineer are product specifications and an
engineering bill of materials (eBOM), typically accompanied by 3D digital mock-
ups. These specifications, along with the eBOM, outline the initial design
concepts for a product.
Using the eBOM and the digital mock-ups, manufacturing engineers establish
strategies on how to build a product that satisfies these engineering specifications.
Manufacturing engineers re-organize and re-structure the eBOM into a
manufacturing bill of materials (mBOM) that outlines the product from a
manufacturing process and strategy point of view.
Use the Manufacturing Product Structure Explorer to define manufacturing
product structures. The Manufacturing Product Structure Explorer is also used to
manage manufacturing parts, and the associations between different BOMs, when
transforming an engineering bill of materials into a manufacturing bill of
materials, and to manage the associations between parts and process plans.

Customizing the Transforming of an eBOM into an mBOM


Transforming an engineering bill of materials (eBOM) into a manufacturing bill
of materials (mBOM) is a key component of the manufacturing process. Typically
the as-designed, or engineering view of how a product is manufactured differs
from the as-planned, or manufacturing view of how the product is actually built.
Windchill MPMLink allows both design and manufacturing engineers to not only
modify their respective bill of materials, but to maintain links between the two.
This ensures that any changes made to the design of a product are immediately
communicated to the manufacturing engineers, and the impact of such changes
are immediately known.

Copying Part Attributes from the eBOM to the mBOM


When transforming an eBOM into an mBOM it is possible to customize
Windchill MPMLink so that the attributes, soft type attributes (IBAs) and
associations of the eBOM part are automatically copied over to the mBOM part
when performing a BOM transformation. This scenario could arise when;
• Copying the attributes from an upstream part master to a downstream child
part master;
• Copying the attributes and associations from an upstream iteration of a part to
a downstream part.

Tip: For more information and examples refer to the comments in the property
file.

Customizing Windchill MPMLink 20-23


Use the following procedure to copy part attributes from the eBOM to the
mBOM:
1. Navigate to the following directory:
\codebase\com\ptc\windchill\mpml\xconfs\
mpmlink.properties.xconfs

2. Search for the following property:


com.ptc.windchill.mpml.copyOver

3. Update the property as in the following example:


<Property name="com.ptc.windchill.mpml.copyOver.<create or
update>.wt.part.WTPartMaster" default="WCTYPE|wt.part.<WTPart
or WTPartMaster>~MBA|<attribute>"/>

Where:
– <create or update> defines whether part attributes are copied over at the
creation of the equivalent link for the downstream part (create), or when
the equivalent link of the downstream part is updated (update). If
<create> is used alone there is no synchronization between the upstream
and downstream parts. To create a scenario where upstream and
downstream parts are synchronized update the property to include both
<create> and <update> options.
– <WTPart or WTPartMaster> defines whether the copied attributes are
from the upstream iteration of the part (WTPart) or from the upstream
part master (WTPartMaster).
– <attribute> is the attribute to be copied over during BOM transformation.

Tip: To keep the copied attributes specific to a product update the property
must include the product library container. For example:

<Property name="com.ptc.windchill.mpml.copyOver.<create or
update>.wt.part.WTPartMaster.<PDMLinkProduct.Product1>"
default="WCTYPE|wt.part.<WTPart or WTPartMaster>~MBA|
defaultUnit"/>

Where:
– <PDMLinkProduct.Product1> is the name of the product container.

Note: To copy over multiple soft attributes, or attributes that are sub-classes of
other attributes, you must include the full path to the attributes you want to copy
over, using the delimiter specified in the following property:

<Property name="com.ptc.windchill.mpml.copyOverDelimeter"
default=","/>

20-24 Windchill Customizer’s Guide


Defining Rules for the Add Children from Upstream BOM Window
When transforming an eBOM into an mBOM using the paste with associative
links preference the following window appears:

Windchill MPMLink can be customized so that this window is automatically


populated with certain options if a predefined set of rules has been met. This is
done using a Windchill MPMLink delegate.
For example, Windchill MPMLink is configured by default to populate the Add
Options field with Add Selected Part if the copied upstream part has a Source
value defined as Buy.
Use the following procedure to change this behavior, or to add additional
customizations:
1. Navigate to the following directory:
\codebase\com\ptc\windchill\mpml\xconfs\
mpmlink.properties.xconfs

2. Search for the following property:


mpmlink.typedservices.properties.xconf

3. Search for:
<Option cardinality="singleton" requestor="WCTYPE|
wt.associativity.EquivalenceLink"
serviceClass="com.ptc.windchill.mpml.MPMCopyOverEquivalenceLink
Delegate"/>

4. Substitute
"com.ptc.windchill.mpml.MPMCopyOverEquivalenceLinkDelegate" with
the name of the class that implements the new behavior. Or modify the class
itself to change the behavior.

Customizing Windchill MPMLink 20-25


20-26 Windchill Customizer’s Guide
21
Customizing Search
Functionality

This chapter describes how to customize various aspects of the search


functionality.

Topic Page
Customizing Index Search Capabilities ............................................................21-2
Customizing Indexing Behavior........................................................................21-6
Windchill Client Architecture Search Customization .....................................21-11
Search Elements and Associated JSPs ............................................................21-17

21-1
Customizing Index Search Capabilities
There is support for creating a new Customized search application with Index.
The Indexed-Search webject queries the indexing engine for the indexed content
of Windchill objects if Index Search is installed. It accepts a 'keyword' String as
input and returns XML formatted results (see below). It includes the ufid(obid),
the object class, a rank, and a teaser for every associated contentItem for that
object. It also may include one or more spelling suggestions.
<wc:COLLECTION xmlns:wc="http://www.ptc.com/infoengine/1.0">
- <wt.fc.WTObject NAME="output" TYPE="Unknown" STATUS="0">
<wc:INSTANCE />
- <wc:INSTANCE>
<obid>VR:wt.doc.WTDocument:22052</obid>
<class>wt.doc.WTDocument</class>
<teaser>Basketball rules Basics Goal is to shoot the ball into a
basket (10' high) to score points. A basic shot counts as 2 points,
and shots from the three point line count as 3 points and free
throws count as 1 point.</teaser>
<rank>1997</rank>
<contentItem>OR:wt.content.ApplicationData:22059|1898|Basketball
rules Basics Goal is to shoot the ball into a basket (10' high) to
score points. A basic shot counts as 2 points, and shots from the
three point line count as 3 points and free throws count as 1
point.</contentItem>
</wc:INSTANCE>
<wc:INSTANCE>
<suggest>wrong</suggest>
</wc:INSTANCE>
</wt.fc.WTObject>
</wc:COLLECTION>

Input Parameters to the Index-Search Webject

SESSION_ID
Session identifier with all tasks
TYPE
Specifies the set of Windchill Business Types to constrain the search. This
would be wt.part.WTPart, wt.doc.WTDocument, etc.
WHERE
If specified, the indexing tool will attempt to filter results based on the
whereClause.
KEYWORD
Specifies a query expression identifying the keyword string to be sent to
Index Search.
LIBRARIES
Specifies the set of Index Search libraries (collections) to search for the
keyword.

21-2 Windchill Customizer’s Guide


FETCH_FIELDS
Specifies a set of fields that are stored in Index Search to be retrieved as part
of the query. The default fields that will always be requested is the ufid, which
is used by Search-Objects to retrieve the results from the Indexed-Search
from Windchill.
SORTBY
Specifies a set of attributes that are both specified to be returned by the query
and that have sorting preferences defined. Multiple values can be specified for
this parameter. If multiple values are specified, then the first value is the
primary sort attribute, the second value is the secondary sort attribute, and so
on. This parameter is optional.
SORTED
Specifies whether the current attribute to sort by should be sorted as
descending or ascending. The default for this parameter is descending. This
parameter is optional.
FILTER_ACCESS
When set the indexing engine will use a filter the result set to a 'Potential' read
list.
SPELL_CHECK
If set to true, then Indexing Engine will attempt to validate spelling and
suggest possible query terms.
TYPE_CONTAINER
Determines the set of base types to be used in the search from the incoming
type parameter.
QUERY_TYPE
Determines the type of query to perform, Simple or Advanced. A Simple
query sends the keyword to Index Search as a keyword only. An Advanced
query sends the keyword as an Index Search query, so it must have valid
syntax for an Index Search query. See the Instream SDK Query Language
Parameters Guide for valid Index Search query syntax.
MAX_DOCS
Determines the maximum amount of documents to return from index search.
MIN_HITS
This parameter is ignored.
CONTAINER_REF
Filters the search results to those objects within the container reference.
INSTANCE
Specifies the name of the Windchill adapter. You can define the adapter name
when you configure the adapter on the Info*Engine Property Administrator
service form. This parameter is required.

Customizing Search Functionality 21-3


COMPONENT_ID
Specifies which client component is invoking the search. This parameter is
used to select the list of classes to query against as defined in
com/ptc/windchill/enterprise/search/server/SearchableTypes.properties.
SEARCH_IN_USER_ORG
Search only in containers (contexts) belonging to principal's org.
AND_OR_OPERATOR
Determines if the Index Search query uses SIMPLEANY (OR) or
SIMPLEALL (AND).
ATTRIBUTE_TYPE_CONTEXT
Filters the search results by attribute type.
UNFORMATTED
This parameter is ignored.
GROUP_OUT
Specifies the name of the output group containing the results. If this
parameter is omitted the name of the output group is constructed by
appending the string "-Output" to the webject name. This parameter is
optional.
The resulting group is not access controlled, but can then be used to query
Windchill for the appropriate objects, to include access control. The group could
be combined with other criteria as well to perform a more specific search. Please
see the Windchill Adapter Guide for more information around setting up Search-
Objects and Query-Objects webjects.

Sorting IndexSearch Search Results


You can sort the results returned by IndexSearch when invoked through the
Indexed-Search webject.
To accomplish this, customize the task search-IndexSearch.xml (in
<Windchill>/tasks/com/ptc/windchill/enterprise/search/).
If they do not already exist, add two parameters to this task as follows:
<ie:param name="SORTBY" data="sortBy"/>
<ie:param name="SORTED" data="sorted"/>

These two are optional parameters. The default values are "sortBy" and "sorted",
respectively. If the parameters are not present, or if the default values are used, no
sorting is done.
To specify the fields to sort by, set the SORTBY parameter value to any of the
fields defined for the particular library.
The default library (collection) provided in Windchill is wblib; the list of fields
(for example, "name", "number", "title") is shown in the IndexSearch

21-4 Windchill Customizer’s Guide


Administration UI, on the Search page. To view all available fields, check the
"Show All Fields" checkbox in Advanced Controls.
If you specify a value in SORTBY that is not a default and does not match any of
the library fields, then it is ignored and no sorting will be done.
The SORTBY parameter is a case sensitive field. Hence for sorting the results
based on number, and in ascending order, the parameters to add would be:
<ie:param name="SORTBY" data="number"/>
<ie:param name="SORTED" data="ascending"/>

You can give multiple fields and their corresponding sort orders by space
separated values. For example:
<ie:param name="SORTBY" data="name number"/>
<ie:param name="SORTED" data="asc"/>

This would sort the results first on name and then number.
For further information on the Indexed-Search webject, see the Windchill Adapter
Guide.

Customizing Search Functionality 21-5


Customizing Indexing Behavior
You can modify the information stored in the search engine’s index that is
associated with a Windchill business object either by extending the
wt.index.InstreamIndexDelegate class and providing customized behavior, or by
simply using xconfmanager to update the wt.index.Index.Fields property in
<Windchill>/codebase/wt.properties.
The default InstreamIndexDelegate indexes every attribute, every soft attribute,
the identity of every object reference connected with the business object (that is,
the owner), the text of content files, and the links and descriptions of attached
URLs. You most likely need to modify the behavior of the
wt.index.InstreamIndexDelegate if your site has a customized object with a
particular attribute that you want to appear in its own field in the search engine’s
index. If this field is a modeled attribute, then simply adding it to the
wt.index.IndexFields property would suffice.
The following sections describe the predefined Index Search fields supplied with
Windchill and how to add the capability to index data into new fields.

IndexSearch Fields
In addition to the full text index of object metadata and content files, text can be
indexed into specific IndexSearch fields. When text is indexed into fields, it is
possible to restrict, or filter, query responses by entering search terms in data
fields, such as title, number, date, and so on. These queries can be used in
combination with a full text query or used alone to limit the types of documents
returned. Windchill provides a Index Search Profile configured with the fields in
the table below.
If you want a library to contain additional fields, you must add those fields to the
profile before data is indexed into the library. Refer to the Index Profile Features
Management section of the InStream Configuration Guide for further information
on setting up library fields. After the fields have been defined for the library, you
can write a custom InstreamIndexDelegate subclass to populate the new fields
with the appropriate data, or you can simply append them onto the following
property in wt.properties:
wt.index.IndexFields=
name,lifeCycleState,description,number,title,containerReference,modifyTimestamp

Notice that some attributes are indexed automatically and cannot be overridden.

Field Description Required

businesstype This is the actual type of the object, it Yes


is used internally to filter queries in a
more performant manner.

21-6 Windchill Customizer’s Guide


Field Description Required

iscontent This is a flag to indicate if an index Yes


entry represents content or not. Could
be used to filter by content vs
metadata.

ufid This is the id of the ContentItem that is Yes


actually indexed. This is used as a
way to keep track of multiple indexed
items with one Windchill Object.

name The name of the indexed object. No

number The number of the indexed object. No

metadata This field contains all of the Yes


miscellaneous attributes for an object
that are not defined in any other field.

lifecyclestate The lifecycleState of the object (In No


Work, Released, etc)

containerreference The object reference of the container No


the object belongs to.

modifytimestamp The last modified stamp of the object No

createtimestamp The created timestamp of the object. No

ibas This is a field that represents all of the Yes


soft attributes associated with an
object.

Note: The name of the field comes


from the fact that soft attributes have
sometimes been referred to as
instance-based attributes (IBAs).

organizationreference The object reference of the


organization the object belongs to.

Creating a Custom InstreamIndexDelegate


The default InstreamIndexDelegate implementation indexes all object metadata
and any soft attributes associated to the current object. Creating a custom
InstreamIndexDelegate object is appropriate if you know which fields you want
indexed for an object and you only want those fields indexed. This is the primary
reason for creating a custom InstreamIndexDelegate. A custom
InstreamIndexDelegate could theoretically improve indexing performance

Customizing Search Functionality 21-7


because fewer attributes would need to be processed and written to IndexSearch
but this should be a secondary consideration when determining if creating a
custom InstreamIndexDelegate is appropriate.
To create a custom InstreamIndexDelegate, use Rational Rose to model your new
class, making it extend the InstreamIndexDelegate class. Then generate the Java
code and provide implementations for the following method signatures:
public void custom_getAdditionalMetaData( Indexable indexable,
IndexingObject indexingObject )

throws WTException, IndexingException {

public void custom_getAdditionalFieldData( Indexable


indexable, IndexingObject indexingObject )

throws WTException, IndexingException {

These methods do nothing in the base class, so anything added will be additional
functionality for the indexing system. There are examples below on how to call
specific methods to write customized fields, or specify additional metadata on an
indexed object.
To put your custom InstreamIndexDelegate into action, you must update the
service.properties file to reflect this change. Following is the default
InstreamIndexDelegate entry:
# #####################################################
# The wt.index.IndexServiceDelegate service.
# ###########################################################
wt.services/svc/default/wt.index.IndexServiceDelegate/null/
wt.index.Indexable/0=wt.index.InstreamIndexDelegate/duplicate

As part of the changes introduced in 8.0, the ability to subclass the delegate by
type is no longer supported. However, this functionality can easily be reproduced
by logic in a customer IndexServiceDelegate. Also, the ability to define a
delegate for a single library is no longer supported either, but fields that are not
defined in a particular library are ignored, so sending additional information to
IndexSearch is not an issue.
For this example, assume that you have a custom InstreamIndexDelegate named
InstreamSubClassIndexDelegate that you want to use to index. If you want to
override the default InstreamIndexDelegate you must add the following line to
service.properties:
wt.services/svc/default/wt.index.IndexServiceDelegate
/null/wt.index.Indexable/0=
wt.index.InstreamSubClassIndexDelegate/duplicate

(Note that you should actually enter only one line; the indentation shown here
indicates a continuation of the preceding line, necessary for presentation of lines
within the book.)

21-8 Windchill Customizer’s Guide


Overriding the custom_getAdditionalFieldData custom_getFieldData() Method
Overwrite the custom_getAdditionalFieldData( Indexable indexable,
IndexingObject indexingObject ) method and add your specific code into this
method. See below for a very simple example. There are two methods in
IndexingObject parameter that can be used to send information to Index Search.
The first is the appendMetadataField method which allows you to add
information to the meta data field in Index Search. The second is the
appendSearchField method, which will add an indexed search field of a specified
type you would like to index with the object.
*********EXAMPLE***********
package wt.index;

import wt.index.InstreamIndexDelegate;
import wt.index.IndexingException;
import wt.util.WTException;

public class InstreamSubClassIndexDelegate extends


InstreamIndexDelegate {

/**
* This method can be used to provide customized fields to be
indexed
* in your Indexing engine.
**/

public void custom_getAdditionalFieldData( Indexable indexable,


IndexingObject indexingObject )
throws WTException, IndexingException {

String newField = "myValue";

//this will add meta data to the index


indexingObject.appendMetadataField("MyNewMetadata");

//This will add the a new search field to the index


indexingObject.appendSearchField ("MetaData", newField,
"string");

********EXAMPLE**********

Customizing Search Functionality 21-9


IndexingObject Method Reference
Following are IndexingObject methods that are applicable to customizing your
class:
public void appendMetadataField(String value)
This method appends the string value to the metadata field in the index.
public void appendIBAField(String value)
This method appends the string value to the IBA field in the index.
public void addContentItem (Object key, InputStream value, long size)
This methods adds the content contained in the InputStream value with the
specified size to the index with the specified key, normally the ufid of the
content.
public void appendSearchField(String inSearchField, Object inSearchValue,
String inSearchType)
This method appends the search field with name inSearchField, value
inSearchValue and type inSearchType to the search fields in the index. The
inSearchType value should be one of "string", "double", "float", "int32" or
"datetime".

21-10 Windchill Customizer’s Guide


Windchill Client Architecture Search Customization

Search customization Scenarios


• Scenario A - Best practice to add attribute in criteria drop down on advanced
search page
• Scenario B - Best practice to add new action to search result table
• Scenario C - Best practice to add new item type to search item picker

Objective
Scenario A: Allow user to add customized attribute to Criteria drop down
Scenario B: Allow user to add new action for given type to search result table
Scenario C: Allow user to add new customized type to search item picker

Background
• Scenario A - An out-of-the-box user can search on all the modeled attributes
as well as soft attributes for given Object Tyep. User can not see attributes
that are added by modeling the Object in Rational Rose.
• Scenario B - The site-defined preference,
/com/ptc/windchill/enterprise/search/allSearchTypes,determines the list of
types that are to be included when a user searches across "all" Object types.
This is the same list that a user can choose from within the Object Type picker
for the Customize link on the Search page, and the Search For link onthe
Advanced Search page
• Scenario C - The allSearchTypes preference defines a base list of types; out-
of-the-box searching rules include all soft types defined from one of these
types. It does not, however, include any modeled subclasses. Any new
modeled object type should be defined in the allSearchTypes preference to
make it available for searches.

Scope/Applicability/Assumptions
• Scenario A - New attributes are added to item by Rational Rose modeling.
• Scenario B - New actions are defined
• Scenario C - New item or object type is modeled in Rational Rose

Intended Outcome

Scenario A - Adding new criteria to search result table:


An out-of-the-box user will not get added extra attributes in Criteria drop down on
advanced search page. Once user adds entry for logical attribute name for new

Customizing Search Functionality 21-11


attributes in SearchableAttributesByType.properties, user can see new attribute
criteria drop down.

In above case user has added new attribute Real and Real _Units which are added
by rose modeling.

Scenario B - Adding new action to search result table.


Out-of-the-box there are fixed actions defined for all Object type on simple search
page whereas on advanced search page Object Type specific actions are available
on search result table. Out-of-the-box on simple search page Copy, Delete, Add to
Project, Move, Reassign Life Cycle, Export actions are provided. We have to add
action Set State on simple search page.

Scenario C - Adding new item to search item picker


The allSearchTypes preference defines a base list of types; out-of-the-box
searching rules include all soft types defined from one of these types. It does not,
however, include any modeled subclasses. Any new modeled object type should
be defined in the allSearchTypes preference to make it available for searches.

21-12 Windchill Customizer’s Guide


Solution

Solution For Scenario A:


Add the logical attribute name against given Object Type in
<Windchill>/codebase/com/ptc/windchill/enterprise/search/server/SearchableAttr
ibutesByType.properties.

Solution For Scenario B:


Add action name and type in <Windchill>/codebase/config/actions/search-
actionmodels.xml

Solution For Scenario C:


Add new sub class modeled type entry in
<Windchill>/codebase/com/ptc/windchill/enterprise/search/server/SearchableTyp
es.properties.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving HTML forms, JSP, XML, Java

Customizing Search Functionality 21-13


Solution Elements

Element Type Description

Scenario A - properties Runtime location


SearchableAttributesByType.properties <Windchill>/codebase/com/ptc/windchil
l/enterprise/search/server/SearchableAttr
ibutesByType.properties

Scenario B - search-actionmodels.xml XML Runtime


<Windchill>/codebase/config/actions/se
a rch-actionmodels.xml

Scenario C - properties Runtime location


SearchableTypes.properties <Windchill>/codebase/com/ptc/windchil
l/enterprise/search/server/SearchableByT
ypes.properties

Scenario A: Procedure – Adding new attribute in Criteria drop down


To add attributes for a particular type, simply add the logical attribute name to the
comma separated list for that type in SearchableAttributesByType.properties. The
logical attribute name is the attribute retrieved from introspection or defined
within the <Windchill>/codebase/LogicalAttributes.xml file.
For example, if we were to add "Real" to wt.part.WTPart, it would look like this:
advancedSearch.wt.part.WTPart=folderingInfo.cabinet,thePersistInfo
.creat
eStamp,iterationInfo.creator,defaultUnit,lock.locker,name,number,o
wnership.owner,source,state.state,thePersistInfo.modifyStamp,itera
tionInfo.modifier,view.id,organizationReference,Real

Scenario B: Procedure – Adding new action to Search Result table


To add new action to search result table, add entries to search-actionmodels.xml
file.Suppose we want to add new action Set State on simple search page, add
following entry to search-actionmodels.xml as:
<model name="search table actions">
<action name="list_copy" type="object"/>
<action name="list_delete" type="object"/>
<action name="CREATEPROMOTIONNOTICE" type="pdmObject"/>
<action name="SBAddToPrj" type="sandbox"/>
<action name="WFSAVEAS" type="pdmObject"/>
<action name="CONTAINERMOVE" type="pdmObject"/>
<action name="userInitiatedReplication" type="replication"/>
<action name="reassignLC" type="lifecycle"/>
<action name="setState" type="lifecycle"/>
<action name="exportSearchResults" type="search"/>
</model>

21-14 Windchill Customizer’s Guide


Scenario C: Procedure - Add new Object type to Object Type picker
To add new Object type for picker, add new object name to
SearchableTypes.properties. We have new sub class as searchPart. For this new
object add entry to add in SearchableTypes.properties as :
PDMLink.allSearch.0=wt.change2.WTChangeIssue
PDMLink.allSearch.1=wt.change2.WTChangeRequest2
PDMLink.allSearch.2=wt.change2.WTChangeOrder2
PDMLink.allSearch.3=wt.part.WTPart
PDMLink.allSearch.4=wt.doc.WTDocument
PDMLink.allSearch.5=wt.epm.EPMDocument
PDMLink.allSearch.6=wt.workflow.engine.WfProcess
PDMLink.allSearch.7=wt.part.WTProductInstance2
PDMLink.allSearch.8=wt.part.WTProductConfiguration
PDMLink.allSearch.9=wt.query.template.ReportTemplate
PDMLink.allSearch.10=wt.vc.baseline.ManagedBaseline
PDMLink.allSearch.11=wt.meeting.Meeting
PDMLink.allSearch.12=wt.org.WTOrganization
PDMLink.allSearch.13=wt.inf.library.WTLibrary
PDMLink.allSearch.14=wt.pdmlink.PDMLinkProduct
PDMLink.allSearch.15=wt.dataops.archive.Archive
PDMLink.allSearch.16=wt.part.WTPart.searchPart

After adding the new type you should set the property
com.ptc.windchill.search.refreshTypesFromProperties to "true" in wt.properties.

Sample Code

Scenario A: Entries from SearchableAttributesByType.properties for new attribute


part Type
advancedSearch.wt.part.WTPart=folderingInfo.cabinet,thePersistInfo
.creat
eStamp,iterationInfo.creator,defaultUnit,lock.locker,name,number,o
wnership.owner,source,state.state,thePersistInfo.modifyStamp,itera
tionInfo.modifier,view.id,organizationReference,Real

Scenario B: Entries from search-actionmodels.xml


<model name="search table actions">
<action name="list_copy" type="object"/>
<action name="list_delete" type="object"/>
<action name="CREATEPROMOTIONNOTICE" type="pdmObject"/>
<action name="SBAddToPrj" type="sandbox"/>
<action name="WFSAVEAS" type="pdmObject"/>
<action name="CONTAINERMOVE" type="pdmObject"/>
<action name="userInitiatedReplication" type="replication"/>
<action name="reassignLC" type="lifecycle"/>
<action name="setState" type="lifecycle"/>
<action name="exportSearchResults" type="search"/>
</model>

Customizing Search Functionality 21-15


Scenario C: Entries from SearchableTypes.properties
PDMLink.allSearch.0=wt.change2.WTChangeIssue
PDMLink.allSearch.1=wt.change2.WTChangeRequest2
PDMLink.allSearch.2=wt.change2.WTChangeOrder2
PDMLink.allSearch.3=wt.part.WTPart
PDMLink.allSearch.4=wt.doc.WTDocument
PDMLink.allSearch.5=wt.epm.EPMDocument
PDMLink.allSearch.6=wt.workflow.engine.WfProcess
PDMLink.allSearch.7=wt.part.WTProductInstance2
PDMLink.allSearch.8=wt.part.WTProductConfiguration
PDMLink.allSearch.9=wt.query.template.ReportTemplate
PDMLink.allSearch.10=wt.vc.baseline.ManagedBaseline
PDMLink.allSearch.11=wt.meeting.Meeting
PDMLink.allSearch.12=wt.org.WTOrganization
PDMLink.allSearch.13=wt.inf.library.WTLibrary
PDMLink.allSearch.14=wt.pdmlink.PDMLinkProduct
PDMLink.allSearch.15=wt.dataops.archive.Archive
PDMLink.allSearch.16=wt.part.WTPart.searchPart

21-16 Windchill Customizer’s Guide


Search Elements and Associated JSPs
• Search element and their associated JSP for Simple Search Page
• Search element and their associated JSP for Advanced Search Page

Search element and their associated JSP for Simple Search Page

Search sub Associated Custom Tag


Search UI Element Element Associated JSP (if any)

Search Page /netmarkets/jsp/search/e


xecuteSearch.jsp

Search Page Navigation Search /netmarkets/jsp/search/se searchNavigation


Advanced Search archNavigation.jsp
Saved Searches

Common Search Page Keyword /netmarkets/jsp/search/c searchTextBoxWithLabel


Show Results ommonSearch.jsp
Results Per Page
Search In
Search For

Search In /netmarkets/jsp/search/sh searchInContext


owContext.jsp

Search For /netmarkets/jsp/search/ty


peChooser.jsp

Name /netmarkets/jsp/search/si searchTextBoxWithLabel,


Number mpleNameNumberCriter searchPickerWithLabel
Organization ia.jsp

FileName /netmarkets/jsp/search/si searchTextBoxWithLabel


mpleNameNumberCriter
ia.jsp

Last Updated /netmarkets/jsp/search/si searchDateWithLabel


Created On mpleNameNumberCriter
ia.jsp

Save This /netmarkets/jsp/search/se


Search,Search,Clear Button archButton.jsp

Search Results Table /netmarkets/jsp/search/se


archResults.jsp

Save This Search /netmarkets/jsp/search/c


ustomizeQuery.jsp

Customizing Search Functionality 21-17


Search element and their associated JSP for Advanced Search Page
Search sub Associated Custom Tag (if
Search UI Element Element Associated JSP any)

Search Page /netmarkets/jsp/search


/executeSearch.jsp

Search Page Navigation Search /netmarkets/jsp/search searchNavigation


Advanced Search /searchNavigation.jsp
Saved Searches

Common Search Page Keyword /netmarkets/jsp/search searchTextBoxWithLabel


Show Results /commonSearch.jsp
Results Per Page
Search In
Search For

Search In /netmarkets/jsp/search searchInContext


/showContext.jsp

Search For Type Picker /netmarkets/jsp/search


/typeChooser.jspf

Search For Define Search /netmarkets/jsp/search archivePanel


Criteria for /handleArchiveSearch.
Archived Objects jsp

Search For Options for Part searchDDLComponent


advanced search

Search For SuMA sourcing /netmarkets/jsp/search


contexts /sourcingContext.jsp

Select Search Criteria Criteria: /netmarkets/jsp/search


/queryBuilder.jsp

Save This /netmarkets/jsp/search


Search,Search,Clear /searchButton.jsp
Button

Search Results Table /netmarkets/jsp/search


/searchResults.jsp

Save This Search /netmarkets/jsp/search


/customizeQuery.jsp

21-18 Windchill Customizer’s Guide


III
Business Logic Customization
Section

Chapter Page
Customizing Business Logic............................................................................. 22-1
Customizing Change Management ................................................................... 23-1
Customizing Life Cycle Administration ........................................................... 24-1
Customizing Workflow Administration............................................................ 25-1
Customizing Workgroup Managers .................................................................. 26-1
Customizing Windchill Visualization Services ................................................ 27-1
Report Generation ............................................................................................. 28-1
Customizing Event Audits ................................................................................ 29-1
Customizing Communication Tools ................................................................. 30-1
22
Customizing Business Logic

This chapter describes how to customize business logic.

Topic Page
Identified Business Classes ..............................................................................22-2
Customizing Iteration and Version Identifiers ................................................22-17
Customizing a Bill of Materials ......................................................................22-19
Customizing User Preferences ........................................................................22-24
Writing a Servlet Helper to Use URLFactory Functionality...........................22-30
Updating a Master Through an Iteration .........................................................22-32

22-1
Identified Business Classes

Identity Attributes
Identity attributes are the attributes of an object that, as a whole, distinguish it to
the user from other objects. The designer of a class must decide which attributes
compose its identity. For example, a SubFolder is identified by its name and its
parent folder. A WTPart’s identity attributes include number and name. For
classes that are uniquely identified, at least one of the identity attributes of the
class must have a uniqueness constraint in order to distinguish between different
instances of the class.

How Identity Is Assigned and Managed

User-Assigned Identity Attributes


User-assigned identity attributes can be set by a user when an object is created.
Unlike other attributes, they cannot be modified after the object is created.
However, the user can change the values of identity attributes using the rename
operation in Windchill Explorer. This is actually accomplished by calling the
changeIdentity operation of the IdentityService. The name attribute of the
WTDocument class is an example of a user-assigned identity attribute.

System-Assigned Identity Attributes


System-assigned identity attributes have values that are generated by the system
when the object is created. The number attribute for the WTChangeOrder2 class is
an example of a system-assigned identity attribute.

Changing an Object’s Identity


Currently, all Windchill classes that have user-assigned identity attributes can be
modified later by the user, but system-assigned identity attributes cannot be
modified by the user. This is not a hard and fast rule, however. For example, a
document number could be assigned by a user when the document is created and
then never be allowed to change. Or, a default number could be generated by the
system, but the user could override this number if desired either when the
document is created or at a later date.

Permissions to Modify Identity


Business object attributes are modelled with the "Changeble" property set to
"ViaOtherMeans" to prevent use of the attribute's setter after the object is
persisted; this enforces use of a service (such as the Identity Service) for changing
these attributes. A separate use of the "Changeable" property- on the attributes of
the wt.fc.IdentificationObject, not the business object- will identify attributes
which can be edited only by users possessing the MODIFY_IDENTITY
permission.

22-2 Windchill Customizer’s Guide


If an attribute of a wt.fc.IdentificationObject is modelled with the "Changeable"
property set to "ViaOtherMeans", the Identity Service will consider that attribute
part of the identity, and will require that the user have MODIFY_IDENTITY
permission to change that attribute. The Identity Service will require MODIFY
permission to change attributes whose models do not have the "Changeable"
property set to "ViaOtherMeans". Attributes which are modelled as "Changeable
Via Other Means" on the business object, but are not so modelled on the
IdentificationObject, will not be protected by the MODIFY_IDENTITY
permission.

Customizing Business Logic 22-3


User-Managed Versus System-Managed Identity
An object’s identity is user-managed if the user can either assign or modify its
identity attributes. It is important to distinguish user-managed from system-
managed identity because typically not all identity changes that a user might
attempt are valid. For example, a part master’s identity includes its name and
number. WTPartMaster is user-managed because the user can assign and modify a
part master’s name and number. Because it is user-managed, a constraint is
enforced which requires that no two parts can have the same number. If the part
number was assigned by the system, however, it would no longer be necessary to
enforce the part number uniqueness constraint because the algorithm that the
system uses to generate part numbers guarantees unique part numbers.
The interfaces wt.fc.Identified and wt.fc.UniquelyIdentified, which work in
conjunction with the IdentityService, are implemented by classes that have user-
managed identity in order to apply validation logic and uniqueness constraints
when a user makes a change to an object’s identity.

A Special Case—RevisionControlled Identity


Classes that extend RevisionControlled are identified by a version and iteration
identifier. The version and iteration are assigned by the system, based on the
previous version and iteration. However, because a new version is derived from a
user-specified old version, possibly not the latest, a user may cause the same
system-generated identity to apply to two separate objects. Because of this
behavior, RevisionControlled does not fit the description of either a user- or
system-managed identity. A uniqueness constraint must be enforced such that two
identical versions of the same master cannot be created. However, subclasses of
RevisionControlled do not need to implement the Identified interface, as
explained next.
Checking out a RevisionControlled object, such as a WTDocument, causes the
document’s iteration number to increase: A.1 to A.2. In this case, it is clear that
the system is managing the identity, and it is impossible for the user to create two
different iterations with the same number. Creating a new version conceptually
creates a new document with an identity of B.1. Again the system is managing the
version identity attribute. However, when both version A.2 and B.1 exist, it is
possible for a user to attempt to create a new version from A.2 again. If not
prevented, this would create two version B objects. Thus, a uniqueness constraint
must be applied that prevents two identical versions of the same master from
being created. This situation is unique because the system manages the identity
attributes, but the user can instruct the system to create the same object twice,
even though it does not directly control the assignment of the version letter.
Contrast this to a class such as WTChangeRequest2, where each new change
request object is assigned the next unique number from an integer sequence for its
identity.

22-4 Windchill Customizer’s Guide


When to Use the IdentityService
Any class that has user-managed identity attributes must implement the Identified
or UniquelyIdentified interfaces. This enables the object’s identity to be changed
with the IdentityService. The IdentityService provides users of a class that
implements the Identified interface a means to change the identity attribute values
subject to validation logic and uniqueness constraints.
Use the following flowchart to help determine whether a class that has identity
attributes should implement the Identified interface, the UniquelyIdentified
interface, or neither.

Customizing Business Logic 22-5


How to Use the IdentityService

Overview
The following figure illustrates the IdentityService.

IdentificationObject is a non-persistent class that holds the values of the identity


attributes from a class that implements the Identified or UniquelyIdentified
interface. For a particular business class that implements Identified, a subclass of
IdentificationObject is modeled that has the same identity attributes as the
business class. Instead of directly changing the identity attributes of the business
object, the attributes of the IdentificationObject subclass are used to change the
identity, and these values are then copied back to the business object, subject to
validation logic and uniqueness constraints, when IdentityService.changeIdentity
is called.
Any class that implements the Identified interface must implement the
getIdentificationObject method, which returns an instance of IdentificationObject
that holds the current value of the identity attributes.

22-6 Windchill Customizer’s Guide


The following sequence diagram illustrates how a change order’s identity is
modified:

Identified
When a class implements the Identified or UniquelyIdentified interface, the
identity attributes of the class must be modeled in a special way. Also, a single
method on the Identified interface -- getIdentificationObject -- must be
implemented. UniquelyIdentified has no methods to implement.
wt.change2.WTChangeRequest2 is used to illustrate the step-by-step instructions.
See the class diagram named "request" in the wt.change2 package of the Rose
model for reference.
1. Add a public constructor that has arguments for each user-assigned identity
attribute.
WTChangeRequest2 has a constructor that has a single argument for the name
attribute. Number is the other identity attribute but, because it is system-
assigned, it does not need to be an argument of the constructor. In the
initialize method that is called from the generated factory method for this
constructor, the name attribute is initialized. Sequential system-assigned
attributes, like numbers, should not be initialized in the constructor, but
instead in the PersistenceManager PRE_STORE event processing right before
the object is saved. This greatly improves the odds that elements in the
sequence are not lost if the create action is aborted by the user. That is,
system-assigned attributes are initialized only when it is certain that an object
will be persisted.
2. Set the WriteAccess model property to "protected" for all identity attributes.

Customizing Business Logic 22-7


This action prevents general access to the setter methods, allowing only the
IdentityService to update the identity attributes of an Identified object.
Note: There may be cases where it is necessary to create an uninitialized
instance of a class by calling the no-arg constructor, followed by calls to the
setter methods to initialize the attributes. This is the case with WTPartMaster
and WTDocumentMaster. In this situation, the identity attributes must have
public WriteAccess instead of protected. To prevent the use of the setter
methods after the object has been persisted, use the "Changeable" property.
When set to the value "ViaOtherMeans", the Changeable property causes
validation code to be generated in the setter method for the attribute, which
allows the method to be used only if the object is not persistent.
3. Implement getIdentificationObject (part of the Identified interface) to return a
new instance of the subclass of IdentificationObject that has been designed
for this particular Identified class. In the case of WTChangeRequest2, there is
a subclass of IdentificationObject called WTChangeRequest2Identity.
Following is an example:
public IdentificationObject getIdentificationObject()
throws WTException {
//##begin getIdentificationObject%3536588B01EEg.body
preserve=yes
return WTChangeRequest2Identity.newWTChangeRequest2Identity(
getNumber(), getName());
//##end getIdentificationObject%3536588B01EEg.body
}

The following section describes the role of IdentificationObject


and how to extend it.

IdentificationObject
Throughout these instructions, the example of wt.folder.SubFolderLinkIdentity is
used to illustrate each step. See the class diagram named "Identification" in the
wt.folder package of the Rose model for reference.
1. Model a subclass of IdentificationObject in the same package.
wt.folder.SubFolderLinkIdentity extends IdentificationObject. Notice that the
subclass of IdentificationObject is in the same package as the class that
implements Identified, namely SubFolderLink. This is a requirement because
SubFolderLinkIdentity must call protected setter methods on SubFolderLink
to change the value of its identity attributes.

22-8 Windchill Customizer’s Guide


2. Add public attributes for each user-assigned identity attribute.
For every user-assigned identity attribute of the Identified class, add the same
attributes to the subclass of IdentificationObject. In the case of
SubFolderLinkIdentity, the identity attributes are subFolderName and
parentFolderReference. Making the identity attributes public on the
IdentificationObject allows any client to assign a new identity to an object
through the IdentificationObject setter methods instead of the ones on the
Identified object (see the preceding figure on modifying a
WTChangeOrder2’s identity).
3. Add a protected constructor that has an argument for the Identified object.
The constructor is protected because it is intended to be invoked only in the
getIdentificationObject method of the corresponding Identified class, in this
example, SubFolderLink. Alternatively, the constructor can have an argument
for each identity attribute instead of the entire Identified object.
4. Implement the code-generated initialize method to set the identity attributes
from the Identified Object.
For every modeled constructor, a static factory method is automatically
generated that is implemented to call an initialize method. In this initialize
method, call the identity attribute getter methods on the Identified object and
set them to the IdentificationObject’s identity attributes. That is, copy the
identity attributes from the Identified object to the IdentificationObject.
Following is an example:
protected void initialize( SubFolderLink link )
throws WTException {
//##begin initialize%356993D30199.body preserve=yes

setParentFolderReference((ObjectReference)link.
getRoleAObjectRef());
setSubFolderName(link.getFoldered().getName());

//##end initialize%356993D30199.body
}

5. Implement the getIdentity method.


The getIdentity method is not used unless the subclass of IdentificationObject
is for a UniquelyIdentified class. If your class implements only Identified,
getIdentity can return any String representation of the identity attributes.

Customizing Business Logic 22-9


6. Implement the setToObject method.
The setToObject method is invoked by the IdentityService to transfer the
values of the identity attributes from the IdentificationObject to the Identified
object. Following is the implementation of
SubFolderLinkIdentity.setToObject:
public void setToObject( Identified obj ) {
//##begin setToObject%356993A900B2s.body preserve=yes
// All we have to set is the reference because the name
// is managed by the SubFolder object.

((SubFolderLink)obj).
setRoleAObjectRef(getParentFolderReference());

//##end setToObject%356993A900B2s.body
}

This completes the implementation of the IdentificationObject subclass if the


corresponding business class implements Identified. If it implements
UniquelyIdentified, then the following two additional steps are necessary:
1. Override the getKeyClassName method.
This method returns the name of the class that extends SemanticKey, which is
used to store the key value that is subject to the uniqueness constraint for the
UniquelyIdentified object. For the SubFolderLinkIdentity example, a private,
static String constant is modeled and initialized to the value
SubFolderLinkConstraint.class.getName(). Then getKeyClassName simply
returns this String constant.
2. Ensure that getIdentity returns a String that represents the uniqueness
constraint on the UniquelyIdentified object.
Because getIdentity is an abstract method in IdentificationObject, every
subclass must implement it. However, it is not actually used unless the
subclass of IdentificationObject is for a UniquelyIdentified class. In this case,
getIdentity is called to set the value of SemanticKey.key. Remember, this is
the String that represents the uniqueness constraint on the UniquelyIdentified
object. In this example, getIdentity returns the following string:
getParentFolderReference().getObjectId().getStringValue()
+ "+" + getSubFolderName();

This String is a combination of the parent folder and subfolder name. This
indicates the uniqueness constraint on SubFolderLink is that no two
subfolders in a given parent folder can have the same name.

22-10 Windchill Customizer’s Guide


UniquelyIdentified and SemanticKeys
You must implement the UniquelyIdentified interface in cases where a uniqueness
constraint on a user-managed identity attribute applies across multiple classes.
This is because every class in the model is mapped to a single database table.
Because unique database indexes apply to one table at most, some mechanism in
the application layer must be used to enforce the uniqueness constraint. This
mechanism is the SemanticKey class found in the wt.fc package.
The following sequence diagram illustrates how SemanticKey works:

The preceding figure illustrates the general case. Consider a specific example,
WTPartMaster. WTPartMaster has two identity attributes: name and number.
Number must be unique across all subclasses of WTPartMaster, so we must
implement a SemanticKey. WTPartMasterKey extends SemanticKey and
WTPartMasterIdentity extends IdentificationObject. The implementation of
WTPartMasterIdentity.getKeyClassName returns "wt.part.WTPartMasterKey"
and WTPartMasterIdentity.getIdentity returns the part number. So, whenever a
WTPartMaster is saved, the value of the part number is stored in the
WTPartMasterKey table. Any subclass of WTPartMaster also stores its number in
the same SemanticKey table, WTPartMasterKey. Because there is a uniqueness
constraint on the key attribute of the WTPartMasterKey class, unique part
numbers are guaranteed across WTPartMaster and all its subclasses.

Customizing Business Logic 22-11


Enforcing Uniqueness Constraints with Database Indexes
Windchill supports the creation of unique database indexes through the model
properties Unique and CompositeUnique. Unique database indexes are an
efficient way to enforce uniqueness constraints for one or more attributes of a
single class. If the uniqueness constraint must apply across multiple classes, such
as a base class and all its subclasses, database indexes do not help. In this case,
SemanticKey class is used.
Database indexes are used to enforce uniqueness constraints on both user- and
system-managed identity attributes. See the first figure in this chapter, the
identified classes flowchart, to help determine when a database index should be
used.
The Unique property of an attribute creates a unique index on the database column
for that attribute. The following example is for wt.folder.Cabinet, which specifies
that its name is a Unique attribute. The SQL DDL generated is as follows:
CREATE UNIQUE INDEX Cabinet$name ON Cabinet(name) STORAGE
( INITIAL 20k NEXT 20k PCTINCREASE 0 )

22-12 Windchill Customizer’s Guide


The CompositeUnique1 and CompositeUnique2 properties of a class create a
unique index across multiple database columns. The following example is for
wt.enterprise.RevisionControlled, which specifies that the master + version +
iteration + checkout state attributes are unique as a whole.

When using the CompositeUnique property, only two unique indexes can
currently be specified in the model. Additional attributes can be added to the
index in the subclass by adding them after the "+".

Customizing Business Logic 22-13


The following figure is an example of a composite uniqueness constraint for
WTPart.

22-14 Windchill Customizer’s Guide


How to Implement System-Managed Identity
To implement system-managed identity, perform the following steps:
1. Use database sequences for system-assigned number attributes.
Typically, system-assigned attributes are generated as a number sequence.
Windchill supplies a utility method that provides access to a sequence of
number values maintained by the Oracle database:
public String getNextSequence(Class a_class) throws WTException;

Given a modeled class that implements the DatastoreSequence interface, the


getNextSequence method returns a number that is represented as a String. The
number value returned is incremented each time the getNextSequence method
is invoked for the given sequence name.
2. Listen for the PRE_STORE event on the identified object.
The service associated with the Identified object in question must listen for a
PersistenceManager PRE_STORE event and assign the number value at this
time. For example, for WTChangeRequest2, the ChangeService2 implements
the following to assign numbers to change requests:
protected void performStartupProcess()
throws ManagerException {
//##begin performStartupProcess%35D1B483001F.body preserve=yes
/*
* Listen for a PersistenceManager PRE_STORE event
* on a WTChangeRequest2
*/
getManagerService().addEventListener(
new ServiceEventListenerAdapter() {
public void notifyVetoableEvent( Object event )
throws WTException {
PersistenceManagerEvent pmEvent =
(PersistenceManagerEvent)event;
Persistable target = pmEvent.getTarget();
if (target instanceof WTChangeRequest2) {
// assign a number
WTChangeRequest2Identity idObj =
(WTChangeRequest2Identity)target.
getIdentificationObject();
idObj.setToObject(target);
}
}
},
PersistenceManagerEvent.generateEventKey(
PersistenceManagerEvent.PRE_STORE));
}

Customizing Business Logic 22-15


3. Implement the setToObject method on WTChangeRequest2Identity:
protected void setToObject( Identified obj )
throws WTException {
//##begin setToObject%356DC85D038A.body preserve=yes

String number = PersistenceHelper.manager.getNextSequence(


Class.forName("wt.change2.ChangeRequest2IdentitySequence");

((WTChangeRequest2)obj).setNumber(number);

//##end setToObject%356DC85D038A.body
}

4. Create the sequence as a standalone datastore element, by modeling a class


that implements wt.fc.DatastoreSequence. Set the datastore schema name,
initial seed value, and increment value from the Rose model. Use the
generated database script to create the datastore schema object. For more
information, see How Rose UML Maps to Database Schema in the System
Generation chapter on page 32-41.
In this example, ChangeRequest2IdentitySequence implements
DatastoreSequence.
Following is an example for WTChangeRequest2:

22-16 Windchill Customizer’s Guide


Customizing Iteration and Version Identifiers
Both iteration and version series can be customized to better represent a
company’s way of identifying minor and major changes, respectively. The
following is a segment of the wt.properties file where properties exist for these
kinds of customizations:
# Seriesfactoryassociations'
wt.vc.IterationIdentifier=wt.series.IntegerSeries
wt.vc.VersionIdentifier=wt.series.HarvardSeries
# Series’ subclassdefaults'
wt.series.IntegerSeries.min=1
wt.series.IntegerSeries.max=2147483647
wt.series.IntegerSeries.delta=1
wt.series.MulticharacterSeries.min=A
wt.series.MulticharacterSeries.max=Z
wt.series.MulticharacterSeries.delta=1
wt.series.MulticharacterSeries.length=3
wt.series.HarvardSeries.depth=16
wt.series.HarvardSeries.level.1=wt.series.MulticharacterSeries
wt.series.HarvardSeries.delimiter=.

Iteration identifiers are by default specified as being an integer series where this
series contains whole numbers from a minimum to a maximum value. The default
minimum is one (1) and the default maximum is the largest possible 32-bit
positive integer value as defined by 2**31-1 (2,147,483,647). There is also a
default specification of the delta between adjacent numbers, which is one (1)
meaning that, if given 10, the next incremented integer value would be 11 by
default.
Version identifiers are by default specified as being a harvard series. A harvard
series is one that is made up of subseries and is typically depicted as a stream of
values delimited by a dot (for example, 1.1, 1.3.5, 1.2.1.1, and so on). Version
identifiers must be specified as some sort of multilevel series where the harvard
series is currently the only option. This is done to represent both in-lined versions
and branched versions in one identifier that forms a version tree. In turn, the
harvard series’ subseries are by default specified as being multi character series at
level one and then, because there are no other levels specified, the default from
there on is what was specified before for all levels. In this case, it would be multi
character series for all levels. If level two was specified as an integer series then,
starting at the beginning, every two levels would alternate from a multi character
to integer series up to the specified depth as seen below.
wt.series.HarvardSeries.depth=16
wt.series.HarvardSeries.level.1=wt.series.MulticharacterSeries
wt.series.HarvardSeries.level.2=wt.series.IntegerSeries

Customizing Business Logic 22-17


Multi character series are specified much like integer series where there is a
minimum, maximum, and delta. By default, these properties specify A, Z, and 1,
respectively. But there also is another property to specify the length of the multi
character series. By default, this is three (3), which means that an identifier of this
series would have a range from A to ZZZ, where incrementing from Z of a delta
of one (1) would be AA, incrementing from AZ would be BA, and incrementing
from ZZ would be AAA. Decrementing follows these same rules except in
reverse. If a length of one (1) were specified instead of the default of three, this
series would range from A to Z given the same other properties.
Any character value for the minimum and maximum can be specified for a multi
character series. But only integers can be specified for the minimum and
maximum values of an integer series.
For additional information, see the "Object Initialization Rules" chapter in the
Windchill Business Administrator’s Guide.

22-18 Windchill Customizer’s Guide


Customizing a Bill of Materials

Overview
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
out-of-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.

Customizing Business Logic 22-19


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

22-20 Windchill Customizer’s Guide


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 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();
}
}

Soft attributes on parts are displayed in the BOM reports automatically using the
table view, but soft attributes on part usage link 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
JSP file needs to be customized 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 by
1. Set up a custom table view with that column as one of the selected columns.
2. Add the following to the describeTable section of the JSP:
<describeColumn id="IBA|LinkName" targetObject="link" <any
other settings for the column> />

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:

Customizing Business Logic 22-21


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.

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
part’s quantity and the current part’s 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

22-22 Windchill Customizer’s Guide


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.

Customizing Business Logic 22-23


Customizing User Preferences
This section discusses and gives examples of how you customize the out-of-the-
box user preference functionality.

Preference Definition
The preference definition contains all of the static information about a preference
which is stored in the database. This definition contains a default value and the
constraint (as in the IBA constraints) for what is allowed as a value instance. The
preference API returns this default value if a preference value (in the form of a
preference instance) is not located in the database. Display information used in the
Preference Manager UI is also defined in the preference definition as resource
bundle entries. The static information in the preference definition includes the
following:
• Name
• Default Value
• Display Name
• Display Description
• Display Long Description
• Visibility (Hidden, Site, Org, Container, User, and User Only)
• The value handler for processing the preference values

Visibility
The preference definition contains a visibility flag to show who can see a given
preference in the Preference Manager.
• HIDDEN- preference would be one that is not visible in the Preference
Manager.
• SITE - preference is on that is visible only to the Site Administrator.
• ORGANIZATION - preference is one that is visible to the Site and Org
Administrators. Each Org could have a separate instance of the value tied to
that Org.
• CONTAINER - preference is one that would be visible to the Site and Org
Administrators and the Container Manager.
• USER - preference is one that would be visible at all levels.
• USER_ONLY - preference is one that is settable only at the user level.

22-24 Windchill Customizer’s Guide


Value Handler (type)
The handler defines the type of preference (Boolean, String, Pick from a list, etc.).
The handler interface was designed, so that a type of preference is not limited to
only a few select types. The handler interface allows for the specification of how a
preference value is edited, stored and displayed. All preference value handlers
should be extended from the abstract class
com.ptc.windchill.enterprise.preference.handler.AbstractPreferenceValueHandle.
Some common out-of-the-box handlers in the
com.ptc.windchill.enterprise.preference.handler package:
• BooleanPreferenceValueHandler
• CustomPreferenceValueHandler
• NumberPreferenceValueHandler
• StringPreferenceValueHandler

Preference Instance
The individual values are set within the preference instance. The preference
instance ties the chosen context; Site, organization container, application
container (such as a projects, programs, products, or libraries) or user to the
preference definition with the value set for the context. If a preference instance is
not found in a request for a preference, then the default value defined in the
preference definition is returned.

Preference Category
The category is just a means of grouping preferences in the tree structure of the
Preference Manager. An individual preference definition is contained within a
preference category. A preference category can be contained within another
category. This allows for a hierarchical view of the preferences. The preference
category has no impact on the actual operation of the system, but is used in the
administration of the preferences.

Preference Client
The client was added for UWGM to set preference values by Authoring
Applications like AutoCAD, CATIA V5, etc. The default client name if not
specified is “WINCHILL”, defined by the constant
wt.preference.PreferenceClient.WINDCHILL_CLIENT_NAME.

The Preference Hierarchy


Preference values set at one level are inherited by the application contexts below.
For example, preference values set at the site level are inherited by the

Customizing Business Logic 22-25


organization; application contexts within the organization inherit preference
values from the organization.

Note: User preferences may be inherited directly from the organization-level,


from individual application contexts, or may be unique (settable only at the user
level).

Preference values can be set for each application context, or for an individual user,
unless the preference value is locked at a higher level. For example, if a
preference is not locked at the organization level, then it may have one value at
the organization level, but individual products or projects within that organization
could each specify a different value. Similarly, if a preference is not locked at an
organization level, but is available at the user level, then individual users could
each set different values for that preference.
Preferences can be locked at any level above the individual user. If a preference is
locked, then the value cannot be changed for those lower levels. A site or
organization administrator can choose to delete all values for a particular
preference that may be set at levels below the current context, usually prior to
locking the preference.
If a preference is not explicitly set for a particular application context, then the
value for that preference is inherited from the level above. For example:
• •If a preference is not set for a particular product or project, then the value set
for that preference at the organization level is used.
• •If the preference is not set at the organization level, then the value set for that
preference at the site level is used.
• •If no preference is set at any level, then the default value defined for that
preference is used.

22-26 Windchill Customizer’s Guide


Calling preference values
Preference values are retrieved for through the preference service API's in the
wt.preference package. To retrieve a single preference value the method to call is:
public Object PreferenceHelper.service.getValue(

WTContainerRef containerRef, String definitionName,


String clientName, WTUser user );

The above method will return the value at the user context if it exists, otherwise
the value set at the container context and so on up the preference hierarchy. Other
single preference value methods in the wt.preference package include:
public Object getValue( String definitionName, String clientName );

public Object getValue( String definitionName, String clientName,


OrgContainer organization );

The first method retrieves value at the Site context, while the second method
retrieves the value at the Organization context and if it does not exist, then the
inherited value at the Site is returned.
Multiple preference values can be retrieved at the same time. This is more
efficient in database calls:
public Map<String, Object> getValues(WTContainerRef containerRef,
Collection<String> definitionNames, Collection<String>
categoryNames, String clientName, WTUser user)

Example:
Map<String,Object> preferenceMap = null;

ArrayList<String> categories = new ArrayList<String>();

ArrayList<String> definitionNames = new ArrayList<String>();

definitionNames.add("PREFERENCE_DEFINITION_1");

definitionNames.add("PREFERENCE_DEFINITION_2");

definitionNames.add("PREFERENCE_DEFINITION_3");

definitionNames.add("PREFERENCE_DEFINITION_4");

Map <String, Object> preferenceMap =


PreferenceHelper.service.getValues(

containerRef, definitionNames, categories, clientName, user);

Adding Preferences
New preference definitions and categories are added using the LoadFromFile
utility to load an XML based load file. This can be run with the following
command:

Customizing Business Logic 22-27


windchill wt.load.LoadFromFile -d %WT_HOME%/loadFiles/filename

An example XML preference load file which loads various preference definitions
and preference categories is the Windchill/loadfiles/preference.foundation.xml
load file.
Example Preference Definition:
<?xml version="1.0"?><!DOCTYPE NmLoader SYSTEM "standardX10.dtd">

<NmLoader>

<csvPreferenceDefinition
handler="wt.preference.LoadPreference.createPreferenceDefinition">

<csvname>PREFERENCE_DEFINITION_1</csvname>

<csvvisibility>USER</csvvisibility>

<csvcategoryName>UNASSIGNED</csvcategoryName>

<csvdisplayName>com...PrefsRB:MYPREF_NAME</csvdisplayName>
<csvdescription>com...PrefsRB:MYPREF_SHORT_DESC</csvdescription
>

<csvlongDescription>com...PrefsRB:MYPREF_DESC</csvlongDescripti
on>

<csvdefaultValue>false</csvdefaultValue>

<csvhandler>wt.preference.handler.BooleanPreferenceValueHandler
:

</csvhandler>

</csvPreferenceDefinition>

<csvLinkPreferenceClientDefinition
handler="wt.preference.LoadPreference.setClientDefinitionLink">

<csvname>PREFERENCE_DEFINITION_1</csvname>

<csvclientName>WINDCHILL</csvclientName>

</csvLinkPreferenceClientDefinition>

</NmLoader>

Note: The <csvLinkPreferenceClientDefinition> entry is needed if the


preference is to be visible in the Preference Manager UI. The
<csvdisplayName>, <csvdescription>, <csvlongDescription> are in the
form of rbinfo file/key pair separated by a colon : like the following:

wt.preference.preferenceResource:Unassigned

22-28 Windchill Customizer’s Guide


The preference category specified by <csvcategoryName> needs to exist
otherwise the creation of the preference definition will fail.
Example Preference Category:
<csvPreferenceCategory
handler="wt.preference.LoadPreference.createPreferenceCategory">

<csvname>UNASSIGNED</csvname>

<csvparentName></csvparentName>
<csvdisplayName>wt.preference.preferenceResource:Unassigned

</csvdisplayName>

<csvdescription></csvdescription>

</csvPreferenceCategory>

Sub-categories can be created by adding an existing category name to the


<csvparentName> element.

Customizing Business Logic 22-29


Writing a Servlet Helper to Use URLFactory Functionality
Servlets within Windchill are accessed by requesting a Web resource that exists
under a path with the following format:
<Web application>/servlet/<your servlet name>
The role and arguments of servlets can vary greatly depending on their
application. However, if HREFs and URLs are being generated to the servlet, the
URLFactory should be used in conjunction with a servlet helper to add the
functionality provided by the URLFactory.
The GatewayServletHelper class located in wt.httpgw is a good example of how
to create HREFs and URLs to the anonymous and authenticated gateway servlets.
A preconfigured URLFactory is taken as the first argument of each method, and
this URLFactory is used to create the final HREF or URL accordingly within the
method.
When writing servlet helpers, keep the following points in mind:
• All methods should have a URLFactory as their first argument. (See the
example that follows.)
• URLFactory may be null or uninitialized. In this case, the method body
should instantiate a new URLFactory for the HREF and URL generation.
• The method name should follow either of the following helper conventions,
where <servlet> is a name representing the servlet:
– build<servlet>HREF( )
– build<servlet>URL( )
• The method bodies should take arguments and generate a proper resource
path (such as, servlet/WindchillAuthGW), then pass this resource path to the
URLFactory getHREF and getURL methods for generating the servlet HREF
and URL.
The URLFactory in the JSP Environment section in the Additional Topics - Client
Customization appendix on page E-5 gives more detailed reference information
on URLFactory usage and encoding/decoding techniques to use in JSP
development.

22-30 Windchill Customizer’s Guide


Example URLFactory Usage/Instantiation
Following is a sample file setting up a default URLFactory implementation in an
internationalization environment.
<%
// bcwti
// Copyright (c) 2001 Parametric Technology Corporation, all rights reserved.
// ecwti

//////////////////////////////////////////////////////////////////////
// This file is intended to give an example of how the URLFactory
// and GatewayServletHelper may be used within
// the JSP programming environment. To run this file, simply
// place the file in the /Windchill/codebase/wtcore/jsp directory.
// Extra whitespace as been left in for clarity and ease of reading.
///////////////////////////////////////////////////////////////////////
%>

<% /*** The WTContextBean is a JavaBean for use in Java Server Pages or
Servlets that wish to use Windchill Java client or server APIs ***/ %>

<jsp:useBean id="wtcontext" class="wt.httpgw.WTContextBean" scope="request">


<jsp:setProperty name="wtcontext" property="request" value="<%=request%>"/>
</jsp:useBean>

<% /*** The URLFactory is a JavaBean for use in the generation of HREFs used in
Windchill JSP clients ***/ %>
<jsp:useBean id="url_factory" class="wt.httpgw.URLFactory" scope="request" >
<%

url_factory.setRequestURL(request.getScheme(),request.getHeader("HOST"),
request.getRequestURI());
%></jsp:useBean>

<%
// The response header for the output stream should be set to UTF-8
response.setContentType("text/html; charset=UTF-8");
// Below we also set the content type in the @page tag, since some
// servlet engines
%><%@ page import="wt.httpgw.*,java.util.HashMap" contentType="text/html;
charset=UTF-8" %>

<%
// Here we want to generate a link to the Windchill home page through
// the default authenticated gateway. For this we will utilize the
// wt.httpgw.GatewayServletHelper class to generate a HREF which
// from the current URLFactory will generate a link to this site.
// %>
<BR>
<A HREF="<%=
wt.httpgw.GatewayServletHelper.buildAuthenticatedHREF( url_factory )
%>">Windchill Home</A>
<BR>
<% // Perhaps you would like a link to your personal cabinet. In order to
// do this, you must generate a link through the authenticated gateway
// with a class/method and arguments to invoke like below

Customizing Business Logic 22-31


//
String URL_PROCESSOR = "wt.enterprise.URLProcessor";
String TEMPLATE_ACTION = "URLTemplateAction";
// URLFactory and GatewayServletHelper uses HashMap for arguments
HashMap map = new HashMap( );
map.put( "Action", "Create" ); // adds the action 'create' to the
hashmap
map.put( "Class", "wt.doc.WTDocument" ); // adds the class to apply the action
// to.
%>
<A HREF="<%=
wt.httpgw.GatewayServletHelper.buildAuthenticatedHREF(url_factory,
URL_PROCESSOR, TEMPLATE_ACTION, map )
%>">Create a Document</A>

<%
// For optimization, any links generated in the fashion described above could be
// generated reusing the HashMap and Strings already created. The Setup.jsp file
// located in codebase/wtcore/jsp/wt/portal/Setup.jsp does just this in the
// generation of the links thus reducing the overhead in String/HashMap object
// creation.
//
// In the FORM below we use the URLFactory to generate a link to the resource
// wtcore/jsp/sample.jsp. See the Javadoc for method prototypes. The URLFactory
// is smart enough to see how it is currently configured and return a String link
// which should work within the current environment. For the example below, since
// we are running the file from /WEB-APP/wtcore/jsp the link will generate simply
// "sample.jsp". Optionally we could have called
// url_factory.getHREF("wtcore/jsp/sample.jsp",request.getQueryString() ) if we
// wished to retain the current Query string.
%>
<FORM ACTION="<%= url_factory.getHREF("wtcore/jsp/sample.jsp") %>" METHOD="POST">
<INPUT TYPE="text" NAME="Sample_Text" VALUE="<%= prev_value %>">
<INPUT TYPE="submit">
</FORM>

Updating a Master Through an Iteration

Introduction
The master-iteration documentation (described the Windchill Design Patterns
chapter on page 35-1) specifies that the Mastered and Iterated classes work
together closely. A class that implements Mastered (henceforth called the master)
contains all the version-independent information, whereas the Iterated class
(henceforth called the iteration) contains the incremental change that an object
undergoes. When applying the master-iteration pattern, it is important to consider
whether the master and iteration will be treated as a single logical object or as two
distinct objects. Specifically, consider whether a client needs to know that a
document is actually composed of an iteration and a master.
The Windchill reference implementations WTPart and WTDocument define the
master attributes on the iteration as derived attributes, thus hiding the existence of
the master from clients. For both WTPart and WTDocument, the only attributes

22-32 Windchill Customizer’s Guide


on the master are number and name. In addition to being master attributes, they
are also identifying attributes. This means that they can be modified only by using
the IdentityService after the object has been persisted.
The Windchill reference implementation does not have an example of a master
class with non-identifying attributes. Currently, there is no support for
automatically persisting a master if its non-identifying attributes are updated using
derived attributes on the iteration. That is, the attribute could be modified by
calling its setter on the iteration, but the client would have to persist the master to
save the changes.
The following is a discussion of different ways master attributes can be exposed
on the iteration and how changes to master attributes through the iteration can be
persisted.

Read-only and Queryable Master Attributes on the Iteration


It is quite easy and often desirable to view and/or query attributes from the
iteration and master together. This capability is supported at the database level by
an auto-navigate feature. That is, when an iteration is retrieved from the database,
the association between Iterated and Mastered is auto-navigated to retrieve the
corresponding master in a single query.
To take advantage of auto-navigate, perform the following actions:
1. Add derived attributes on the iteration for each master attribute that you want
to be viewed and/or queried along with the iteration. The "DerivedFrom"
model property must be as follows:
master> attribute_name
For example, part number is modeled on WTPart with the following:
DerivedFrom = master>number

2. To make derived attributes read-only, set their WriteAccess to something


other than Public.

Updating Master Attributes via the Iteration


The goal of this action is to be able to automatically update the master if any of its
attributes have been modified via derived attributes on the iteration. The
advantage is that clients have to deal directly with only one object, the iteration.
The recommended approach at a high level is to add a boolean "dirty" flag to the
iteration class which is set to true if any of the setter methods that update master
attributes are invoked. Next, implement a special save method that clients will use
to save the iteration instead of using PersistenceHelper.manager.save(Persistable
obj). This method is implemented in a lightweight service class so that it runs on
the server in the context of a transaction. It is implemented to check if the dirty
flag is true; if so, it will save the master as well as the iteration.

Customizing Business Logic 22-33


Updating the Master and Iteration Separately
Updating the master and iteration separately may be appropriate depending on the
business rules. For example, for parts that go through a design review life cycle,
modifying a master attribute would affect all versions, some of which are in a
"released" state that implies they should not be modified. Changing a master
attribute is significant because it violates the basic business rule that released parts
should not change. For this reason, the master class could have a more restrictive
set of access rules, and any changes to it would be against the master object
directly, not derived attributes on the iteration.
If this approach is taken, the client must update and persist masters and iterations
separately. There may still be derived master attributes on the iteration to facilitate
querying and/or read-only access of master attributes via the iteration. However,
these attributes would not be set via the iteration.

The Identifying Attributes


The identifying attributes that are part of the master are not updated by calling
setter methods, but rather by using IdentityService.changeIdentity. The client
must know about the master in order to pass the master to the IdentityService.
That is, the iteration can not be passed to the IdentityService. When the
IdentityService changes the identity, it re-persists the modified master; thus, the
client does not have to directly use the PersistenceManager to modify the master.
Master identifying attributes can only be set via the iteration before the object is
persisted. When the first iteration is saved, the master is automatically created and
saved as well. If you want to expose identifying attributes on the iteration,
perform the following steps:
1. Add a derived attribute on the iteration for the master identifying attribute by
setting the model property "Derived" to the following:
master> attribute_name
2. Set the attribute model property "Changeable" to "ViaOtherMeans" on the
master. This allows the attribute to be set only until the object is persisted.
After it is persisted, the IdentityService is the only way to change the value.
3. Add a protected setIdentificationObject method to the master which directly
sets the identifying attributes on the master from the IdentificationObject
values.
After the master is persisted, the identifying attributes can be changed only by the
IdentityService, which invokes the setIdentificationObject method on the master
via the IdentificationObject.setToObject method.
For additional information, see Identified Business Classes on page 22-2.

22-34 Windchill Customizer’s Guide


Overriding Accessors for Master Attributes Derived on the Iteration
Code generation is not yet capable of determining which subtype of Mastered,
such as WTPartMaster, is applicable in order to invoke the accessor methods
specific to a concrete Mastered class. This means that the accessors must be
implemented by hand. Following is an example for WTPart:
public String getName() {
/##begin getName% [ ]364F678B0148g.body preserve=yes
try { return ((WTPartMaster) getMaster()).getName(); }
catch (NullPointerException npe) { return null; }
/##end getName% [ ]364F678B0148g.body
}

public void setName( String a_Name )


throws WTPropertyVetoException {
//##begin setName% [ ]364F678B0148s.body preserve=yes
((WTPartMaster) getMaster()).setName( a_Name );
/##end setName% [ ]364F678B0148s.body
}

Customizing Business Logic 22-35


22-36 Windchill Customizer’s Guide
23
Customizing Change
Management

This chapter describes how to customize change management.

Topic Page
Change Management Delegates ........................................................................23-2

23-1
Change Management Delegates
The wt.change2 package has several delegates defined to allow customization.
The following is an overview to help you know where to start.

ChooseLifeCycleDelegate
ChooseLifeCycleDelegate is used within StandardChangeService2 by calling the
protected method chooseLifeCycle. In the chooseLifeCycle method, the delegate
is obtained from the Change2DelegateFactory. The chooseLifeCycle method is
not called if the change object is already persisted, because it would already have
a life cycle set. In the chooseLifeCycle method, the delegate mechanism is used
only if a life cycle has not yet been set.
// In any of the saveChange... methods, such as saveChangeRequest:
If changeItem is not persistent {
ChangeServiceHelper2.service.chooseLifeCycle (changeItem);
}

// In chooseLifeCycle
if changeItem has no lifecycle {
Set the lifecycle using the delegate;
}

When saving a change object, Windchill uses the ChooseLifeCycleDelegate


mechanism to assign a life cycle if and only if the change object is not yet
persistent and a life cycle is not assigned already. This means that the delegate
mechanism is effective only when creating a new change object. As a
customization, you could allow the user to select a life cycle from a drop-down
list in the HTML page and then, because the life cycle would already be set, the
delegate would not replace that life cycle.
The DefaultChooseLifeCycleDelegate uses a property file entry to get the name of
the life cycle that should be used.

ChooseFolderDelegate
ChooseFolderDelegate is used within StandardChangeService2. It is obtained
from the Change2DelegateFactory.
The Windchill vision of change management is that change issues, requests and
orders should be visible in folders so that a user can easily look for issues (or
suggestions), requests (issues that are being addressed), and orders (changes that
have been made). The investigations, proposals, analysis activities, and change
activities are tightly tied to other objects and they are not visible in folders.
Because these related objects need the same access control and other attributes of
their related object, which is in a folder, Windchill puts them in the same domain
as the related object that is in a folder. The ChooseFolderDelegate assigns one
ChangeItem to a folder/cabinet based on the folder/cabinet of another
ChangeItem.

23-2 Windchill Customizer’s Guide


The SynchronizedDomainChooseFolderDelegate assigns a CabinetManaged
object to the same domain as a CabinetManaged object or a Folderable object. It
assigns a Folderable object to the same folder as another Folderable object. It
throws an exception when asked to assign a Folderable object based on a
CabinetManaged object.
In addition, a listener is defined on the change2 service that listens for movement
of change issues, request, and orders. It moves their child objects (analysis
activities, change activities, change investigations, and change proposals) to the
same cabinet into which the parent object was just moved.

ConcreteAssociationDelegate
ConcreteAssociationDelegate is used within StandardChangeService2. It is
obtained from the Change2DelegateFactory.
There are many subclasses of ConcreteAssociationDelegate. Each one takes two
arguments: the two objects being linked. Each one returns the link object that
links the two objects. There is no mechanism for adding additional values for
attributes that belong on the link object, so this mechanism works best for link
objects that have not been customized with additional attributes.
One other complication with this delegate is that if you customize some of the
main classes, you may have to add properties file entries that may not seem
intuitively obvious.
Assume that you customize change order (that is, make a subclass of
wt.change2.WTChangeOrder2) in your myChange2 package within your
customization package and call it MyChangeOrder.
When looking up the appropriate subclass of
wt.change2.ConcreteAssociationDelegate, the following entry in section 9 of
wt.change2.change2.properties is being used when linking the change order to a
change request:
wt.services/svc/default/wt.change2.ConcreteAssociationDelegate/
wt.change2.WTChangeOrder2/wt.change2.WTChangeRequest2/
1=wt.change2.AddressedBy2Delegate/singleton

The reference to wt.change2.WTChangeRequest2 is in a field where inheritance is


applied. In other words, if you subclassed wt.change2.WTChangeRequest2 as
customization.myChange2.MyChangeRequest, then the delegate lookup process
could still use this line in the properties file, because
customization.myChange2.MyChangeRequest is a
wt.change2.WTChangeRequest2.
The reference to wt.change2.WTChangeOrder2 is in a field where inheritance is
not applied. In other words, if you subclassed wt.change2.WTChangeOrder2 as
customization.myChange2.MyChangeOrder, then the delegate lookup process
could not use this line in the properties file because the string
"customization.myChange2.MyChangeOrder2" does not match exactly the string
"wt.change2.WTChangeOrder2".

Customizing Change Management 23-3


All that is needed is another line in the properties file:
wt.services/svc/default/wt.change2.ConcreteAssociationDelegate/
customization.myChange2.MyChangeOrder/
wt.change2.WTChangeRequest2/
1=wt.change2.AddressedBy2Delegate/singleton

DisplayIdentificationDelegate
DisplayIdentificationDelegate is used within StandardChangeService2. It is
obtained from the Change2DelegateFactory. For further information, see the
section on implementing new display identification delegates in the identity
service description in the System Generation chapter on page 32-1.

23-4 Windchill Customizer’s Guide


24
Customizing Life Cycle
Administration

This chapter describes how to customize the life cycle administration.

Topic Page
Customizing the Display of Life Cycle Information.........................................24-2
Defining Customized Life Cycle Transitions....................................................24-3
Setting Up a Customized State-Based Versioning Scheme ..............................24-3

24-1
Customizing the Display of Life Cycle Information
The way life cycle state information is displayed, particularly in life cycle-
managed object properties pages, can be customized by setting configurable
components in the wt.lifecycle.lifecycleResource*.java files. You can set values
for the following entries:
STATES_SEPARATOR
When displaying a string of states, this value is the separator between each of
the states listed. Default is " - ".
CURRENT_STATE_BEGIN
When displaying a string of states, this value is the notation that a particular
state is the current state. Default is "<B>".
CURRENT_STATE_END
When displaying a string of states, this value is the notation that a particular
state is the current state. Default is "</B>".
DROPPED_STATE_BEGIN
This entry notes that the current state (usually dropped) is not found in the list
of current states. Default is " [".
DROPPED_STATE_END
This entry notes that the current state (usually dropped) is not found in the list
of current states. Default is "] ".
IS_AT_GATE
This value is used to indicate that Awaiting Promotion = true. Default is
"Yes".
IS_NOT_AT_GATE
This value is used to indicate that Awaiting Promotion = false. Default is
"No".
LABEL_BEGIN
This value is used when displaying any of the StateProcessor labels. Default is
"<B>".
LABEL_END
This value is used when displaying any of the StateProcessor labels. Default is
": </B>".
STATE_LIST_BEGIN
When the list of states is provided along with other information, this entry
differentiates the State list from other information in the display. Default is
"(".
STATE_LIST_END
When the list of states is provided along with other information, this entry
differentiates the State list from other information in the display. Default is
")".
HISTORY_LABEL
This entry is used when displaying a link to the Life Cycle History page.
Default is "History".

24-2 Windchill Customizer’s Guide


HISTORY_NOTATION_BEGIN
When the history link is provided along with other information, this entry
differentiates the History link from other information in the display. Default is
" (".
HISTORY_NOTATION_END
When the history link is provided along with other information, this entry
differentiates the History link from other information in the display. Default is
") ".

Defining Customized Life Cycle Transitions


You can create customized life cycle transitions that you can then define between
life cycle states using the Life Cycle Administrator. For example, to create a new
transition called "My Reject":
1. Add the following entry to
<Windchill>/wtCustom/wt/lifecycle/TransitionRB.rbInfo (create this file if it
does not exist):
MY_REJECT.value=Reject
MY_REJECT.shortDescription=Reject transition

2. Build the runtime resource bundles for the customized packages by entering
the following command from a windchill shell:
ResourceBuild wt.lifecycle.TransitionRB

The new transition will be added to the transitions that are available when you
create or update life cycles using the Life Cycle Administrator.
The new transition can be accessed programatically. You can invoke the
navigate() method to find the valid transitions between states using that new
transition, such as in the following code snippet:
WTKeyedMap rejectMap=new WTKeyedHashMap();
Set rejectSet = new HashSet();
State rejectState=State.toState("DESIGN");
rejectSet.add(rejectState);
rejectMap.put(<life_cycle_managed>, rejectSet);
WTKeyedHashMap returnMap =
(WTKeyedHashMap) LifeCycleHelper.service.navigate
(rejectMap,
Transition.toTransition("MY_REJECT"),
true);

The above call to navigate() returns the successor states to the DESIGN state on a
life cycle managed object (<life_cycle_managed>), following valid
MY_REJECT transitions.

Setting Up a Customized State-Based Versioning Scheme


Setting up a customized state-based versioning scheme consists of the following:

Customizing Life Cycle Administration 24-3


• Adding The Series To StateBasedVersioning.xml And Loading The File
• Making The Newly Added Version Schemes Available In The Lifecycle
Administrator
• Creating A Lifecycle Template Which Uses The New Version Series’
• Setting Up The Object Initialisation Rules
• How The Revision Scheme Can Be Used

Adding The Series To StateBasedVersioning.xml And Loading The File


1. Make a backup copy of the StateBasedVersioning.xml file, located under
<Windchill80>\loadFiles\pdmlink.
2. Append your versioning schemes to the existing file using a text editor so that
it matches your requirements.
The stated based series makes use of <seed name> elements within the xml
file to define the Version Series and the example below contains an additional
2 series’ ‘PROTOTYPE’ which will define versions ‘proto_1’ to ‘proto_10’
and ‘RELEASED’, which runs from ‘rel_A’ to ‘rel_F’. These series’ have
been added as extra “seeds” to the original NUMERIC and MILSTD, and will
be available as options in the Lifecycle Administrator “Version Series”
dropdown:

3. Load the file into Windchill using the following command:


C:\ptc\Windchill_8.0>java.wt.series.LoadFileBasedSeries C:\ptc\
Windchill_8.0>loadFiles\pdmlink\StateBasedVersioning.xml -load

4. You will be prompted to log in as a member of the Administrators group.

24-4 Windchill Customizer’s Guide


Observe the warning that THIS WILL OVERWRITE THE EXISTING
SERIES.
Once the file has been loaded, you will receive a message: “Successfully
saved FileBasedSeries”.

Making The Newly Added Version Schemes Available In The Lifecycle


Administrator
Customize the Lifecycle Administrator, adding the two seeds as options to the
‘Version Series’ drop-down.
This is done using the enumcustomise utility found in <Windchill>\bin, and the
file to modify is the Resource Bundle wt.series.SeriesRangeSelectorRB.
Ensure that the key that you add matches the name of the seed you have defined in
the StateBasedSeries.xml. Below is an example of how to add the PROTOTYPE
seed, which we added as a seed and loaded in Step 1.

Customizing Life Cycle Administration 24-5


Rebuild the resource:

Finally, rebuild the jars in a Windchill shell with the following command:
<Windchill>\ant\bin\ant –f <Windchill>\codebase\makejar.xml

Note that the extra series’ were added using the ‘Default’ locale in the
enumcustomize utility. This means that they will only be visible if the browser
language is set to English (US).

Creating A Lifecycle Template Which Uses The New Version Series’


Now that the “Version Series” dropdown contains the appropriate options, we can
proceed to create a Lifecycle Template which will use them.

24-6 Windchill Customizer’s Guide


In this instance, a lifecycle called prototype_released was created which uses the
PROTOTYPE version series in the Prototype phase, and the RELEASED version
series in the Released phase.

Setting Up The Object Initialisation Rules


Set up the Object Initialisation Rules so that the Object is associated with the
newly created Lifecycle, and takes the StateBased versioning scheme where the
seeds are defined.
The example below shows a modified initialisation rule for a WTPart.
<AttributeValues objType="wt.part.WTPart">

<!-- set the folder -->


<AttrValue id="folder.id"
algorithm="com.ptc.core.foundation.folder.server.impl.
FolderPathAttributeAlgorithm">
<Arg>/Default</Arg>
</AttrValue>

<!-- set the lifecycle -->


<AttrValue id="lifeCycle.id"
algorithm="com.ptc.core.foundation.lifecycle.server.impl.LifeCycleTemplateAttribute
Algorithm">

<Arg>
<!-- Translation of the word "Basic" must be the same as the
translation done in commonLifeCycles.xml -->
<?loc-begin key="BASIC_LIFECYCLE_NAME"
maxlen="30"?>Basic<?loc-end?>
</Arg>

Customizing Life Cycle Administration 24-7


</AttrValue>

<!-- set the team template -->


<AttrValue id="teamTemplate.id"
algorithm="com.ptc.core.foundation.team.server.impl.TeamTemplateAttributeAlgorithm"
>
<Arg>Default</Arg>
</AttrValue>

<!-- set the number to a generated number -->


<AttrValue id="number"
algorithm="com.ptc.windchill.enterprise.revisionControlled.server.impl.NumberGenera
tor">
<!-- add a V prefix for variant parts -->
<Value algorithm="wt.rule.algorithm.BooleanBranch">
<Value algorithm="wt.rule.algorithm.EqualsTest">
<Attr id="genericType"/>
<Arg>variant</Arg>
</Value>
<Arg>V</Arg>
<Arg></Arg>
</Value>

<!-- the sequence -->


<Arg>{GEN:wt.enterprise.SequenceGenerator:WTPARTID_seq:10:0}</Arg>
</AttrValue>

<!-- set the version info to a generated version info -->


<AttrValue id="MBA|versionInfo"
algorithm="com.ptc.core.foundation.vc.server.impl.VersionInfoGenerator">
<Arg>wt.series.HarvardSeries</Arg>
</AttrValue>
</AttributeValues>

Note: <If this rule is defined at Site or Organization level, object initialisation
rules defined at context level may need to be disabled.

Automatic Part Numbering - Upgrade Considerations


On any system upgraded to Windchill release 9.x or any new installation where
part Object Initialisation Rules are customized, the following must be considered.
Variant Part Creation fails when Part automatic numbering is turned off; Part
Object Initialisation Rules are customized to turn off automatic numbering. This
results in the failure of VariantPart creation (Request Deliverables action on
VariantSpecifications).
Variants are auto generated by the system and automatic numbering cannot be
turned off for the variant parts. If you need to turn off automatic numbering for
parts other than variants, the following code sample shows how to modify the Part
Object Initialisation Rules xml file for the "number" attribute.

24-8 Windchill Customizer’s Guide


<AttrValue id="number"
algorithm="wt.rule.algorithm.BooleanBranch">
<Value algorithm="wt.rule.algorithm.EqualsTest">
<Attr id="genericType"/>

How The Revision Scheme Can Be Used


The screenshots below show examples of a WTPart created and associated to the
above Lifecycle. The part initially started as version proto_1 and was revised to
proto_2.
The part was then promoted to the “Released” phase, then revised again.

Customizing Life Cycle Administration 24-9


Note: The version now shows rel_A, as defined in the StateBasedVersioning.xml
file in the beginning.

Caution: This procedure should be performed immediately after installation, and


before any objects are created in the Windchill system. If objects have already
been created using a different versioning scheme, then the behavior when these
objects are revised will be unpredictable.

24-10 Windchill Customizer’s Guide


25
Customizing Workflow
Administration

This chapter describes how to customize workflow.

Topic Page
Customizing Workflow HTML Templates .......................................................25-2
Customizing Change Management Workflow Process Templates ...................25-6
Customizing Promotion Request Workflow Processes...................................25-13
Customizing Workflow Events on an Object..................................................25-17
Customizing Workflow Task Pages ................................................................25-19
Refine and Review Workflow Transitions Best Practice................................25-27

25-1
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 chapter
on page 11-1. This section discusses the HTML client only as it applies to
workflow.

25-2 Windchill Customizer’s Guide


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

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

Customizing Workflow Administration 25-3


wt.clients.workflow.tasks.task.14=UserTask5
wt.clients.workflow.tasks.task.15=UserTask6
wt.clients.workflow.tasks.task.16=UserTask7
wt.clients.workflow.tasks.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=
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).

25-4 Windchill Customizer’s Guide


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]

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

Customizing Workflow Administration 25-5


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 Robot

Change Issue Process Sync on Request Association

Change Issue Process Listen for Request Disassociation

Change Issue Process Sync on Request Complete

25-6 Windchill Customizer’s Guide


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 3a) This conditional router checks the
the change issue has been immediately state of the associated change request.
disassociated with the change request. If it is in state Completed, the
If so, the workflow cycles back to 1a; workflow continues to 3b (the end of
otherwise, it continues to the sync the process). If it is in state Cancelled,
robot at 2b. the workflow loops back to a point
near the beginning of the process.
Otherwise, the workflow continues to
the sync robot at 3b.

Customizing Workflow Administration 25-7


2b) The Listen for Request 3b) The Sync on Request Complete
Disassociation sync robot listens for robot waits until the state of the
the event ISSUE_UNFORMALIZED associated change request changes. If
on the primaryBusinessObject, the state is Completed, the workflow
signaling the change issue has been continues to 3b (the end of the
disassociated from its change request. process). If it is in state Cancelled, the
This causes the sync robot at 3b (‡) to workflow loops back to a point near
terminate, and the workflow to loop the beginning of the process.
back to the conditional at 1a. Otherwise, the sync 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

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

25-8 Windchill Customizer’s Guide


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 25-9


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.

25-10 Windchill Customizer’s Guide


This change resulted in the following improvements:
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.
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.

Customizing Workflow Administration 25-11


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.

25-12 Windchill Customizer’s 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 25-13


Promotion Request Review Process

Key Customization Points


You must keep the following key points in mind when customizing these
workflows.

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

25-14 Windchill Customizer’s Guide


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";
}
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 25-15


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.

25-16 Windchill Customizer’s 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 the Managing
Customizations chapter on page 5-18).
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.

Customizing Workflow Administration 25-17


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

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.

25-18 Windchill Customizer’s 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
• Rendering PBO UI Components
• Auto Create Change Notice customization
• Auto Create Change Notice customization
• Implementing customized Task Page JSP

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 25-19


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

25-20 Windchill Customizer’s Guide


The following table lists the paths that can be used for tablePageLink for a
specific object.

PBO Component Path Available Function

Affected Data /netmarkets/jsp/change/affectedDat • Change Request-


aTable.jsp WTChangeRequest2
• Change Issue or Variance-
ChangeIssue

Affected End Items /netmarkets/jsp/change/affectedEnd • Change Request-


ItemsTable.jsp WTChangeRequest2
• Change Issue or Variance-
ChangeIssue

Affected Items /netmarkets/jsp/changeTask/affecte • Change Task-


dItemsTable.jsp WTChangeActivity2

Affected and /netmarkets/jsp/changeTask/affecte • Change Task-


Resulting Items dAndResultingItems.jsp WTChangeActivity2

Attributes and /netmarkets/jsp/object/attributes.jsp • Change Request-


Attachments (no attachments for CA) WTChangeRequest2
• Change Notice -
WTChangeOrder2
• Change Task-
WTChangeActivity2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice -
PromotionNotice

Annotations /netmarkets/jsp/annotation/annotati • Change Request-


onChangeTable.jsp WTChangeRequest2
• Change Task-
WTChangeActivity2
• Change Issue or Variance-
ChangeIssue

Customizing Workflow Administration 25-21


PBO Component Path Available Function

Baselines /netmarkets/jsp/object/relatedBaseli • Change Request-


nes.jsp WTChangeRequest2
• Change Notice -
WTChangeOrder2
• Change Task-
WTChangeActivity2
• Change Issue or Variance-
ChangeIssue

Contexts /netmarkets/jsp/object/relatedConte • Change Request-


xts.jsp WTChangeRequest2
• Change Notice -
WTChangeOrder2
• Change Issue or Variance-
ChangeIssue

Discussion /netmarkets/jsp/forum/discuss.jsp • Change Request-


WTChangeRequest2
• Change Notice -
WTChangeOrder2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice -
PromotionNotice

Maturity History /netmarkets/jsp/history/maturityHis • Change Request-


tory.jsp WTChangeRequest2
• Change Notice -
WTChangeOrder2
• Change Task-
WTChangeActivity2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice -
PromotionNotice

Promotion Items /netmarkets/jsp/promotionRequest/ • Promotion Notice -


promotionItemsTable.jsp PromotionNotice

25-22 Windchill Customizer’s Guide


PBO Component Path Available Function

Reassignment

Related Changes /netmarkets/jsp/change/relatedChan • Change Request-


ges.jsp WTChangeRequest2
• Change Notice -
WTChangeOrder2
• Change Issue or Variance-
ChangeIssue

Resulting Items /netmarkets/jsp/changeTask/resulti • Change Task-


ngItemsTable.jsp WTChangeActivity2

Routing/Process /netmarkets/jsp/workflow/processH • Change Request-


istory.jsp WTChangeRequest2
• Change Notice -
WTChangeOrder2
• Change Task-
WTChangeActivity2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice -
PromotionNotice

Subscriptions /netmarkets/jsp/subscription/object • Change Request-


Subscriptions.jsp WTChangeRequest2
• Change Notice -
WTChangeOrder2
• Change Task-
WTChangeActivity2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice -
PromotionNotice

Customizing Workflow Administration 25-23


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 Syntax for including on JSP

Promotion Notice Table If the PBO is a PromotionNotice, the customizer


may include the promotion objects table as follows:
<workItem:setPrimaryBusinessObject/>

<workItem:promotionObjects/>

Notebook Table <workItem:notebook displayType="Table"/>

Discussion Table <workItem:discussions


displayType="Table"/>

Routing History Table To display routing history for all activities:


<tags:routingStatus dispProcess="All"/>

To display routing history for just the current


activity:
<tags:routingStatus/>

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.

Reassignment 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 ChangeManagement-


service-properties.xconf:

25-24 Windchill Customizer’s Guide


<Service context="default"
name="com.ptc.windchill.enterprise.change2.handler.AutomateCreateC
hangeNoticeHandler">

<Option
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 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's 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-of-the-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.
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.

Customizing Workflow Administration 25-25


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

25-26 Windchill Customizer’s Guide


Refine and Review Workflow Transitions Best Practice

Objective
Sometimes there is a 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.

Scope/Applicability/Assumptions
• It is assumed that you are familar with change management concepts such as
resulting data.
• It is assumed that your Windchill system supports Refine and Review
workflow transitions.
• It is assumed that you have administrator level aceess to the Workflow and
Life Cycle applications.

Intended Outcome
To understand how to customize the workflow to use the Refine and Review
transitions.

Solution

Prerequisite knowledge
To follow this process you need to have an understanding of the following:
• Knowledge of creating and modifying a workflow

Adding the transitions


1. In Windchill navigate to Site > Utilities > Workflow Administrator.
2. Edit the Change Notice Workflow.
3. Upon editing the Change Notice workflow, add a new Expression Robot.
Click Execute Expression ( ) and then select the workflow to add the
transition.
4. Link the expression with the workflow so it is executed.
a. Modify or create new arrows by using the Action tool.
b. Use the CTRL key and dragarrows between states. In the example below,
it has been added just before the Change Notice is submitted.

Customizing Workflow Administration 25-27


5. After it has been added to the Change Notice workflow’s execution, you must
make it a Refine or Review transition. To do so, you must add some code to
the expression. Double click the new Expression and then select the
Expression tab.
6. To add a Refine transition add the following expression code to the transition:
wt.maturity.TransitionHandlerFactory.getInstance().transitionTa
rgets(primaryBusinessObject,wt.life
cycle.Transition.toTransition(“REWORK"),false);

7. To add a Review transition add the following expression code to the


transition:
wt.maturity.TransitionHandlerFactory.getInstance().transitionTa
rgets(primaryBusinessObject,wt.life
cycle.Transition.toTransition("REVIEW"),false);

Caution: If you copy and paste the transition code out from this document
and directly into Windchill, the quotes will be invalid characters for the java
compiler. It is suggested that you paste it into a Notepad first, copy it from
Notepad, then paste into the Windchill Expression box.

The following example shows a Review transition:

8. Select Check Syntax.


9. Save your changes and then Exit the Change Notice Workflow window. You
now have a working copy of the new workflow with a Review Transition.

25-28 Windchill Customizer’s Guide


Understanding the transitions
After you modify the default Change Notice life cycle to contain the Refine and
Review transitions, the resulting workflow will that look something like the
following example.

Understanding the execution of Refine and Review


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

Customizing Workflow Administration 25-29


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

Note: In the followingscenario, the part is using the Two Phase Development
Life cycle instead of the default one.

1. In Windchill navigate to Site > Utilities > Life Cycle Administrator.


2. Edit the Two Phase Development Life Cycle. You will have to check it out.
3. Configure what the new state will be when the Review transition is executed.
For this example, 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:

4. Configure what state should do if it is under the Refine transition. Keep in


mind this would likely be useful to use just after the Review has occurred.

25-30 Windchill Customizer’s Guide


Because of this, when the Change Notice is in Under Review state, use the
Refine transition to change the object back into something editable. To do
this, we will change the state to Production Change:

5. Once the changes are made, click Save.


6. Click OK.
7. Back in the Life Cycle Administrator, check in the changes to the Two Phase
Life cycle.

Vefifying the changes


Verify the changes within the UI.
1. Create a few new Parts to ensure they are all in the design state.
2. Copy the new Parts to the clipboard.
3. Launch the Create Change Notice wizard.

Customizing Workflow Administration 25-31


4. On the implementation table of the Change Notice wizard, find the Default
Change Task, and edit it.
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 as shown 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.

25-32 Windchill Customizer’s Guide


26
Customizing Workgroup
Managers

This chapter describes how to customize workgroup manager.

Topic Page
Customizing and Administering Pro/ENGINEER Wildfire .............................26-2

26-1
Customizing and Administering Pro/ENGINEER Wildfire
See the "Customizing and Administering Pro/ENGINEER Wildfire" chapter in
the Using Pro/ENGINEER Wildfire with Windchill guide for information.
This chapter presents customization and administration information and
recommendations for using Pro/ENGINEER Wildfire integrated with Windchill
PDMLink and Windchill ProjectLink. The primary audience is Pro/ENGINEER
and Windchill system administrators; however, much of the information can be
useful to end users as well.
The topics presented include Pro/ENGINEER configuration information
(environment variables and config.pro options) that applies to the interaction with
Windchill, and Windchill server-side preferences, as well as specific information
on parameter mapping, parameter customization, customizing object naming,
automated part creation, supporting custom parts, and customizing the user
interface. In addition, recommendations for system configuration and
performance tuning are offered.
The final section lists and describes Windchill preferences that are especially
relevant to the interaction with Pro/ENGINEER.

26-2 Windchill Customizer’s Guide


27
Customizing Windchill
Visualization Services

This chapter describes how to customize Windchill Visualization Services.

Topic Page
Custom Publishing ............................................................................................27-2

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

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

27-2 Windchill Customizer’s Guide


• 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 Additional Resources section on page 27-17 includes references to


many or all of these subjects.

Solution Elements

Element Type Description

Publisher.class Class file Contains api for doPublish needed for


invoking publishing from code.
Runtime Location: <Windchill>\
codebase\com\ptc\wvs\common\ui

PublisherAction.class Class file Used to create the optional actionString


to be passed to the doPublish method in
Publisher. See JavaDoc for details.
Runtime Location: <Windchill>\
codebase\com\ptc\wvs\common\ui

VisualizationHelper.class Class file Contains helper api’s such as


findRepresentable and
getRepresentation often needed in
custom code.
Runtime Location: <Windchill>\
codebase\com\ptc\wvs\common\ui

ScheduleJobs.class Class file Contains getCurrentContainer method


needed when writing custom schedule
jobs.
Runtime Location:
<Windchill>\codebase\com\ptc\wvs\
server\schedule

wvs.properties Properties file Contains specific properties used with


the Windchill 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:

Customizing Windchill Visualization Services 27-3


• doPublish from Publisher class – see Simple Publish on page 27-4
• PublisherAction class for advanced use of doPublish – see Advanced Publish
on page 27-5
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 it’s 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);

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”,
“My Description”, Publisher.EPM, null,
0);

27-4 Windchill Customizer’s Guide


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 ProductView 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();
}

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,

Customizing Windchill Visualization Services 27-5


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.newObjectRefer-
ence(mydoc).toString();
PublisherAction pa =
new PublisherAction(PublisherAction.DOCUMENTFILE, “doc3.doc”);
Publisher pub = new Publisher();
boolean result = pub.doPublish(true, true, objRef, (Config-
Spec)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.

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 27-6
• getRepresentation and getRepresentations from VisualizationHelper class
– see getRepresentation on page 27-7
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 aren’t 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 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

27-6 Windchill Customizer’s Guide


are no actively associated parts, it simply returns the object you passed in. The
method signature is shown below:
public Representable findRepresentable(Persistable 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)

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)

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 can’t be found with the supplied name, null will be returned.
public QueryResult getRepresentations(Persistable 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:

Customizing Windchill Visualization Services 27-7


• Creating a custom schedule job step-by-step and using supported api
getCurrentContainer from ScheduleJobs class – see Custom Schedule Job
Fundamentals on page 27-8
• Incorporating the use of doPublish from the Publisher class in your custom
schedule job – see An Advanced Technique for Custom Schedule Jobs on
page 27-10

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

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 default="MyCustomJob" name="myJob.description"/>
<Property default="ext.wvs.CustomJobs" name=" myJob.class"/>
<Property default="myCustomJob" name=" myJob.method"/>
<Property default="true" name=" myJob.enableOnContainers"/>
<Property 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.

27-8 Windchill Customizer’s Guide


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();
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),
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;
}

Customizing Windchill Visualization Services 27-9


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

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.

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

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 section (see page
27-8) 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 the Procedure – Invoking Publishing from Custom
Code/Workflow section (see page 27-3) with the Custom Schedule Job
Fundamentals section (see page 27-8) 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);

27-10 Windchill Customizer’s Guide


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);
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();
pub.doPublish(false, true, objRef, (ConfigSpec)null,
(ConfigSpec)null, true, "My Rep",
"My Description", Publisher.NONE, null, 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 the Custom Schedule Job Fundamentals section
(see page 27-8), but notice the use of the doPublish method shown in bold. This

Customizing Windchill Visualization Services 27-11


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 the Procedure – Invoking Publishing from Custom Code/Workflow
section (see page 27-3) for see other useful ways to use the doPublish method.

Procedure – Customizing 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 27-12
• publish.service.filterdocumentpublishmethod – see Filter Publishing for
WTDocument Check-in or Upload on page 27-13
• Incorporating the use of doPublish from the Publisher class in your custom
hook code – see An Advanced Technique for Custom Check-in Based
Publishing on page 27-14

Filter Publishing for EPMDocument Check-in


Once publishing is configured for an Authoring Application (i.e.
Pro/ENGINEER) 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 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.

27-12 Windchill Customizer’s Guide


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

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

Customizing Windchill Visualization Services 27-13


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 WTDocument’s 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;
}
}
return Boolean.TRUE;
}

An Advanced Technique for Custom Check-in Based Publishing


Using the techniques in the Filter Publishing for EPMDocument Check-in section
(see page 27-12) and the Filter Publishing for WTDocument Check-in or Upload
section (see page 27-13) 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 the Procedure – Invoking Publishing from Custom
Code/Workflow section (see page 27-3) with the concepts in the Filter Publishing
for EPMDocument Check-in (see page 27-12) and Filter Publishing for
WTDocument Check-in or Upload (see page 27-13) sections 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,
"My Rep", "My Description", Publisher.EPM, null, 0);

27-14 Windchill Customizer’s Guide


return Boolean.FALSE;
}

This is the same example used in the Filter Publishing for EPMDocument Check-
in section (see page 27-12), 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 the Procedure – Invoking Publishing from Custom Code/Workflow
(see page 27-3) for see other useful ways to use the doPublish method.

Procedure – Customizing General Publishing


This section details how to:
• Use the property-driven hook: publish.service.filterpublishmethod – see
Filtering All Publishing on page 27-15
• Incorporate the use of doPublish from the Publisher class in your custom
hook – see An Advanced Technique for General Publishing on page 27-16

Filtering All Publishing


In addition to the filters specifically for EPMDocuments and WTDocuments
described in the Procedure – Customizing Check-in Based Publishing section (see
page 27-12), 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 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"/>

Customizing Windchill Visualization Services 27-15


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.
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 the Procedure – Invoking Publishing from Custom
Code/Workflow section (see page 27-3) with the Filtering All Publishing section
(see page 27-15) 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);

27-16 Windchill Customizer’s Guide


} catch (WTException wte) {
wte.printStackTrace();
}
return Boolean.FALSE;
}

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 (f.k.a. CAD 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 the Procedure – Creating Custom Schedule Jobs section (see page
27-7) 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 10’s or 100’s of thousands of results.

Custom Check-in Filtering Performance


Keep in mind with using the check-in filter techniques shown in the Procedure –
Customizing Check-in Based Publishing section (see page 27-12) 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.

Customizing Windchill Visualization Services 27-17


Related 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

27-18 Windchill Customizer’s Guide


28
Report Generation

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

Topic Page
Overview ...........................................................................................................28-2
Basic Report Example .......................................................................................28-2
Import and Export of Report Templates..........................................................28-11
Customization Details .....................................................................................28-15
Cognos Presentation Customization................................................................28-38
Reporting Info*Engine Task Data Source Customization ..............................28-44
Report Loading................................................................................................28-50
ReportTemplate Data Source Customization ..................................................28-59
Reporting Input Page Customization ..............................................................28-63
Report Localization Customization.................................................................28-68
Report Selection List Customization...............................................................28-74

28-1
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


In this example, a new report is created. The report will list all the objects in a
specific cabinet and contain information similar to that displayed when browsing
folders. The difference is that this report will show a flattened view as opposed to
a hierarchical view. The results displayed in this example reflect demo data that
has been loaded.
This section includes the following topics:
• Query
• Report Parameters

Query
The following steps show how to create the initial query for the report:
1. Create a new report template object and specify the query using the Query
Builder user interface, as follows. (For detailed usage instructions, use the
Query Builder online help.)
a. From Report Manager, click the New button. The Query Builder interface
appears (see figure below).
b. To add classes for the query, click the Add button on the From tab. Select
the Foldered and Cabinet classes. These classes will be used as the basis
for the query.

28-2 Windchill Customizer’s Guide


c. Select the name attribute of these classes by clicking the Add button on
the Select tab.

Report Generation 28-3


d. Every foldered object contains a reference to its cabinet. Add a reference
join between the foldered object and its associated cabinet by selecting
Query > Create Join. In the Create Join dialog box, select these classes
and the Cabinet reference association, then click the OK button.

e. Add criteria for filtering the results to only a single cabinet. On the
Criteria tab, set the following values, as shown in the following figure:

Field Value

Alias Cabinet

Attribute Name

Operator =

Value System

28-4 Windchill Customizer’s Guide


f. Preview the data to see if the query has been constructed properly by
selecting Query > Preview. A figure similar to the following appears.

g. Save the report in Windchill by selecting File > Save.

Report Generation 28-5


2. Execute this report as follows.
a. Select Report > Generate. (The Generate Report action is also available
when viewing the properties for a report template object.)
b. From the report generation form, click Standard, HTML (with sorting),
as the output format and click the Generate button.

28-6 Windchill Customizer’s Guide


Report Parameters
The initial report includes criteria for filtering the results based on cabinet name.
In this example, the name is System. For most reports, it is desirable to have
parameters that can be specified at execution time. This is accomplished using
parameters in the criteria, as shown in the following steps:
1. Edit the Foldered report template to change the criteria to use a parameter, as
follows:
a. From Report Manager, select the Foldered report and then click the
Update button to launch Query Builder.
b. On the Criteria tab, change the value of the Type field from "Constant"
to "Parameter" and specify a parameter name in the Name field, in this
case, "Cabinet Name".

c. Save the report template.

Report Generation 28-7


2. Execute the report, as follows:
a. Select Report > Generate.
The report generation form now specifies the parameter name, Cabinet
Name.
b. Enter a valid cabinet name in this field, in this case, System, and click the
Generate button.
If this field is left empty, the associated criteria is dropped. In this
example, if the Cabinet Name field was left empty, the query would
return all Foldered objects in any cabinet.

28-8 Windchill Customizer’s Guide


Another way to specify values dynamically is to use report parameter macros.
Macros specify values that are derived by the system at report execution time. An
example of a macro is CURRENT_USER_NAME. This macro returns the name
of the current user and is useful for showing information related to the user
running a report.
Macros can be specified for constants and parameters within the Query Builder
user interface. You can also enter macro names in the report generation form. The
following are predefined macros:

Name Description Type

CURRENT_USER_NAME Name attribute of the current String


authenticated user.

CURRENT_TIME Current system time. The time String


is formatted as a Java string
using SimpleDateFormat and
the method server timezone
(specified by
wt.method.timezone).

Report Generation 28-9


The following steps show how to put a macro in the report generation form:
1. Edit the Foldered report template to change the criteria to use a macro for the
parameter default as follows:
a. Select the Foldered report and then click the Update button to launch
Query Builder.
b. On the Criteria tab, change the value of the Default Value field from
"System" to "CURRENT_USER_NAME" using the drop-down list.

c. Save the report template.


2. Execute the report by selecting Report > Generate.
The report generation form now specifies the macro and the results show
foldered items only in the current user’s personal cabinet.
If demo data has been loaded, several example reports are available within the
Windchill folder System/Reports. These sample reports provide examples of the
types of reports that are possible. The following section contains more
information on loading these sample reports.

28-10 Windchill Customizer’s Guide


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

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.
• No entry, which requires the user
to select a format style at report
template generation time.

Report Generation 28-11


csvReportTemplate element Description

csvservice If the XSLT designation is DEL, this


column is required. The formats
currently available are as follows:
HTML
CSV
TSV
XML
PDF
HTMLWithSorting
HTMLWithMerging
MSWord2000Portrait
MSWord2000Landscape

csvContainerPath Optional. This column specifies a


container where the report should be
stored. If no value is specified, the site
container is used by default.

csvurl1 If the XSLT designation is URL, this


column is required and should contain
a URL pointing to a customized XSLT
stylesheet.

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

csvinputPage Optional. This entry specifies an input


page for the Report.

csvresourceBundle Optional. This entry specifies a


resource bundle for the Report.

28-12 Windchill Customizer’s Guide


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 absolute path of a user-defined XML file.
java wt.query.template.LoadReportTemplate
loadReports.xml
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.

Report Generation 28-13


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,
default 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
container 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

28-14 Windchill Customizer’s Guide


Customization Details
After a report exists, there are a number of ways to customize various aspects of
the report. This section gives detailed information on the following items:
• Customizing the Query
• Customizing the Report Format
• Customizing the Report Generation Client
• Customizing the Report Generation URL
• Customizing Macros
• Customizing Query Builder Types

Customizing the Query


Customizing the query involves editing the query using the Query Builder user
interface. An existing query is opened, edited, and then saved. The new query can
then be used immediately in reports.
The following steps show how to add additional attributes of the foldered object to
the query results:
1. Open the existing Foldered report template object using the Report Manager
Update button.

Report Generation 28-15


2. From the Select tab, click the Add button. Select the Location attribute and,
under Persist Info, select the Last Updated attribute. (To add multiple
attributes, hold the CTRL key while selecting them.)

3. Re-order the columns as necessary.


4. Preview the data to make sure the query is correct.
5. Save the query. The existing query is then overwritten.
6. Execute the report.

Customizing the Report Format


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

28-16 Windchill Customizer’s 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:1
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:2
http://www.w3.org/TR/xslt

For additional information about XSLT, refer to the What is XSLT? link and the
Resources area currently available at the following URL:3
http://www.xml.com

1. If you have difficulty with this URL, try the site URL www.w3.org.
2. If you have difficulty with this URL, try the site URL www.w3.org.
3. If you have difficulty with this URL, try the site URL www.xslinfo.com.

Report Generation 28-17


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"

XSLT Stylesheet Standard Format Name Description

identity.xsl XML Performs the identity


transformation on the XML
query results; that is, it outputs
the XML input.

csvFormat.xsl CSV (Comma Separated Produces comma-separated-


Variable) values format (useful for
reading into spreadsheets, and
so forth).

tsvFormat.xsl TSV (Tab Separated Variable) Produces tab-separated-values


format (useful for reading into
spreadsheets, and so forth).

simpleHtmlFormat.xsl HTML Produces a simple HTML


format. Unlike the other HTML
formats provided, this format
does no extra formatting on
numeric columns.

htmlWithSorting.xsl HTML (with sorting) Similar to


simpleHtmlFormat.xsl except
that sorting is provided through
hyperlinks on the column
headers.

htmlWithMerging.xsl HTML (with merging) Similar to


simpleHtmlFormat.xsl except
that vertically duplicated cells
are merged under certain
conditions. This is a time-
consuming transformation
compared to the others
provided.

28-18 Windchill Customizer’s Guide


XSLT Stylesheet Standard Format Name Description

sortedHtmlAsXML.xsl Produces the same results as


htmlWithSorting.xsl except
that the output is well-formed
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.

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

msw2000ls.xsl Microsoft Word 2000 HTML Produces a simple HTML


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

msw2000p.xsl Microsoft Word 2000 HTML Same as msw2000ls.xsl except


(Portrait) the result has portrait page
orientation.

Report Generation 28-19


XSLT Stylesheet Standard Format Name Description

xslfo.xsl PDF 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/post
procmap/application/xslfo+xm
l
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.

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

28-20 Windchill Customizer’s Guide


XSLT Stylesheet Standard Format Name Description

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

barChart.xsl Produce various types of charts


llineChart.xsl corresponding to their names.
pieChart.xsl The first result column is
scatterChart.xsl 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/svg/vie
wer/install/main.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/post
procmap/image/svg+xml
/wt/query/report/template/post
procmap/svgRasterizer/rasterF
ormat

Report Generation 28-21


XSLT Stylesheet Standard Format Name Description

includes/linker.xsl 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.

includes/excelWebQueryBase. The shared implementation


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

28-22 Windchill Customizer’s Guide


XSLT Stylesheet Standard Format Name Description

includes/chart.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 be captured as well by
implementing
wt.query.template.Chartable
interface and replacing
"wt.query.template.ChartCreat
er" in this file with the name of
the custom Chartable
implementation.

includes/msw2000.xsl 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.

includes/htmlWith The shared implementation


SortingBase.xsl behind htmlWithSorting.xsl
and sortedHtmlAsXML.xsl.
This stylesheet is intended
solely for inclusion from other
stylesheets.

includes/localize String.xsl 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.

Report Generation 28-23


XSLT Stylesheet Standard Format Name Description

includes/urlEncode.xsl 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.

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

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.

28-24 Windchill Customizer’s Guide


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.com’s annotated XML specification, currently available at the
following URL:4
http://www.xml.com/pub/axml/axmlintro.html

The W3C unannotated, original version of the XML specification is currently


available at the following URL:5
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.

4. If you have difficulty with this URL, try the site URL www.xml.com.
5. If you have difficulty with this URL, try the site URL www.w3.org.

Report Generation 28-25


New Formats
Besides modifying existing XSLT, you can also author entirely new XSLT
stylesheets. The XSLT standard is still relatively new, however, and therefore
editors that accurately display the actual appearance are not yet widely available.
You can, however, author new stylesheets without any such tools 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.6
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.

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

28-26 Windchill Customizer’s Guide


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 Name</name>
<description>Report Description</description>
<objectIdentifier>Report Object Id</objectIdentifier>
<sourceSystem>Windchill Codebase URL</sourceSystem>
<sourceGateway>Windchill Gateway URL</sourceGateway>
<executingPrincipal>
<fullName>User’s Full Name</fullName>
<objectIdentifier>User Object ID</objectIdentifier>
</executingPrincipal>
<timeOfExecution>Time when Executed</timeOfExecution>
<locale>Locale of User</locale>
</metadata>
<auxData>
<dataItem name="requestParam1">value</dataItem>
. . .
<dataItem name="requestParamN">value</dataItem>
</auxData>
<qml>
. . .
</qml>
<actualParameter parameterId="ParamName1"> Value
</actualParameter>
. . .
<actualParameter parameterId="ParamNameN"> Value
</actualParameter>
<result>
<heading tag="column1TagName"
type="Java data type">column header</heading>
. . .
<heading tag="columnNTagName"
type="Java data type">column header</heading>
<row idx="1">
<column1TagName>value</column1TagName>
. . .
<columnNTagName>value</ColumnTagName>
</row>
. . .
<row idx="N">
. . .
</row>
</result>
</queryResult>

Report Generation 28-27


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 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
Each XML row would then contain a Part element like the following:
<Part branchID="dataFromBranchIdColumn"
type="dataFromTypeColumn">dataFromPartColumn</Part>

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.

28-28 Windchill Customizer’s Guide


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 Description

metadata Meta-information about the query


from which the data resulted and the
user executing it.

auxData The request parameters used.

qml Fully defines the details of the report


template query which was made (see
<Windchill
codebase>/wt/query/qml/qml.dtd for
further details).

actualParameters The query parameters used when


executing the query.

result The column headers and types, and the


rows of data.

Report Generation 28-29


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 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.ReportSAXTr
ansform and should be removed.
The format of these entries is that of the Windchilll application services
delegation mechanism.For more information see the Customizing
service.properties topic in the Developing Server Logic chapter on page 36-24. If
localization of the additional entries is required, edit the Java resource bundle
wt.query.template.TemplateResource.

Customizing the Report Generation Client


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 the Customizing HTML Clients Using the Windchill JSP
Framework chapter on page 11-1.
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). Reports
that use soft types (that is, types created using the Type Manager) should 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).

28-30 Windchill Customizer’s Guide


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, which are part of Java 2
v1.4, or access Saxon directly. For further information, see the Saxon Web page,
currently available at the following URL:
http://saxon.sourceforge.net

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 28-31


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

28-32 Windchill Customizer’s Guide


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


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: 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
form’s 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.

Report Generation 28-33


URL Parameter Name Description

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

format Specifies the format type:


formatDelegate or formatCustom.
This parameter is used only if the
report template object has no XSL
specification.

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

xsl1 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 only if the report template object
has no XSL specification and the
format URL parameter has a value of
"formatCustom".

28-34 Windchill Customizer’s Guide


URL Parameter Name Description

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

Customizing Macros
Customizing macros uses the standard Windchill application services delegation
mechanism (for further information, see the Customizing service.properties topic
in the Developing Server Logic chapter on page 36-24). This customization
example creates a new macro to automatically compute a cutoff time. A new
query is created that uses this macro and generates a report containing objects that
have been modified within the last three days.
Note that this example assumes you are familiar with Rational Rose and
Windchill code generation, and have completed the previous customization
examples.
1. Create a new implementation of the MacroExpressionProcessor interface
using Rational Rose and Windchill code generation 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. Generate the code for this class.

Report Generation 28-35


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


return new DateExpression(time);

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

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 Value

Class Foldered

Attribute thePersistInfo.modifyStamp

Operator >

Value TIME CUTOFF

Note that the time cutoff macro now appears in the drop-down list.
d. Save the query.
4. Execute the report.

28-36 Windchill Customizer’s Guide


Customizing Query Builder Types
Query Builder uses 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 modeled interfaces that do not
implement this interface, yet have subclasses that implement a Persistable
interface and can be used in queries. An example in the Windchill model 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 (for further information, see the
Customizing service.properties topic in the Developing Server Logic chapter on
page 36-24). 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.

Report Generation 28-37


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/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 28-59 for more details.

28-38 Windchill Customizer’s Guide


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

Report Generation 28-39


Solution Elements

Element Type Description

<MyDataSource> Cognos Cognos Object The Cognos object that is


Data Source used to query data from
Windchill.

<MyReport> Cognos Cognos Object The Cognos object for a


Report report that contains the
definition of the query and
specifies the presentation
formatting.

<MyReport> Windchill Windchill Object The Windchill object that is


Report 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
• Creating a Report in a non-Site context
• Deleting a Report

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.

28-40 Windchill Customizer’s Guide


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 >
<WindchillInstanceName> > Monitors > ReportingSystem”. From the
Operations tab, click “exposeReports”.
– Select the Edit Table button in Windchill Site/Reports to refresh the
page.
9. View the <MyReport> Report in Windchill. The object will be displayed in
the “Site > Reports” tab. 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 the “Home > Reports” tab 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>.

Report Generation 28-41


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
the "Product: <MyProduct> > Reports" tab.

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 Windchill UI to locate <MyReport> and select the “Delete”
action.

Note: The Reports tab table supports a multiple row delete action if the Reports
tab 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.
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

28-42 Windchill Customizer’s Guide


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 Business Administration Guide
for details. Directly modifying the associated objects is not supported.

Related 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 Business Administration Guide
– Windchill System Administration Guide

Related Websites
• http://support.cognos.com/support

Report Generation 28-43


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

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

28-44 Windchill Customizer’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 Type Description

<MyTask> Info*Engine Task 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
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

Report Generation 28-45


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

28-46 Windchill Customizer’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.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”.

Report Generation 28-47


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.

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

28-48 Windchill Customizer’s Guide


– com.ptc.windchill.enterprise.report

Related Customization Documentation


• None

Other Related Windchill Documentation


• Info*Engine User’s Guide (Prerequisite)
• Info*Engine Administration and Implementation Guide
• Windchill System Administrators Guide

Related Websites
• http://support.cognos.com/support

Report Generation 28-49


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 report’s 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/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>.
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.

28-50 Windchill Customizer’s Guide


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
• ReportManager User Interface
• Windchill Data Loading

Solution Elements

Element Type Description

<MyTask> Info*Engine Task The Info*Engine task for


retrieving and manipulating
Windchill data.

<MyReportTemplate> Windchill Object The Windchill object that


Windchill ReportTemplate specifies a query for retrieving
Windchill data.

<MyReportTemplateQML> XML File The XML file that specifies a


Windchill ReportTemplate query associated with a
Query Definition Windchill ReportTemplate.

<MyReportTemplateLoad> XML File The XML file that specifies


Windchill Data Load data loading directives
Specification associated with a Windchill
ReportTemplate.

<MyReport> Windchill Report Windchill Object 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.

Report Generation 28-51


Element Type Description

<MyReportLoad> Windchill XML File The XML file that specifies


Data Load Specification data loading directives
associated with a Windchill
Report.

<MyCognosReport> Cognos Cognos Object The Cognos object for a report


Report that contains the definition of
the query and specifies the
presentation formatting.

<MyCognosReportXML> XML File The XML file that specifies the


Cognos Report Query and query and presentation
Presentation Definition associated with a Cognos
Report.

<MyCognosReportAttributes> Properties File The Properties file that


Cognos Report Attributes 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”.
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.

28-52 Windchill Customizer’s Guide


Procedure – Loading a ReportTemplate Data Source
1. Create the file,
<WindchillHome>/loadFiles/reports/custom/<MyReportTemplateQML>.xml
using the ReportManager “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 ReportManager


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

Report Generation 28-53


<?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 tab 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/<MyCognosReportAttri
butes>.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=
#resourceBundle=

5. Load <MyCognosReport> using the following command.


windchill com.ptc.windchill.cognos.CognosProxy loadreports
<WindchillHome>/loadFiles/cognosReports/custom

28-54 Windchill Customizer’s Guide


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 procedure Procedure – Loading an Info*Engine Task Data Source
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 procedure Procedure – Loading a ReportTemplate Data Source
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 procedure Procedure – Loading a Windchill Report Object 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.

Procedure – Specifying Windchill Report Object Attributes


In the primary procedure Procedure – Loading a Windchill Report Object 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 Description

csvname Required. This entry specifies the Report’s 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.

Report Generation 28-55


csvReport Element Description

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.

csvreportTemplateNa Optional. This entry specifies the ReportTemplate


me name if 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.

csvreportTemplateCon Optional. This entry specifies the ReportTemplate


tainerPath name if the Report uses a ReportTemplate as its data
source. This element is used along with the
“csvreportTemplateName” 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, a single
Cognos Report is loaded.

28-56 Windchill Customizer’s Guide


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 procedure Procedure – Loading a Cognos Report above, only the
basic Cognos Report attributes are specified. The following are the additional
attributes that can be specified.

Property Name Description

type Optional. This entry specifies the Report’s type. The


valid values are report, query, and reportTemplate. If not
value is specified, then the default value is "report".

defaultName Required. This entry specifies the Report’s name.

defaultDescription Optional. This entry specifies a description of the Report.

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

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.

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 28-44
• ReportTemplate Data Source Customization on page 28-59

Report Generation 28-57


• Cognos Presentation Customization on page 28-38

Related Package/Class Javadoc


• Foundation module
– wt.query.template
– wt.query.qml
• 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 Administration and Implementation Guide
• Windchill System Administrators Guide
• ReportManager online help

Related Websites
• http://support.cognos.com/support

28-58 Windchill Customizer’s Guide


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

Solution
Use ReportManager 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 Generation 28-59


• ReportManager 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 Type Description

<MyReportTemplate> Windchill Object The Windchill object that


Windchill specifies a query for retrieving
ReportTemplate Windchill data.

Procedure – Creating a ReportTemplate Data Source


1. Navigate to the Windchill “Site > Utilities” and launch the “Report Manager”
utility.
2. From the “Report Manager” 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.

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.

28-60 Windchill Customizer’s Guide


1. Assume you have ReportTemplate create access in the organization
<MyOrg>.
2. In step 1, navigate to the “Utilities” tab under <MyOrg> instead of the Site
Utilities tab.
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 ReportManager 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:
windchill wt.load.LoadFromFile –d
<WindchillHome>/loadXMLFiles/DemoReports.xml –CONT_PATH /

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 28-44
• Cognos Presentation Customization on page 28-38

Report Generation 28-61


Related Package/Class Javadoc
• Foundation module
– wt.query.template
– wt.query.qml
• Reporting module
– com.ptc.windchill.enterprise.report

Other Related Windchill Documentation


• ReportManager online help (Prerequisite)
• Query Builder online help (Prerequisite)
• Windchill System Administrators Guide

Related Websites
• http://support.cognos.com/support

28-62 Windchill Customizer’s Guide


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

Report Generation 28-63


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 Description

<MyInputPage> JSP File The custom JSP page for specifying report
input parameter values.

<MyReport> Windchill Report Windchill Object 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.

Procedure – Specifying a Windchilll JSP Input Page


1. Create a Windchill JSP page,
<WindchillHome>/codebase/wtcore/jsp/<MyInputPagePackage>/<MyInputP
age>.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”;

28-64 Windchill Customizer’s Guide


%>
Name: <input type="text" name="<c:out value='<%=paramName%>'/>"
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” tab, 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” tab 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.

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.

Report Generation 28-65


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 report’s Data Source. The following is an example for
specifying this.
<input type="hidden" name="paramA" value="valueA"/>
<input 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 report’s Data Source. The following is an example
for specifying this.
<%
request.setAttribute("parametersToOmit",
Arrays.asList("param1"));
%>

Limitations
None.

28-66 Windchill Customizer’s Guide


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

Report Generation 28-67


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

28-68 Windchill Customizer’s Guide


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
• ReportManager User Interface

Solution Elements

Element Type Description

<MyTask> Info*Engine Task The Info*Engine task for retrieving and


manipulating Windchill data.

<MyTaskResource> Resource Bundle Info The resource bundle info file used to
Properties File localize Info*Engine task text items.

<MyReportTemplate> Windchill Object The Windchill object that specifies a


Windchill ReportTemplate query for retrieving Windchill data.

<MyReportTemplateResource Resource Bundle Info The resource bundle info file used to
> Properties File localize ReportTemplate text items.

<MyReport> Windchill Report Windchill Object 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.

<MyReportResource> Resource Bundle Info The resource bundle info file used to
Properties File localize Report text items.

<MyCognosReport> Cognos Cognos Object The Cognos object for a report that
Report contains the definition of the query and
specifies the presentation formatting.

Report Generation 28-69


Element Type Description

<MyCognosReportResource> Resource Bundle Info The resource bundle info file used to
Properties File 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 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 Manager" utility. From
the "Report Manager" UI, select <MyReportTemplate>, and click "Update" to
launch QueryBuilder. 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

28-70 Windchill Customizer’s Guide


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" tab, 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 and Procedure - Localizing a ReportTemplate
Data Source), 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.

Customization Points

Procedure - Localizing Cognos Report Static Text


When the above Procedure - Localizing a Cognos Report 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/<MyCognosReportXM
L>.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

Report Generation 28-71


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

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 Package/Class Javadoc


• Foundation module
wt.query.template
• Reporting module
com.ptc.windchill.enterprise.report

Related Customization Documentation


• Internationalization and Localization on page 40-1

28-72 Windchill Customizer’s Guide


Other Related Windchill Documentation
• Info*Engine User's Guide
• Info*Engine Administration and Implementation Guide
• Windchill System Administrators Guide
• ReportManager online help

Related Websites
• http://support.cognos.com/support

Report Generation 28-73


Report Selection List Customization
Several part related reports can be launched from the part’s information page by
clicking the corresponding report item from the "Related Reports" drop-down list.
Previously, this list of these reports and the order in which the reports were
displayed in the list could not be customized.
The report list infrastructure has been enhanced to allow the following
customizations:
• Customizing the order of the reports in the list
• Removing one or more reports from the list
• Adding new custom reports to the report list at any place in the list

Scope/Applicability/Assumptions
The processes described in this section are applicable to the following report
types:
• Part
• Part Configuration
• Part Instance
This section describes the process for customizing the report selection list. It does
not include information on how to author a report or load a report into a third party
reporting system. For any custom reports, it is assumed that they have been
authored and that a JSP file exists for each custom report that needs to be hooked
up to the existing report list.
It is assumed that the person doing the customization has access to make the
updated to <WindchillCodebase> directory.

Solution
The following section describes the process of customizing the report selection
list in detail.

Solution Elements

Element Type Description

service.properties properties Configuration point for mapping new <CustomDelegate>


to ProductStructureReportListDelegate interface
Run time Location:
<Windchill>\codebase\service.properties

28-74 Windchill Customizer’s Guide


Element Type Description

<CustomDelegate>.java java Implement the methods to create the Related Reports


drop-down list.

<customReport>.jsp jsp Used to gather some of the parameters that needs to


generate a report or pass on to another report generator.

partReportResource.rbInfo Resource bundle Optional. Used to define the localized names for reports
Runtime location:
<Windchill>/codebase/com/ptc/windchill/enterprise/part/
structure

Overview
1. Implement and compile the custom delegate that defines the list of reports,
including any custom reports to be displayed in the ‘Related Reports drop
down’ in the Product Structure Browser.
2. Author the Custom Report JSP file (and other related artifacts) corresponding
to the custom report(s) into the <Windchill>/codebase.
3. Add and build the localization entries for the custom report(s) and build the
localization resources.
4. Register the custom delegate by replacing the out of the box with the custom
delegate.
5. Restart Windchill for your changes to take effect.

Implement and compile the custom delegate


To customize the report list for a part, part instance, or part configuration, you
need to implement a custom delegate. There needs to be a separate custom
delegate for part reports, part instance reports, and part configuration reports.
The custom delegate must extend from
AbstractProductStructureReportListDelegate and must implement the required
method generateReportSelection. This is the method that contains the logic to
generate the report list.
AbstractProductStructureReportListDelegate has several helper methods (specific
to part report list, part instance report list and part configuration report list) that
can be used by this logic. Refer to the Javadoc for
AbstractProductStructureReportListDelegate for details on the helper methods.

Sample Code: Adding a new custom part report at the end of the existing part report list
If you want to add a new custom part report at the end of the existing (out of the
box) part report list. Assume that the new custom report has a JSP file
netmarkets/jsp/part/custom/myCustomReport.jsp.

Report Generation 28-75


import
com.ptc.windchill.enterprise.part.structure.AbstractProductStructu
reReportListDelegate

import
com.ptc.windchill.enterprise.part.structure.partReportResource

public class ProductStructureCustomPartReportListDelegate extends


AbstractProductStructureReportListDelegate {

public void generateReportSelection() {

// Generate out of the box report list


super. generateOutOfTheBoxReportList();

// Append Custom Report at the bottom


// partReportResource.CUSTOM_REPORT_LABEL is resource label for
the custom report
// name and is defined later in the document
super.generateCustomReport
(partReportResource.CUSTOM_REPORT_LABEL,
" netmarkets/jsp/part/custom/myCustomReport.jsp ");
}
}

Sample Code: Remove existing part reports from the report list
The following example shows the code to remove some of the existing part
reports from the list.
import
com.ptc.windchill.enterprise.part.structure.AbstractProductStructu
reReportListDelegate

public class ProductStructureCustomPartReportListDelegate extends


AbstractProductStructureReportListDelegate {

public void generateReportSelection() {

// Selectively add only the reports of interest

// Single-Level BOM
super.generateSingleLevelBOM();

// Single-Level BOM with Notes


super.generateNoteReport();

// Single-Level Consolidated BOM


super.generateSingleLevelConsolidatedBom();

// Multi-Level Components List


super.generateMultiLevelComponentList();

// HTML Multi-Level BOM


super.generateMultilevelBOM();

// Multi-Level BOM Compare

28-76 Windchill Customizer’s Guide


super.generatePLMMultilevelBomCompareQuery();

// Multi-Level BOM with Replacements


super.generateMultiLevelBOMWithReplacement();

// Multi-Level Where Used


super.generateMultilevelWhereUsed();

Author the Custom Report JSP file


The JSP file has the following information available as HTTP request parameters.

Parameter Name Description Value

hostName Windchill installed machine IP address String (Usually an IP address)

sessionId Windchill servlet session ID String

oid Context Object Reference of the String


persisted primary content item (part, or
Example: OR:wt.part.WTPart.:11045
part configuration or part instance)

part Version Reference of the context part. String


Only exists if the report was invoked
VR:wt.part.WTPart.:34023
from part info page.

part_instance Version Reference of the context part String


instance. Only exists if the report was
Example:
invoked from part instance info page.
VR:wt.part.WTProductInstance2:580
54

part_configuration Version Reference of the context part String


configuration. Only exists if the report
Example:
was invoked from part configuration
VR:wt.part.WTProductConfiguration
info page.
:32168

applyCSToTop A Boolean indicating whether to apply “true” or “false”


configuration specification to the top
level object criteria

applyDCSToUnresolved A Boolean indicating whether to use “true” or “false”


Latest Configuration Specification for
unresolved dependents

encodedConfigSpec Base64 encoded configuration String


specification criteria.

In case your reports require the access to the encoded configuration specification,
you can use
ProductStructureReportSelectorHelper.decodeConfigSpec(encodedConfigSpec)
to decode the configuration specification. ProductStructureReportSelectorHelper

Report Generation 28-77


can be found in the runtime location:
<Windchill>/codebase/com/ptc/windchill/enterprise/part/structure.

Example <customReport>.jsp
This is an example of how to access the JSP parameters.
<%
String hostName = request.getRemoteHost();
String sessionId = session.getId();
String oid = (String)request.getParameter("oid") ;
String applyCSToTop = (String)request.getParameter("applyCSToTop")
;
String part = (String)request.getParameter("part") ;
String encodedConfigSpec = (String)request.getParameter(
"encodedConfigSpec" );
String applyDCSToUnresolved =
(String)request.getParameter("applyDCSToUnresolved") ;
%>

<table cellpadding="0" cellspacing="0">


<tr><td>
<table width ="100%" cellpadding="0" cellspacing="0">
<THEAD><b>My Custom Report<br></b></THEAD>

<table width ="100%" cellpadding="10" cellspacing="1" border="1">


<tr>
<td align = "left" valign="top"><font size="-1"><b>Parameter
Name</b></font></td>
<td align = "left" valign="top"><font size="-1"><b>Parameter
Value</b></font></td>
</tr>
<tr>
<td align = "left" valign="top"><font size="-
1">hostName</font></td>
<td align = "left" valign="top"><font size="-1"><%=hostName%>
</font></td>
</tr>
<tr>
<td align = "left" valign="top"><font size="-
1">sessionId</font></td>
<td align = "left" valign="top"><font size="-1"><%=sessionId%>
</font></td>
</tr>
<tr>
<td align = "left" valign="top"><font size="-1">oid</font></td>
<td align = "left" valign="top"><font size="-1"><%=oid%>
</font></td>
</tr>
<tr>
<td align = "left" valign="top"><font size="-1">part</font></td>
<td align = "left" valign="top"><font size="-1"><%=part%>
</font></td>
</tr>
<tr>
<td align = "left" valign="top"><font size="-
1">applyCSToTop</font></td>

28-78 Windchill Customizer’s Guide


<td align = "left" valign="top"><font size="-1"><%=applyCSToTop%>
</font></td>
</tr>
<tr>
<td align = "left" valign="top"><font size="-
1">applyDCSToUnresolved</font></td>
<td align = "left" valign="top"><font size="-
1"><%=applyDCSToUnresolved%> </font></td>
</tr>
<tr>
<td align = "left" valign="top"><font size="-
1">encodedConfigSpec</font></td>
<td align = "left" valign="top"><font size="-
1"><%=encodedConfigSpec%> </font></td>
</tr>
</table>
</tr>
</table>

Sample Report Output


This is an example of the output generated by this JSP.

Parameter Name Parameter Value


hostName 132.253.8.149

sessionId D180CB2067B751629C8BA557A355D11D

oid wt.part.WTPart:78035

part VR:wt.part.WTPart:68117

applyCSToTop false

applyDCSToUnresolved false

encodedConfigSpec rO0ABXNyABh3dC5wYXJ0LldUUGFydENvbmZpZ1NwZWMAAAAAA
AAAAQQAAHhyABR3dC5lbnRlcnByaXNlLlNpbXBsZQAAAAAAAAA
BBAAAeHIADnd0LmZjLldUT2JqZWN0AAAAAAAAAAEEAAB4cLWF
MlThpvDmcNMGeSFFACwBAQ ….

Add and build the localization entries


1. To have the localized name for your custom report, add a new resource entry
in the
<WindchillCodebase>/com/ptc/windchill/enterprise/part/structure/partReport
Resource.rbInfo file. The localized report name can be used in the Related
Report drop-down list, or as the title in your custom report. For more
information see the Resource Info (.rbInfo) Files section on page 37-7 in the
Internationalization and Localization chapter.
For example:
CUSTOM_REPORT_LABEL.value=My Custom Report

Report Generation 28-79


CUSTOM_REPORT_LABEL.constant=CUSTOM_REPORT_LABEL
CUSTOM_REPORT_LABEL.comment=Label for Pick a Custom Report drop
down item

2. Build the resource bundle by executing the following command from a


windchill shell:
ResourceBuild
com.ptc.windchill.enterprise.part.structure.partReportResource

Register the custom delegate


Register the newly implemented custom delegate into
<WindchillCodebase>/service.properties. The service delegate mechanism uses
Java property files to specify the delegates that are used for each service. The
main property file is service.properties and located in /Windchill/codebase/.
For more information, see the Property Files section on page 2-9 in the The
Windchill Development Environment chapter.
• For a Part report, execute the following command from within <Windchill>
directory in Windchill shell:
xconfmanager -s
wt.services/svc/default/com.ptc.windchill.enterprise.part.struc
ture.ProductStructureReportListDelegate/reportSelector/wt.part.
WTPart/0=<Qualified Path>.<CustomDelegate>/duplicate -t
service.properties -p

• For a Part Instance report, execute the following command from within
<Windchill> directory in Windchill shell:
xconfmanager -s
wt.services/svc/default/com.ptc.windchill.enterprise.part.struc
ture.ProductStructureReportListDelegate/reportSelector/wt.part.
WTProductInstance2/0=<Qualified
Path>.<CustomDelegate>/duplicate -t service.properties -p

• For a Part Configuration report, execute the following command from within
<Windchill> directory in Windchill shell:
xconfmanager -s
wt.services/svc/default/com.ptc.windchill.enterprise.part.struc
ture.ProductStructureReportListDelegate/reportSelector/wt.part.
WTProductConfiguration/0=<Qualified
Path>.<CustomDelegate>/duplicate -t service.properties -p

Restart Windchill
You must restart the following for the changes to take effect:
• Apache
• Tomcat
• ServerManager
• Method Server

28-80 Windchill Customizer’s Guide


29
Customizing Event Audits

This chapter describes how the Windchill Auditing Framework is implemented


and explains how to extend the auditing framework to allow additional events to
be audited.

Topic Page
Introduction .......................................................................................................29-2
Overview of the Audit Event Framework .........................................................29-3
Capturing New Events.....................................................................................29-10

29-1
Introduction
The auditing framework provides a mechanism to enable event-based logging that
provides a historical record of who did what that caused changes in the Windchill
database. The security auditing feature also provides a mechanism to retain
historical records of security related events, such as privilege changes, team
changes, and denial of access. Security audit reporting is helpful to customers in
highly regulated industries that need to identify events that may have resulted in a
potential security breach. The following list provides possible application uses
that can be recorded:
• Who accessed the application?
• Who viewed or downloaded an object?
• Who changed this object?
• Who granted access to a specific user?
The Windchill Auditing Framework is a Windchill service that captures events
generated through normal application use, using a collection of classes and
configuration files that a customer modifies to indicate which specific events are
to be recorded in the audit log. Out-of-the-box, the auditing framework is enabled
at the global level. However, the only events that are enabled are License Usage
Reporting and Organization Usage. Any other specific events that you want
recorded in the audit log must be enabled on an individual basis.

29-2 Windchill Customizer’s Guide


Overview of the Audit Event Framework
The auditing configuration file
(<Windchill>/codebase/registry/auditing/configAudit.xml by default), defines
event/object pairs which need to be audited. Based on its configuration, the
auditing service registers itself as a listener for each auditable event which may be
generated by other Windchill services. Auditing only registers itself once per
event regardless of how many objects are being audited for that event.
The auditing service's listener is called when an event for which the auditing
service has registered is emitted by a Windchill service. After determining that the
event's target object is being audited, the auditing service determines which call
handler, or audit recorder, is responsible for processing the event. The auditing
recorder stores the event information in one or more tables. Common event
information is stored in the AuditRecord table by the default auditing recorder.
Some events have additional information which must be audited, using event-
specific tables and recorders.
Audit reports are generated from the auditing data stored by the recorders. Audit
reports are currently not customizable. The figure below shows a conceptual view
of the Windchill Auditing Framework.

Windchill Auditing Framework

Customizing Event Audits 29-3


ProjectAuditEvent Class
The ProjectAuditEvent class represents the basic auditing information being
stored for a single event. The ProjectAuditEvent class contains the following
information:

Attribute Name Description

eventKey Every AuditRecord corresponds to a Windchill event


(wt.events.KeyedEvent). This attribute is the Windchill event
key.

eventLabel This is the localized value of the external label for the event
represented by this AuditRecord. It is translated into the
server's locale when the AuditRecord is recorded in the
database

eventTime Time of the event.

userOrgName Organization the current user belongs to at the time the event
was emitted.

targetName The name of the target object of the event.

targetReference A reference to the target object of the event.

userName Name of the user that is the current principal when the event
happened.

userID Identifier of the object that is the target of the event.

IPAddress IP address of the client machine used when the event was
emitted.

targetType Type of the object that is the target of the event.

targetTypeBranchID Numeric ID of the control branch of the type of the target of


the event.

targetID Identifier of the object that is the target of the event.

targetNumber Number of the object that is the target of the event.

cageCode Cage code of the object that is the target of the event.

branchID Numeric ID of the control branch of the object that is the


target of the event.

workingBranchID Numeric ID of the working copy branch of the object that is


the target of the event.

versionID Version ID of the object that is the target of the event.

29-4 Windchill Customizer’s Guide


Attribute Name Description

masterID Identifier of the master of the object that is the target of the
event.

orgContainerID Identifier of the organization that hosts the application


container that owns the object that is the target of the event.

orgContainerName Name of the organization that hosts the application container


that owns the object that is the target of the event.

appContainerID Identifier of the application container that owns the object that
is the target of the event.

appContainerName Name of the application container that owns the object that is
the target of the event.

appContainerTypeBra Numeric ID of the type of the application container that owns


nchID the object that is the target of the event.

folderPath Folder path of the object that is the target of the event.

domainPath Domain path of the object that is the target of the event.

targetIdentity Identity of the object that is the target of the event.

lifecycleState Lifecycle state of the object that is the target of the event.

transactionDescription Transaction description associated with the transaction from


which the event was emitted.

The information contained in the AuditRecord class is sufficient for most events.
In certain situations, however, the Windchill Auditing Framework is required to
capture additional information specific to the event generated. The event-specific
information is stored in an event-specific table and is managed by an event-
specific object.
For example, when a user is added to or removed from a group, it is important to
note which user is involved and not just that the group membership was modified.
The class ModifyGroupEventInfo holds the additional information as a reference
to the user being added or removed. If multiple users were added or removed in a

Customizing Event Audits 29-5


single operation, all ModifyGroupEventInfo instances point to a single
AuditRecord instance. This is shown in the figure below.

Default and specific event information

29-6 Windchill Customizer’s Guide


Audit Recorders
For each class which manages event data stored in the database, a corresponding
audit recorder exists which is responsible for mapping the appropriate event
information to the members of the class. The AuditRecord class, representing the
base information stored for all events, is created and persisted by
wt.audit.configaudit.DefaultAuditEventRecorder. Each class representing
event-specific information also has a corresponding audit recorder. For example,
wt.audit.configaudit.ModifyGroupEventRecorder extends the default recorder
and creates the ModifyGroupEventInfo instances.

Example Audit Recorder Data Model

Windchill Auditing Framework Configuration


The configAudit.xml configuration file identifies which objects are being audited
for which event and what audit recorder to use. The top-level
<EventConfiguration> contains one or more <KeyEntry> and <ConfigEntry>
elements.
The <KeyEntry> elements identify which events should be treated as multi-object
events (available only as of 8.0).
EventConfiguration dtd (part 1)
<!ELEMENT EventConfiguration (KeyEntry*, ConfigEntry*)>
<!ATTLIST EventConfiguration
enabled (true | false) #REQUIRED
>
<!ELEMENT KeyEntry EMPTY>
<!ATTLIST KeyEntry
eventKey CDATA #REQUIRED
multiObject (true | false) #REQUIRED
>

At the global level, the enabled attribute for <EventConfiguration> determines


whether the Windchill Auditing Framework is loaded and initialized. If
enabled="false", no auditing occurs and rest of the configuration file is not
processed. To enable the Windchill Auditing Framework, set the enabled attribute
to true as shown below. Any changes to this configuration file will require a
method server restart in order to take effect.

Customizing Event Audits 29-7


Enabling the Windchill Auditing Framework
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE EventConfiguration SYSTEM "configAudit.dtd">
<EventConfiguration enabled="true">

The <ConfigEntry> element identifies the events to be audited for a specific class.
The class attribute identifies a fully qualified class name to be audited. Within the
<ConfigEntry> element there are additional elements defining the specific events
being monitored for the class and which audit recorder persists the event
information. Originally, these sub-elements were specific to an event type;
PersistenceManagerEventEntry for PersistenceManagerEvent,
AccessControlEventEntry for AccessControlEvent, etc. New in X-05, the
KeyedEventEntry element allows the event class to be explicitly defined and
should be used exclusively going forward.
ConfigEntry dtd (part 2)
<!ELEMENT ConfigEntry (KeyedEventEntry | WIPEventEntry |
WfEngineEventEntry |
PersistenceManagerEventEntry | ActionItemEventEntry |
ProjectServiceEventEntry | AccessControlEventEntry |
ProjectManagementEventEntry | RenameEventEntry |
CustomEventEntry | GroupEventEntry | ForumEventEntry |
VCEventEntry)*>
<!ATTLIST ConfigEntry
class CDATA #REQUIRED
enabled (true | false) #REQUIRED
>
<!ELEMENT KeyedEventEntry EMPTY>
<!ATTLIST KeyedEventEntry
eventKey CDATA #REQUIRED
enabled (true | false) #REQUIRED
handler CDATA "wt.audit.configaudit.DefaultAuditEventRecorder">

The enabled attribute for each <ConfigEntry> element determines whether a


specific Windchill class, as defined by the class attribute, is to be audited. To
enable auditing for a specific class, set the enabled attribute to true as shown in the
example below. It is important to note that auditing is only enabled for this class if
auditing is also enabled at all parent levels. Also, any changes to this
configuration file will require a method server restart in order to take effect.
Enabling class-level auditing
<ConfigEntry class="wt.org.WTGroup" enabled="true">
<KeyedEventEntry
eventKey="*/wt.org.OrganizationServicesEvent/MEMBERSHIP_CHAN
GE"
enabled="true"
handler="wt.audit.configaudit.ModifyGroupEventRecorder"/>
</ConfigEntry>

As described above, each <KeyedEventEntry> element maps an event to an audit


recorder. The eventKey identifies the fully-qualified classname for the event

29-8 Windchill Customizer’s Guide


being audited. The handler attribute identifies the fully-qualified classname for
the audit recorder. If omitted, the default audit recorder is used.
The enabled attribute for each <KeyedEventEntry> element determines whether a
specific event (defined by the eventKey attribute) for a specific class (defined in
the <ConfigEntry> parent element) is to be audited. To enable auditing for a
specific event, set the enabled attribute to true as shown in the example below.
Once again, auditing is only enabled for this event if auditing is also enabled at all
parent levels and any changes to this configuration file will require a method
server restart in order to take effect.
Enabling event-level auditing
<KeyedEventEntry
eventKey="*/wt.org.OrganizationServicesEvent/MEMBERSHIP_CHANGE"
enabled="false"
handler="wt.audit.configaudit.ModifyGroupEventRecorder"/>

Customizing Event Audits 29-9


Capturing New Events
In many situations, the event auditing defined out-of-the-box meets the customer's
need and the only customization required is enabling or disabling auditing, as
appropriate. However, out-of-the-box auditing requirements continue to expand
and certain customers require auditing customizations. Auditing may be extended
in two ways to meet the additional requirements:
• Auditing additional events and capturing default information about the event.
• Auditing additional events and capturing event-specific information.

Capturing default information about a new event.


When additional events to be audited are identified, often capturing default
information is sufficient to meet the auditing requirements. In this case, the
DefaultAuditEventRecorder can be used and the additional auditing can be
implemented without any coding changes. This type of customization will only
require changes to the auditing configuration file.

Extending Auditing For Class


If the class to be audited is already being audited for other events, the
configuration file can have an additional <KeyedEventEntry> element added
defining the new event.
Extending the auditing for a class
<ConfigEntry class="wt.org.WTGroup" enabled="true">
<KeyedEventEntry
eventKey="*/wt.org.OrganizationServicesEvent/MEMBERSHIP_CHANGE"
enabled="true"
handler="wt.audit.configaudit.ModifyGroupEventRecorder"/>
<KeyedEventEntry
eventKey="*/<event_class>/<event_type>"
enabled="true"
handler="wt.audit.configaudit.DefaultAuditEventRecorder"/>
</ConfigEntry>

Adding New Auditing For Class


If the class to be audited is not currently being audited, the configuration file can
have a new <ConfigEntry> element for the new class and event.
Adding new auditing for a class
<ConfigEntry class="<audit_class>" enabled="true">
<KeyedEventEntry
eventKey="*/<event_class>/<event_type>"
enabled="true"
handler="wt.audit.configaudit.DefaultAuditEventRecorder"/>
</ConfigEntry>

29-10 Windchill Customizer’s Guide


Capturing new event-specific auditing information.
Auditing for certain events requires event-specific information to be captured in
addition to the default information identified above, which requires coding
changes. There are three changes which need to occur:
• Create a new event info class
• Create a new event recorder
• Modify configuration file

Create New Event Info Class


To store the event-specific information, a new "event info" class is created. This is
basically a modeling exercise, creating a new class which implements the
Externalizable interface and extends the wt.audit.eventinfo.AbstractEventInfo
abstract class. The Windchill attribute for tablespace must be overridden and set
to WCAUDIT, the Oracle tablespace in which all auditing tables are created. The
figure below shows the model for wt.audit.eventinfo.ModifyGroupEventInfo,
which is currently implemented.

Modeling a new event info class

Create New Event Recorder


The new recorder extends the wt.audit.configaudit.DefaultAuditEventRecorder
class. The recorder needs to override one or both of the persistMultiObjectEvent()
or persistEvent() methods, depending on whether the event is handling one or
multiple objects with a single event. The steps are similar for both:
• Start a new transaction
• Call the parent's method to capture the default event information
• Store the event-specific information for each target object

Customizing Event Audits 29-11


The following examples show an implementation of persistMultiObjectEvent()
and an implementation of persistEvent(). For multiple objects, notice the
optimization to create a collection of event-specific event info classes and to pass
the collection to the persistence layer.
Example: persistMultiObjectEvent method
protected WTCollection persistMultiObjectEvent( KeyedEvent anEvent
)
throws WTException {

Transaction trx = new Transaction();

try {
trx.start();

WTCollection auditRecordCol =
super.persistMultiObjectEvent(anEvent);
int numObjs = auditRecordCol.size();

WTCollection eventInfoCol = new WTArrayList(numObjs);

for (Iterator i = auditRecordCol.persistableIterator();


i.hasNext(); ) {
AuditRecord record = (AuditRecord)i.next();
Persistable target =
record.getTargetReference().getObject();

<event_info_class> eventInfo =
<event_info_class>.new<event_info_class>();

// Set event and target specific attributes here


eventInfo.setAttribute1(target.getAttribute1());
eventInfo.setAttribute2(target.getAttribute2());

// These two attributes are always required


eventInfo.setDomainRef(record.getDomainRef());
eventInfo.setRecord(record);

eventInfoCol.add(eventInfo);
}

PersistentObjectManager.getPom().insert(eventInfoCol, null,
null);

trx.commit();
trx = null;

return recordCol;
}
catch (WTPropertyVetoException pve) {
throw new WTException (pve);
}
finally {
if(trx != null) {
trx.rollback();
}

29-12 Windchill Customizer’s Guide


}
}

Example: persistEvent method


protected AuditRecord persistEvent( KeyedEvent anEvent )
throws WTException {

Transaction trx = new Transaction();

try {
trx.start();

//Store the base data.


AuditRecord record = super.persistEvent(anEvent);
Persistable target = (Persistable)anEvent.getEventTarget();

if (anEvent instanceof <event_class>) {


<event_class> newEvent = (<event_class>)anEvent;

<event_info_class> eventInfo =
<event_info_class>.new<event_info_class>();

// Set event and target specific attributes here


eventInfo.setAttribute1(newEvent.getAttribute1());
eventInfo.setAttribute2(target.getAttribute2());

// These two attributes are always required


eventInfo.setDomainRef(record.getDomainRef());
eventInfo.setRecord(record);

PersistentObjectManager.getPom().insert(eventInfo, null,
null);
}

trx.commit();
trx = null;

return record;
}
catch (WTPropertyVetoException pve) {
throw new WTException(pve);
}
finally {
if (trx != null) {
trx.rollback();
}
}
}

Customizing Event Audits 29-13


29-14 Windchill Customizer’s Guide
30
Customizing Communication
Tools

Windchill provides tools that enable your team to communicate and collaborate
effectively, such as support for meetings, subscriptions, and discussion forums.
This chapter describes how to customize communication tools, where such
customization is supported in Windchill.

Topic Page
Customizing Meetings.......................................................................................30-2
Customizing Action Items (Windchill ProjectLink Only) ................................30-3

30-1
Customizing Meetings
Windchill PDMLink, and Windchill ProjectLink provide the ability to customize
the authentication scheme used for Webex meetings. A delegate object,
implementing the WebexUserInfoDelegate interface, is used to create the account
name and password. To perform this type of customization, you need to write a
class that implements the interface WebexUserInfoDelegate and substitute that for
the default delegate provided out of the box with Windchill.
1. Write your customized WebexUserInfoDelegate.
Write a class that implements the wt.meeting.WebexUserInfoDelegate
interface. See your installed Javadoc for details on the
WebexUserInfoDelegate API. Any class that implements this interface must
conform with all Webex requirements. For example, names, email addresses,
and passwords must conform to the Webex requirements listed in the Webex
API documentation. If storing any information is required to make this work,
that is also the responsibility of the implementor.
2. Include the compiled class in the Windchill codebase in the same way that
you include other customizations.
3. To make Windchill actually use the new delegate, modify the service delegate
mapping according to the procedure described in the Customizing
service.properties topic in the Developing Server Logic chapter on page
36-24. In service.properties, the out of the box entry for
WebexUserInfoDelegate is as follows:
wt.services/svc/default/wt.meeting.WebexUserInfoDelegate/default/java.lang.Object/0
=wt.meeting.DefaultWebexUserInfoDelegate/singleton

In your new mapping, replace


wt.meeting.DefaultWebexUserInfoDelegate with your customized
delegate.

Sample code for WebexUserInfoDelegate


A code sample is provided with Windchill to assist you in creating your own class
that implements the WebexUserInfoDelegate interface. The code can be found in
<Windchill>/src/wt/meeting/DefaultWebexUserInfoDelegate.java.

Caution: While the sample code includes an implementation of the


DefaultWebexUserInfoDelegate class used by Windchill, this is provided for
example purposes and as a possible template on which to base your
implementation. When using it as such, be aware that this sample code is not
necessarily up-to-date.

30-2 Windchill Customizer’s Guide


Customizing Action Items (Windchill ProjectLink Only)
In Windchill ProjectLink, action items have, in addition to standard attributes,
several customizable attributes. These attributes cover a variety of formats such as
date, percentage, number with decimals, and string. Some customizable attributes
are exposed in the user interface out-of-the-box. You can expose or hide any of
these attributes, reorder them, or designate whether they are required by
modifying attributeConfig.xml in the code base. You can also create or modify the
attribute display names through the associated resource bundle. These attributes
are all modeled attributes to ensure the best performance and scalability.

Note: When searching for action items on the Advanced Search page, all
attributes are available, including those not currently exposed in the user interface.

The following table describes the customizable action item attributes:

Name Exposed in UI by Default Description

Action Plan No String – 4000 characters

Actual Effort Yes Integer number of hours

Comments Yes String – 4000 characters

Contacts No String – 4000 characters

Contingency No String – 4000 characters

Cost No Monetary real number

Cost Impact Yes Monetary real number

Customers No String – 4000 characters

Date No Date

Design Cost No Monetary real number

Estimated Effort Yes Integer number of hours

Impact Yes String – 4000 characters

Location No String – 4000 characters

Percent No %

Phase No String – 200 characters

Prevention No String – 4000 characters

Customizing Communication Tools 30-3


Name Exposed in UI by Default Description

Probability Yes String – 200 characters

Production Cost No Monetary real number

Quantity No Integer

Rank Yes Integer

Resources Yes String – 4000 characters

Risk Yes Enumerated value (same as


for activities)
Unavailable
Very High
High
Medium
Low
Very Low

Risk Description Yes String – 4000 characters

Risk Type Yes String – 200 characters

Schedule Impact No + or – days

Size No Real number

Suppliers No String – 4000 characters

Supporting No String – 4000 characters


Information

Time No hh:mm

Tooling Cost No Monetary real number

Exposing or Hiding Customizable Attributes


To expose or hide a customizable attribute in the user interface:
1. Open the attributeConfig.xml file located at
<Windchill>/codebase/wt/meeting/actionitem, where <Windchill> is the
location where Windchill Services is installed.
2. Modify the appropriate <attribute> element. Use the resourceKey to locate
the attribute you want to expose or hide, and set the enabled= value to “true”
(to expose) or “false” (to hide).

30-4 Windchill Customizer’s Guide


The following example from the attributeConfig.xml file shows that the
Comments field is configured to be exposed in the user interface.
<attribute resourceKey="comments"

enabled="true"
order="40"
required="false"
resourceBundle="wt.meeting.actionitem.actionitemModelRB"
displayType="textBox"
internalName="Comments"
type="java.lang.String"/>

Reordering Customizable Attributes


To reorder customizable attributes in the user interface:
1. Open the attributeConfig.xml file located at
<Windchill>/codebase/wt/meeting/actionitem, where <Windchill> is the
location where Windchill Services is installed.
2. Modify the appropriate <attribute> elements. Use the resourceKey to locate
the attributes you want to reorder, and assign values to the order attribute of
each in the numeric order in which you want the attributes to display.

Designating Customizable Attributes as Required


To designate a customizable attribute as required:
1. Open the attributeConfig.xml file located at
<Windchill>/codebase/wt/meeting/actionitem, where <Windchill> is the
location where Windchill Services is installed.
2. Modify the appropriate <attribute> elements. Use the resourceKey to locate
the attribute you want to designate as required, and set the required= value to
“true”.

Changing the Display Names of Customizable Attributes


To change the display name of a customizable attribute, please refer to the
Changing Displayed Text Found in RBINFO Files section in the Managing
Customizations chapter on page 5-9.

Customizing Communication Tools 30-5


30-6 Windchill Customizer’s Guide
IV
Services and Infrastructure
Section

Chapter Page
Windchill Services ............................................................................... 31-1
System Generation ............................................................................... 32-1
Customizing Modeled Elements .......................................................... 33-1
Enumerated Types................................................................................ 34-1
Windchill Design Patterns ................................................................... 35-1
Developing Server Logic ..................................................................... 36-1
The Enterprise Layer............................................................................ 37-1
Persistence Management...................................................................... 38-1
Advanced Query Capabilities .............................................................. 39-1
Internationalization and Localization................................................... 40-1
Customizing Archive, Purge, and Restore ........................................... 41-1
Import Export Framework ................................................................... 42-1
Evolvable Classes ................................................................................ 43-1
Creating Large Objects (LOBs) ........................................................... 44-1
Customizing Data Formats................................................................... 45-1
31
Windchill Services

This chapter describes the various Windchill services.

Topic Page
Windchill Packages ...........................................................................................31-2
Engineering Factor Services..............................................................................31-2

31-1
Windchill Packages
Windchill’s functionality — that is, its services and utilities — is generally
separated into Java packages. These packages are available in the wt and com.ptc
directories within the Windchill codebase directory. You can use these packages
as you build new applications and customize existing applications. Model files are
provided so you can extend some of the classes in the models and then generate
code for them. This section lists a subset of the packages available for use in
customizations and gives an overview of their functionality. Some of the packages
are described in further detail in other chapters of this guide, or in the
accompanying Javadoc for the package.
access
Functionality for access control; used to define access policies (that is, define
rules for what principals have access to what information). See the wt.access
class entry in your installed Windchill Javadoc for more information.
admin
Functionality to create administrative domains and policies. See the wt.admin
class entry in your installed Windchill Javadoc for more information.
content
Functionality for handling content data (attaching files and URLs to content
holders, such as documents and change objects) and associating business
information metadata (such as the author) with content. See the wt.content
class entry in your installed Windchill Javadoc for more information.
content replication
Functionality for increasing the speed at which users can access data. Data is
stored on more rapidly accessible external vaults known as replica vaults.
Base packages cannot be extended or modified in any way. Additional
information about content replication is discussed in the Windchill System
Administrator’s Guide.
effectivity
Functionality to assert that a PDM object is effective under certain conditions.
See the wt.eff and wt.effectivy class entry in your installed Windchill Javadoc
for more information.
epm
The engineering service (wt.epm package) provides functionality to create
and manage CAD model related objects. See the wt.epm and subpackages
entry in your installed Windchill Javadoc for more information.
federation
The federation service (wt.federation package) provides functionality to
create and manage proxy objects of remote systems and perform utility
functions supporting the federation system. See the wt.federation class entry
in your installed Windchill Javadoc for more information.

31-2 Windchill Customizer’s Guide


folder
Functionality to put information into folders and cabinets for navigational
purposes. See the wt.folder class entry in your installed Windchill Javadoc for
more information.
fv
Functionality to define and execute the vaulting algorithm for content items.
See the wt.fv class entry in your installed Windchill Javadoc for more
information.
identity
Functionality to display the identity of business objects; that is, their type and
identifier (for example, a type of part and an identifier of part number). See
the wt.identity class entry in your installed Windchill Javadoc for more
information.
Import and Export
Windchill Import and Export can assist you in moving complete Windchill
content and metadata to and from Windchill sites and Windchill ProjectLink
portals by placing the data in Jar files. See the wt.ixb subpackages entry in
your installed Windchill Javadoc for more information.
index
Functionality to index metadata and content data, controlling how information
is put into search indexes. See the wt.index class entry in your installed
Windchill Javadoc for more information.
lifecycle
Functionality to define and use life cycles. See the wt.lifecycle class entry in
your installed Windchill Javadoc for more information.
locks
Functionality to lock and unlock objects. See the wt.locks class entry in your
installed Windchill Javadoc for more information.
notify
Functionality to define rules and create subscriptions such that when certain
events occur to certain objects, E-mail notification is sent. See the wt.notify
class entry in your installed Windchill Javadoc for more information.
org
Organization services; functionality to create users and groups (generically
called principals). See the wt.org class entry in your installed Windchill
Javadoc for more information.
ownership
Functionality to define ownership of an object. See the wt.ownership class
entry in your installed Windchill Javadoc for more information.
project
Functionality to create projects, associate projects to business objects, and
resolve roles to principals.

Windchill Services 31-3


queue
Functionality to define and manage queues. Queues are used to persistently
record deferred processes. Because queued processes are persistently stored,
they are guaranteed to execute at a later time. See the wt.queue class entry in
your installed Windchill Javadoc for more information.
session
Functionality to define and manage user sessions. See the wt.session class
entry in your installed Windchill Javadoc for more information.
vc
Version control; functionality to handle versions of objects. Version control
services described in this chapter include baselines, configuration
specifications, version structuring, version viewing, and work in progress.
See the wt.vc subpackages entry in your installed Windchill Javadoc for more
information.
workflow
Functionality to create and manage workflow definitions, initiate and manage
process instances, and distribute work items to users and groups. See the
wt.workflow and subpackages entry in your installed Windchill Javadoc for
more information.

31-4 Windchill Customizer’s Guide


Engineering Factor Services
The EPM classes implement a programming model designed to perform the
following activities:
• Allow the loading of CAD models (including information about family
tables) into a Windchill database
• Relate the CAD models to parts in the enterprise
• Support the propagation of changes made to the models into the enterprise
parts
EPM provides Windchill knower and doer classes that allow the engineer to
express the structure of a CAD model and to load the CAD files into the Windchill
database. EPM also provides background services that ensure data consistency in
the database.
Windchill supports the concept of a build operation, which allows a graph of
dependencies in one set of objects (called target objects) to be maintained
automatically as a by-product of changes to another set of objects (called source
objects). EPM implements a build operation specific to creating part objects from
describing CAD documents.
For more information, see the appropriate Javadoc.

Handling CAD Models


CAD models are represented in EPM by EPMDocument objects. If the CAD
model has an associated family table, each line in the family table is represented
by EPMDocument. This section describes EPMDocuments and its associated
links in more detail.EPMDocument

EPMDocument Model
An EPMDocument can represent a component or an assembly, using other
EPMDocuments as components. (This concept is described further in the section
on Handling Model Structure later in this section.)
As shown in the following model, EPMDocument implements a number of
Windchill interfaces that allow it to be used in various Windchill services:
RevisionControlled
Allows the EPMDocument to be checked in and out
Baselineable
Allows the EPMDocument to be stored in a baseline
FormatContentHolder
Allows the EPMDocument to have content
DocumentVersion
Allows the EPMDocument to be treated as a document by the Windchill
Explorer

Windchill Services 31-5


BuildSource
Allows the EPMDocument to be used by the Windchill build mechanism to
maintain a part structure
SupportingDataHolder
Allows the EPMDocument to have EPMSupportingData. An
EPMSupportingDataHolder can hold arbitrary Java objects, each tagged with
a name and an owner application name. This allows an application to store
application-specific data with the EPMDocument without having to extend
the Windchill schema.
EffectivityManageable
Allows the EPMDocument to be assigned an effectivity.
GraphicallyRepresentable
Allows the EPMDocument to have generated graphic representations that can
be viewed and marked up in a view tool.

EPMDocument Model

31-6 Windchill Customizer’s Guide


Because the EPMDocument is RevisionControlled, a corresponding
EPMDocumentMaster exists, which also implements Windchill interfaces:
UniquelyIdentified
Allows the EPMDocument name to serve as a unique identifier
DocumentMaster
Provides a version independent reference to an EPMDocument.

Storing content on EPMDocument


EPMDocument is a Windchill ContentHolder (as shown in the figure above) and,
thus can contain data files, URLs, or both. This allows the engineer to upload the
actual Pro/ENGINEER model file (for example, the .ASM file) and maintain it in
the Windchill database.
An EPMDocument can contain a number of ContentItems. This allows EPM to
store alternate representations of the CAD model (produced by the topology bus,
for example) in the same document. Content is maintained using the normal
Windchill ContentService.

Creating an EPMDocument
An EPMDocument must be created via the factory method newEPMDocument:
EPMDocument doc = EPMDocument.newEPMDocument (
<number >, <name >, <EPMAuthoringAppType authoring App >,
<EPMDocumentType docType>, <CADName>);
The number of the document must be unique within the Windchill database. The
ownerApplication is an EnumeratedType indicating the application that intends to
manage changes to the document. The concept of owner application is no 2 set via
a call to EPMContextHelper.setApplication (EPMApplicationType appType),
where EPMApplicationType is an EnumeratedType. Set the "current application"
for use by checking code. This value is cached on the client-side, but is also sent
(via the EPMContextManager) to the server-side SessionContext.
Once setApplication () has been called, all objects created will be tagged with the
specified application. For Pro/ENGINEER authored CADDocuments, CADName
needs to be specified. EPM Services ensure that CADName is unique in a
Windchill database.

Handling Family Instances


If the CAD model has an associated family table, each line in the family table is
represented by a separate EPMDocument. As shown below, relations between
these EPMDocuments are handled by two types of links viz. EPMContainedIn
and EPMVariantLink.
The EPM ContainedIn relation is an Object to Object link that associates two
EPM Documents where one holds an object that is physically contained in the
other, such as a family instance and the Pro/ENGINEER model that holds the
family table.

Windchill Services 31-7


EPM Variant Link is an Iteration to Master link that denotes that an EPM
Document is a variant of another EPM Document.

31-8 Windchill Customizer’s Guide


Handling Model Structure

EPMDependencyLink
When an EPMDocument represents an assembly, it uses other EPMDocuments
via EPMMemberLinks. It can also reference other EPMDocuments via
EPMReferenceLinks; reference links are non-structural, but are used to include
objects that provide scenery, or constraints.
Both EPMMemberLinks and EPMReferenceLinks are types of
EPMDependencyLink (shown in the following figure), which is used to represent
the concept of one EPMDocument depending on another.

Windchill Services 31-9


The EPMDependencyLink represents a relation between two EPMDocuments.
EPMStructureService can be used to read the EPMDependencyLinks between
EPMDocuments. A number of interfaces similar to the following are available:
public QueryResult navigateUses( EPMDocument document,
QuerySpec querySpec )
throws WTException;

EPMMemberLink
The EPMMemberLink represents the use of one model by another. It includes
data such as quantity and positioning, as shown in the following figure.

EPMReferenceLink
The EPMReferenceLink represents reference to an object by a model. While an
EPMMemberLink can use only another EPMDocument, any Iterated object can
be referred to (for example, a specification in Microsoft Word). The relationship
between an EPMDocument containing a drawing and the EPMDocument
containing the model is represented using an EPMReferenceLink. The direction
of this link should be such that the drawing describes the model. The model never
describes the drawing.

31-10 Windchill Customizer’s Guide


The Relationship Between CAD Models and WTParts
Please note that the Build Model will change in future releases. To prepare for this
change, many of the classes and methods from the build package have been
deprecated. These classes and methods will be replaced. Please refer to the
Javadoc to see the deprecated classes and methods. Windchill defines a build
process, which is used to publish usage links and attributes (see the following
figure).

Build Model

You cannot associate an EPMBuildRule to an EPMDocument that has an


effectivity assigned to it. To create an EPMBuildRule, you must first have created
the WTPart and EPMDocument that you intend to relate. In addition, the WTPart,
but not the EPMDocument, must be either checked out or in your personal folder.
Currently, only one subtype of EPMBuildRule is implemented —
EPMBuildLinksRule. This rule allows for the publication of usage links to the
part structure (see the following figure).

Windchill Services 31-11


Build Rule
To create the rule, you must use the factory method defined on the class:
EPMBuildLinksRule rule = EPMBuildLinksRule.newEPMBuildLinksRule (
<document >, <part);
Once this has been done, you can use the Windchill build process to publish the
document structure to the part structure. This can be done in either of two ways:
• By building the EPMDocument:
BuildHelper.service.buildTarget (<document >,<config spec >);
• By building the WTPart:
BuildHelper.service.buildTargetsForSource (<part >,<config spec >);
If you are building a vaulted WTPart, the build process creates a new iteration of
the WTPart. If the WTPart is either checked out or in your personal folder, no new
iteration is created; instead, the usage links on the latest iteration are changed to
reflect the results of the build.

31-12 Windchill Customizer’s Guide


32
System Generation

When you have finished modeling, the next step is system generation. Using
Windchill extensions to Rose’s original functionality, Windchill generation tools
generate Java code, Info files containing class metadata used by the runtime
environment, and database DDL from the models you create. This chapter
describes how to use the system generation tool and how the classes you model in
UML (in Rose) correspond to the code that is generated.

Topic Page
Overview of System Generation .......................................................................32-2
How Rose UML Maps to Java Classes .............................................................32-3
Implicit Persistable Associations Stored with Foreign ID References............32-21
Extending the EnumeratedType class .............................................................32-36
How Rose UML Maps to Info Objects ...........................................................32-39
How Rose UML Maps to Database Schema ...................................................32-41
How Rose UML Maps to Localizable Resource Info Files ............................32-47
Using the Windchill System Generation Tool ................................................32-50
Using Windchill System Generation in a Build Environment ........................32-54
Deploying Modeled Customizations ...............................................................32-60

32-1
Overview of System Generation
The figure below shows the system generation process.

System Generation Overview

Using the models in the Rational Rose repository, the Windchill export tool
produces mData files. The system generation tools then use the mData files to
produce Java code, Info files (metadata used by the runtime environment), and
database schema. mData files have a non-proprietary file format so that, in the
future, different modeling tools can be used without rewriting portions of the
system generation tool.
The following sections describe how the Rose UML is mapped to each of the
types of output (Java code, Info files, and database schema). The final section of
this chapter describes how to run the system generation tool.

32-2 Windchill Customizer’s Guide


How Rose UML Maps to Java Classes
You control aspects of system generation by specifying values within Rose for the
following model elements:
• Classes
• Operations
• Attributes
• Associations and their roles
• Generalize relationships
• Dependency relationships
The following sections, which describe how each of these elements are mapped to
Java, also include the specifications you must set for each kind of element to
ensure the correct code is generated. Within the Rose dialogs where you set these
values, there are other tabs and fields. Any tabs or fields not described in this
manual are either ignored by the system generation tools or have preferred default
values.
The figure below shows a sample specification dialog in Rose. To access this
dialog, double click on an item in a diagram; or select a diagram item, then select
Open Specification from the right click pop-up menu. Rose displays a
specification that corresponds to the item you selected. The documentation for

System Generation 32-3


code generated items is placed in the generated source code in the format of
Javadoc style comments.

Rose Specification Dialog

Mapping Modeled Classes to Java


Classes modeled in Rose will be generated as Java classes or interfaces. An
interface will be generated when the class is modeled with the Interface
stereotype.
The figure below shows a class modeled in Rose that is mapped to Java.

Model of a Class

32-4 Windchill Customizer’s Guide


Copyright Statement
Rose provides for a default copyright, and also for a copyright to be specified for a
particular package. This copyright statement is generated into the Java source
code for each class.

Package Statement
The package statement corresponds to the Rose UML package that owns the class.
For example,
// Example of a generated package statement
package example;

Import Statements
Java import statements are generated based on references made to other classes
through the following model elements:
• Class and Interfaces inherited by the class.
• Dependencies modeled for the class.
• Non-Persistable Association types.
• Attribute types declared by the class.
• Argument type s specified by the methods of the class.
• Return value types specified by the methods of the class.
• Exceptions thrown by the methods of the class.
For example,
// Examples of a generated import statements
import example.MyAddress;
import example.MySize;
import java.lang.String;
import java.sql.Date;
import java.util.Vector;
import wt.fc.Item;
import wt.pds.PersistentRetrieveIfc;
import wt.pds.PersistentStoreIfc;
import wt.pom.DatastoreException;
import wt.util.WTException;
import wt.util.WTPropertyVetoException;

//##begin user.imports preserve=yes


//##end user.imports

The generated import statements depend on input from the


classRegistry.properties file (discussed later in this chapter) that contains a list of
classes and their associated packages.

System Generation 32-5


The user.imports section is provided as a safe place for the developer to enter
additional imports to support the implementation of the class. This section is
preserved during subsequent generations of the class.
To better support use of Integrated Development Environments (IDEs), the
generator also preserves imports found outside of the user.imports block. If the
(trimmed) text of the import line doesn't begin with the word "import", it won't be
preserved. Anything within a preserve=yes block is ignored. When it finds
unmanaged import statements, it moves them into the user.imports preserve block
and adds a comment to indicate how it got there.
//##begin user.imports preserve=yes
import unmodeled.UnmodeledOne; // Preserved unmodeled dependency
//##end user.imports

The negative side-effect to this change is that imports previously generated from
model dependencies will not be automatically removed when the dependency is
removed from the model. For instance, if a class changed from using Vector to
using List, both classes would continue to be imported. Developers need to purge
unused import statements as they notice them.

Class Documentation
Any documentation that is entered in Rose will be generated into the class in the
form of Javadoc style comments. For example,
//##begin MyItem% [ ]34F19D1A00B3.doc preserve=no
/**
* An example class to demonstrate system generation
*
* @version 1.0
**/
//##end MyItem% [ ]34F19D1A00B3.doc

Class Declaration
A class is declared as modeled and will extend and implement all of the classes
that were modeled as having a generalization relationship. If a class is modeled to
extend a class that was not modeled as Extendable, via the Windchill
SupportedAPI property, the generator will not allow it to be generated until that
modeled generalization is removed.The class can be modeled as concrete,
abstract, or as an interface. For example,
// Example of a class declaration
public class MyItem extends Item implements Externalizable{

// Example of an abstract class declaration


public abstract class Item extends WTObject {

// Example of an interface declaration


public interface Persistable extends ObjectMappable {

32-6 Windchill Customizer’s Guide


Class Body
Some constants are generated into the body of each class. The following are
examples of generated class constants:
// Constants used by the class
private static final String RESOURCE =
"example.exampleResource";
private static final String CLASSNAME =
MyItem.class.getName();

The RESOURCE constant identifies the resource bundle the class is to use for
localizable messages.
The CLASSNAME constant provides an easily accessible, programmatic
reference to the name of the class.
The rest of the class body contains the generated results of elements modeled as
features of the class and as relationships between classes. These include
operations, attributes, associations, and generalizations. The details of these will
be covered in subsequent sections.

Rose Class Specification


On the General tab, set the following values:
• Name specifies the name of the corresponding Java class.
• Stereotype:
– For a class, leave blank.
– For a final class, select Final.
– For an abstract class, select Abstract.
– For an interface, select Interface.
– For a remote interface, select RemoteInterface (see explanation which
follows).
• Export Control should be set to Public or Implementation. Implementation
classes are visible only to other classes within the same package.
• Documentation specifies a description for the element. The documentation
will be generated into the Java code, as Javadoc style comments.
• Type is ignored by the code generator.
On the Windchill tab, set the following values:

Note: Some specification dialogs provide multiple property sets. Every


specification provides a "default" set. The class specification also provides
"EnumeratedType" and "System" sets, The EnumeratedType set contains the
properties that apply to an EnumeratedType class. The System set contains the

System Generation 32-7


properties that apply to non business domain class. Property sets may provide
different default values for the same property.

• SupportedAPI should be set to communicate to users the degree to which the


class will be supported.
– <Default> to ignore the Supported API concept.
– Private if the class will not be supported at all.
– Public if use of the class is supported.
– Extendable if extension of the class is supported.
– Deprecated if the class is obsolete and support is being phased out. (This
setting is superseded by the Deprecated property.)
• Deprecated should be set when the element is obsolete.
– <Default> indicates the class is not deprecated, unless, for backward
compatibility, SupportedAPI is set to Deprecated.
– deprecated if the class is obsolete and support is being phased out.

• Java Properties
– Generate should be set to False if the system generation tools should
ignore this modeled class.
– CodeGenerationName specifies the name of the class that will be
generated. Leave it blank to have the generated name be the same as the
name of the modeled class.
– Serializable indicates if the generated class will implement the
Serializable or Externalizable interface. Default evaluates to
Externalizable, if possible; otherwise, Serializable. Externalizable
(basic), can be used to generate simple Externalization support that does
not include support for reading old versions.For a class that will have
instances serialized into BLOB columns in the database, set the property
to Evolvable. (For further information, see appendix D, Evolvable
Classes.) To have the class implement neither interface, set the property
to None.
– PrimitiveType indicates which primitive value-type a class can be
decomposed into.
– StaticInitBeforeFields indicates whether the static initializer will be
placed before the field declarations.
– GenAttributeLabels indicates whether label constants will be generated
for the modeled attributes and roles of the class. If True, they will be

32-8 Windchill Customizer’s Guide


generated. If Default, they will be generated for classes that implement
ObjectMappable and for interfaces.
– ExplicitOrder (EnumeratedType set only) indicates whether the modeled
EnumeratedType options will be explicitly order in the resource info
(rbInfo) file. By default, a locale specific, alphabetical order will be
determined at run-time.
• Datastore Properties
– PackageName is the package name to use for the class.
– TableName is the database table name to use for the class.
– RemoveEventParticipant specifies if the persistence layer is required to
dispatch Remove events for this class. Remove events include
"REMOVE" and "CLEANUP_LINK". Default will be determined to be
True for any Persistable class.
– CompositeIndexN indicates the columns for composite index on the
table.
– CompositeUniqueN indicates the columns for composite unique index
on the table.
– ColumnType indicates the relational storage type for the value-type. By
default a mapping, based on the primitive type, is used. Specify a
ColumnType of Sequence if the value of the attribute is to be set using a
generated sequence number.
• Oracle Properties
– TableSpaceName is the tablespace to use for storage option of the table.
– TableSize indicates if the relative size required for the objects that will be
stored (the actual storage values are mapped from the size via property
file settings).
– IndexTableSpaceName is the tablespace to use for the storage option of
the indices of the table.
• UI Properties
– StandardIcon is the file name of the standard icon for the class.
– OpenIcon is the file name of the open icon for the class.
– Localizable indicates if the class will have a localizable display name
stored in the resource bundle for the package.
• The rest of the dialog is ignored by the code generator.

System Generation 32-9


Mapping Operations to Java
The figure below shows an operation modeled in Rose that is mapped to a method
in Java.

Model of Operations

The following code is generated for this example.


public class MyItem extends Item implements Serializable {
//##begin operation1% [ ]34F19DCB01D0.doc preserve=no
/**
* The example operation.
*
* @param arg1 The Date argument
* @return StringThe String return value
**/
//##end operation1% [ ]34F19DCB01D0.doc

public String operation1( Date arg1 ) {


//##begin operation1% [ ]34F19DCB01D0.body preserve=yes

return null;
//##end operation1% [ ]34F19DCB01D0.body
}
}

Operations modeled in Rose are mapped as Java methods of the generated class.
For operations that are not modeled as abstract, stubs are created in the generated
class where you add your own code. All documentation, keywords, parameters,
and return types that are modeled in Rose are generated into Java classes.
Information about operations that you can specify in Rose is detailed below.
The begin and end markers that are generated into editable files denote the
sections that you can edit. These sections are preserved as is during subsequent
generations of the files.
Some sections are marked with preserve=no. This is true for all Javadoc comment
sections and some code sections, where some implementation is generated into an
editable file. The "no" value for preserve indicates that the section is a generated
default, which you may choose to edit. If you do edit any of these sections, you
must change the preserve value from "no" to "yes"; otherwise, it will not be
preserved.
If MyItem were an interface, only the operation declaration would be generated
into MyItem, because a Java interface can contain no implementation. To the
degree possible, the implementation aspects of interface operations will be

32-10 Windchill Customizer’s Guide


generated into concrete subclasses. See the Implementing Interfaces section for
details.

Rose Operation Specification


On the General tab, set the following values:
• Name specifies the name of the resulting Java method.
• Return class specifies the type of the method’s return value.
• Export control should be set to Public, Protected, or Implementation. Public
methods are external API to the class. Protected methods are customization
points that extending classes can choose to override. Private methods need not
be part of the business model. Developers can implement them in their classes
as needed.
• Documentation specifies a description for the element. The documentation
will be generated into the Java code, as Javadoc style comments.
On the Detail tab, set the following values:
• Argument Name specifies the name of an argument in the method.
• Argument Type specifies the argument type.
• Exceptions specifies the exceptions thrown by the method.
• The rest of the dialog is ignored by the code generator.
On the Windchill tab, set the following values:
• SupportedAPI should be set to communicate to users the degree to which the
operation will be supported.
– Private if the operation will not be supported at all.
– Public if use of the operation is supported.
– Deprecated if the operation is obsolete and support is being phased out.
(This setting is superseded by the Deprecated property.)
• Deprecated should be set when the element is obsolete.
– <Default> indicates the operation is not deprecated, unless, for backward
compatibility, SupportedAPI is set to Deprecated.
– deprecated if the operation is obsolete and support is being phased out.
• Java Properties
– Abstract should be set to True to make the resulting method abstract.
– Static should be set to True to make the resulting method static.
– Final should be set to True to make the resulting method final.

System Generation 32-11


– Native should be set to True to make the resulting method a native
method.
– Synchronized should be set to True to make the resulting method a
synchronized method.
– RemoteInvocation should be set to True to make the resulting method
executable only at the server. This setting is not needed for classes that
implement a RemoteInterface.

Mapping Attributes to Java

Attribute Implementation
The external Java representation of a class attribute modeled in Rose consists of a
getter operation, a setter operation, and an identifying label. The export visibility
of the getter and setter operations is based on the export visibility of the modeled
attribute in Rose.
The internal Java implementation of the class attribute is always a private field.
This field is accessed strictly through getter and setter operations. Encapsulating
the attribute as a private field provides several benefits:
• The class controls the integrity of the attribute by monitoring changes to the
attribute.
• The class can support subscribe/notify functionality that allows listeners to
monitor the state of the attribute.
• Access through getter and setter operations provides the opportunity to
synchronize access to the attribute.
The following model shows the class MyItem, with attributes a1, a2, and a3,
which extends the class Item.

Model of Attributes

32-12 Windchill Customizer’s Guide


Attribute Label Constants
String field constants are generated as attribute labels so you can use them in APIs
that require an attribute name, such as queries. Thus, the Java compiler can detect
typographical errors.
// Examples of attribute name constants
public static final String A1 = "a1";
public static final String A2 = "a2";
public static final String A3 = "a3";

Field Declarations
All attributes modeled in Rose are implemented as private fields of the Java class.
For example,
// Examples of attribute declarations
private String a1;
private Date a2;
private Xyz a3;

The accessor methods to these attributes are public or protected, depending on the
export control as defined in the model. Examples of accessor methods follow.

Accessor Methods
Public and protected accessor methods are generated in the Java class. For
example,
// Example of a "getter" method
public String getA1() {
return a1;
}
// Example of a "setter" method
public void setA1( String theA1 )
throws WTPropertyVetoException {
a1 = theA1;
}

Accessor methods are code-generated from the attributes modeled on the business
class in the Rose model. They need not be modeled on classes in the UML model.
These accessor methods follow the Java beans naming convention. Attributes that
were modeled as public get public accessor methods. Attributes that were
modeled as protected get protected accessor methods.
The system generation tool generates accessors that enforce attribute validation
based on attribute properties specified in the model.
If the constrain property (a Rose specification) is set to true for an attribute
modeled in Rose, the setter method is declared to throw a
wt.util.WTPropertyVetoException, which is derived from
java.beans.PropertyVetoException. This exception is thrown if the setter method
has determined that a value being set in the attribute is invalid. Developers can
change the default accessor methods by writing code in the preserve region.

System Generation 32-13


Validation code will be generated if the attribute is modeled with a lower or upper
bound, as unchangeable, or as a required attribute. Each of these properties
appear, in Rose, on the Windchill tab for the attribute. Validation code will also be
generated if the attribute is modeled with a constrained type. That is, the attribute
is redefining an attribute, in the hierarchy, to be of a sub-type of the original
definition. If a validation method is generated, the setter code will invoke it. If
validation were generated for the "a1" attribute, the method would be
"validateA1".
If MyItem were an interface, only the accessor declarations and the label constant
would be generated into MyItem, because a Java interface can contain no
implementation. To the degree possible, the implementation aspects of interface
attributes will be generated into concrete subclasses. See the Implementing
Interfaces section for details.

Rose Attribute Specification


On the General tab, set the following values:
• Name specifies the names of the generated attribute.
• Type specifies the attribute’s class.
• Initial value specifies the initial value for the attribute.
• Export control should be set to Public, Protected, or Implementation. If
you want private methods, declare them in your source code.
• Documentation specifies a description for the element. The documentation
will be generated into the Java code, as Javadoc style comments.
On the Detail tab, set the following values:
• Static should be selected if the attribute is to be generated as a static field.
• Derived should be selected if the generated private field is not desired. Also
see the DerivedFrom property below.
• The rest of the dialog is ignored by the code generator.
On the Windchill tab, set the following values:
In addition to the default property set, attributes have two predefined sets. First,
named "constant", which can be used for constant attributes. Second, named
"constantEnumeratedType", which can be used for constant attributes on
EnumeratedTypes. While these property sets can be used to quickly set the
Windchill properties for these constant attributes, the Static property still needs to
be selected on the detail tab.
• Abstract should be set to True if the implementation of a field for the
attribute will be deferred to a subclass. Accessor methods generated for this
attribute will be abstract.

32-14 Windchill Customizer’s Guide


• DerivedFrom should be specified if this attribute is derived from another
modeled element. The value will specify a traversal path to the source. For
example, homeAddress.city indicates that this class has a non-first-class
aggregation named homeAddress which contains an attribute named city. To
specify that an attribute’s derivation traversal goes through an
ObjectReference, a different delimiter is used. For example,
homeAddress>city indicates that this class has an opposite-side role on a
first-class association named homeAddress which contains an attribute named
city.
• StringCase should be set to LowerCase to force the value to lowercase. It
should be set to UpperCase to force the value to uppercase. The enforcement
of this constraint will be generated into the setter method for the attribute.
• LowerLimit constrains the valid values for the type. For String types, it
specifies the minimum length of the String. For numeric types, it specifies the
minimum value of the attribute. Date and Time types are not currently
supported by this property. The constraint is enforced in the validation that is
generated for the setter.
• UpperLimit constrains the valid values for the type. For String types, it
specifies the maximum length of the String. For numeric types, it specifies the
maximum value of the attribute. Date and Time types are not currently
supported by this property. The constraint is enforced in the validation that is
generated for the setter.
• Required should be set to True if the database will not allow a null value in
the column that persists the attribute’s value, and the setter validation will not
allow the attribute’s value to be set to null.
• Changeable should be set to Frozen if the value cannot be changed once it
has been persisted. It should be set to ViaOtherMeans if the normal setter
method is not allowed to change the value once it has been persisted. (For
example, ViaOtherMeans is used for those attributes that are part of the
identity of the class which must be changed through the identity service.)
• WriteAccess should be set if the access of the setter should be different than
that of the getter that will be generated.
• SupportedAPI should be set to communicate to users the degree to which the
attribute will be supported.
– <Default> to ignore the Supported API concept.
– Private if the attribute will not be supported at all.
– Public if use of the attribute is supported.
– Deprecated if the attribute is obsolete and support is being phased out.
(This setting is superseded by the Deprecated property.)
– Deprecated should be set when the element is obsolete.

System Generation 32-15


– <Default> indicates the attribute is not deprecated, unless, for backward
compatibility, SupportedAPI is set to Deprecated.
– deprecated if the attribute is obsolete and support is being phased out.

• Java Properties
– Final should be set to True if the resulting field should be final.
– Transient should be set to True if the resulting field should be transient.
– Volatile should be set to True if the resulting field should be volatile.
– Persistent should be set to True if the field that holds the value will be
persisted to the database.
– GenerateAccessors should be set to False if no accessors are to be
generated.
– Constrain should be set to True if the resulting setter method should
declare that it throws a WTPropertyVetoException.
– GetExceptions specifies exceptions that will be declared as thrown by
the generated getter.
– SetExceptions specifies exceptions that will be declared as thrown by the
generated setter.
– BeforeStaticInitializer should be set to True if field declaration should
be placed prior to the static initializer.
• Datastore Properties
– ColumnName is the class attribute to column name mapping. Default is
the attribute name.
– ColumnType is used to indicate the relational storage type for the value-
type. By default a mapping, based on the attribute type, will be used.
– Index specifies whether an index is created for this attribute.
– Unique specifies whether a unique index is created for this attribute.
– Updatable specifies whether the column can be updated using standard
persistence mechanisms.
• Oracle Properties
– TableSpaceName is the tablespace to use for storage option of the table.
– TableSize indicates the relative size required for the objects that will be
stored (the actual storage values are mapped from the size via property
file settings).

32-16 Windchill Customizer’s Guide


• UI Properties
– Localizable indicates if the attribute will have a localizable display name
stored in the resource bundle for the package.
– Display (constantEnumeratedType set only) specifies the localizable
display name for the attribute, if the attribute is a constant for an
EnumeratedType.
– DefaultValue (constantEnumeratedType set only) should be set to True if
the attribute is the default option for the EnumeratedType. Only one
attribute can be set to True.
– The rest of the dialog is ignored by the code generator.
A constant attribute is one that is specified as static and final.

Mapping Associations to Java

Non-Persistable Associations
The following model shows associations with non-persistable objects
(MyAddress and NameValue).

Associations between Non-Persistable Objects

The following code is generated from this example:


public class MyItem extends Item {
private String a1;
private Date a2;
private Xyz a3;
private MyAddress work;
private Vector list; // contains a set of NameValue objects
// This class also contains the constants and the accessor
// methods for a1, a2, a3, work and list.
}

System Generation 32-17


The implementation of a non-persistable association is the same as the
implementation of a modeled attribute. That is, it will be implemented with a
private field, a constant label, and accessor methods.
If classes modeled in Rose extend the class Item, these classes are automatically
both ObjectMappable and Persistable. But in this example, an object called
MyAddress is modeled that is a composite aggregation. This means that the
instance MyAddress never exists on its own. It exists only as a part of another
instance. In this case, the code generator creates a field in MyItem using the name
of the composite aggregation, that is, the name of the navigable role on the
association (in this example, work). Note that although modeling it as a composite
aggregation communicates the ownership, the role must be navigable to
accomplish the generated implementation.
If the association’s cardinality is greater than one, the attribute is represented as a
Java Vector. For example, the class NameValue is also a composite aggregation
and it contains multiple name and value strings. Because the total number that
could occur is not known during system generation, the code generator creates a
Vector field with the name of the composite aggregation (in this example, list). In
this example, the field is a list of names and values.
The generated class also contains public accessor methods for all the attributes.
Note also that if the role’s cardinality is optional, but the class being aggregated
contains required elements, the aggregated class will be treated as required. The
system generator must enforce this coordination of required attributes because of
the way the PDS (Persistent Data Service) enforces required attributes. The PDS
accomplishes the enforcement through the NOT NULL column feature of SQL
databases. Because a column within the structure will be generated as NOT
NULL, the structure as a whole cannot be nullable.
If MyItem were an interface, only the accessor declarations, and the label constant
would be generated into MyItem, because a Java interface can contain no
implementation. To the degree possible, the implementation aspects of interface
associations will be generated into concrete subclasses. See the Implementing
Interfaces section for details.

32-18 Windchill Customizer’s Guide


Implicit Persistable Associations
The following model shows an association between persistable objects where the
association has no attributes.

An Association with No Attributes between Persistable Objects


The following code is generated from this example:
public final class LinkA extends ObjectToObjectLink
implements Externalizable {

// role name constants


public static final String MY_ITEM_ROLE = "theMyItem";
public static final String YOURS_ROLE = "theYours";
public MyItem getMyItem() { // getter

return (MyItem)getRoleAObject();
}

public void setMyItem( MyItem theMyItem ) // setter


throws WTPropertyVetoException {

setRoleAObject( theMyItem );
}
// two-arg factory for link classes
public static LinkA newLinkA( MyItem theMyItem,
Yours theYours )
throws WTException {

LinkA instance = new LinkA();


instance.initialize( theMyItem, theYours );
return instance;
}
}

System Generation 32-19


In this case, the code generator creates persistable Java classes that extend the
ObjectToObjectLink class and are capable of maintaining a persistent association.
Code-generated accessor methods return the role A and role B objects of the link.
This means that the developer need not be concerned with which object is the role
A object and which is the role B object.
Code-generated factory methods for Link classes take at least two arguments: the
role A object and the role B object. The factory methods are a result of the Link
interface extending the NetFactor interface. A full explanation of factory methods
is included in the section on Implementing the NetFactor Interface.

32-20 Windchill Customizer’s Guide


Implicit Persistable Associations Stored with Foreign ID
References
The following model shows an association between persistable objects where the
association has no attributes.

A Persistable Association Stored with a Foreign ID Reference

The link class is generated for LinkC, just as it was for LinkA, in the preceding
example. In addition, the following code is generated in the class that plays the
role opposite the role that has a cardinality of one.
public class OneMore implements Persistable, Externalizable {

public static final String A1 = "myItem>a1";


public static final String MY_ITEM_REFERENCE =
"myItemReference";

private ObjectReference myItemReference;

public String getA1() {


try { return getMyItem().getA1(); }
catch (NullPointerException npe) { return null; }
}

public void setA1( String a_A1 )


throws WTPropertyVetoException {
getMyItem().setA1( a_A1 );
}

public MyItem getMyItem() {


if ( myItemReference == null )
return null;
return (MyItem)myItemReference.getObject();
}

public ObjectReference getMyItemReference() {


return myItemReference;
}

public void setMyItemReference( ObjectReference


a_MyItemReference )
throws WTPropertyVetoException {

System Generation 32-21


myItemReferenceValidate( a_MyItemReference );
// throws exception if not valid
myItemReference = a_MyItemReference;
}
}

In this case, since the association is persisted via a foreign id in the table for
OneMore rather than in a separate link table, the OneMore class will hold a
reference to myItem and will get myItemReference accessors generated. In
addition to the getter and setter that are generated for the reference, a convenience
getter is generated for the myItem object.
Although these additional accessors are created for developer convenience, the
LinkC class that is generated for the association can be operated on in the same
manner as a link class that is stored in a separate link table. This provides a
common API for manipulating links, regardless of how the database storage is
implemented.
The example also had a derived attribute modeled for the OneMore class. The
DerivedFrom property for the attribute was defined as myItem>a1, which caused
the A1 label constant and accessors to be generated for the a1derived attribute. (If
this were a non-persistable association, the syntax for the derived attribute source
would be myItem.a1.)
Care should be taken in using this feature with persistable associations since
allowing the generation and use of a derived setter will cause a state change in a
different persistable object (myItem) which may not be obvious to the developer
who is using your class (OneMore). The generation of the setter can be turned off
while retaining the generation of the getter by setting the attribute’s WriteAccess
property to Private.

Explicit Persistable Associations


The following model shows an association between persistable objects where the
association has attributes.

An Association with Attributes between Persistable Objects

32-22 Windchill Customizer’s Guide


The following code is generated from this example:
public class LinkB extends ObjectToObjectLink implements
Externalizable {
. . .
/* everything that the implicit link has, plus normal
class generation for attributes, operations, etc. */
}

If an association has attributes associated with it, the code generator creates a Java
class that has all of the attributes for the association and the accessor. The name of
the generated Java class is the name of the attributing class.
The generated Java class extends the ObjectToObjectLink class if the attributing
class does not extend another class in the model. If the attributing class extends
another class in the model, the Java class extends that class. (The class being
extended must be a subclass of Link.)

Rose Association Specification


For the tabs that specify role information, there is a Role A tab and a Role B tab.
Both work essentially the same with the only differences being whether role A or
role B is referred to.
On the General tab, set the following values:
• Name specifies the name association that is the name of the resulting Link
class. If blank, it defaults to a role A/role B concatenation.
• Role A specifies the role A name. If blank, it defaults to the name of the role
A class (in this case, the class name is prefixed with "the" to avoid a naming
conflict). The popup menu for associations provides an alternative means for
specifying role A.
• Role B specifies the role B name. If blank, it defaults to the name of the role B
class (in this case, the class name is prefixed with "the" to avoid a naming
conflict). The popup menu for associations provides an alternative means for
specifying role B.
• The rest of the dialog is ignored by the code generator.
On the Detail tab, set the following value:
• Derived should be set to True to indicate that the implementation of the
association will be derived, as determined by the developer.
• The rest of the dialog is ignored by the code generator.
On the Windchill tab, set the following values:
• Java Properties
– Generate should be set to False if the system generation tools should not
generate a Java class for this modeled association.

System Generation 32-23


– SuperClass is the name of the link class that the class generated for the
association should extend. SuperClass should be defined when a class that
contains a ForeignKey association is a sub-class and the sub-class's
ForeignKey class referential integrity properties (i.e. Owner, Cascade)
should be inherited from the parent's ForeignKey class.
• SupportedAPI should be set to communicate to users the degree to which the
association class will be supported.
– Private if the association class will not be supported at all.
– Public if use of the class is supported.
– Extendable if extension of the class is supported.
– Deprecated if the class is obsolete and support is being phased out. (This
setting is superceded by the Deprecated property.)
• Deprecated should be set when the element is obsolete.
– <Default> indicates the class is not deprecated, unless, for backward
compatibility, SupportedAPI is set to Deprecated.
– -deprecated if the class is obsolete and support is being phased out.
• Datastore Properties
– PackageName is the package name to use.
– TableName is the database table name to use.
– Storage indicates if the association will be stored in a link table or as a
foreign ID reference in the table for one of the role classes. Default
evaluates to ForeignKey if there is a role with single cardinality and the
class opposite that role resides in the same package as the association;
otherwise, evaluates to LinkTable.
– RemoveEventParticipant specifies if the persistence layer is required to
dispatch Remove events for this implicit Link class. Remove events
include "REMOVE" and "CLEANUP_LINK". Default will be
determined to be True for any Persistable class.
• Oracle Properties
– TableSpaceName is the tablespace to use for storage option of the table.
– TableSize indicates if the relative size required for the objects that will be
stored (the actual storage values are mapped from the size via property
file settings).
– IndexTableSpaceName is the tablespace to use for the storage option of
the indices of the table.
• The rest of the dialog is ignored by the code generator.

32-24 Windchill Customizer’s Guide


On the Role <A/B> General tab, set the following values:
• Role specifies the name of the role. (See Role A (or B) description for
General tab above.)
• Export control should be set to Public, Protected, or Implementation. If
you want private attributes, declare them in your source code.
• Documentation specifies a description for the element. The documentation
will be generated into the Java code, as Javadoc style comments.
On the Role <A/B> Detail tab, set the following values:
• Role specifies the name of the role. (See Role A (or B) description for
General tab above.)
• Cardinality specifies the cardinality of the role. The popup menu for
associations provides an alternative means for specifying cardinality.
• Navigable should be selected if the role B (or role A) object should get a
method for accessing the role A (or role B) object. The popup menu for
associations provides an alternative means for specifying navigability.
Navigable is ignored for Persistable associations.
• Aggregate should be selected if the association is an aggregate. The popup
menu for associations provides an alternative means for specifying
aggregation.
• By value should be selected if the aggregate is a composite aggregation. The
popup menu for associations provides an alternative means for specifying
composite aggregation.
• The rest of the dialog is ignored by the code generator.
On the Windchill<A/B> tab, set the following values (ignored for Persistable
associations):
• Abstract should be set to True if the implementation of a field for the role
will be deferred to a subclass. Access methods generated for this role will be
abstract.
• StringCase should be set to LowerCase to force the value to lowercase. It
should be set to UpperCase to force the value to uppercase. The enforcement
of this constraint will be generated into the setter method for the attribute.
• LowerLimit constrains the valid values for the type. For String types, it
specifies the minimum length of the String. For numeric types, it specifies the
minimum value of the role. Date and Time types are not currently supported
by this property. The constraint is enforced in the validation that is generated
for the setter.
• UpperLimit constrains the valid values for the type. For String types, it
specifies the maximum length of the String. For numeric types, it specifies the
maximum value of the role. Date and Time types are not currently supported

System Generation 32-25


by this property. The constraint is enforced in the validation that is generated
for the setter.
• Changeable should be set to Frozen if the value cannot be changed once it
has been persisted. It should be set to ViaOtherMeans if the normal setter
method is not allowed to change the value once it has been persisted.
• WriteAccess should be set if the access of the setter should be different than
that of the getter that will be generated.
• Dependency should be set to True if the opposite-side role class is dependent
on this role.
• SupportedAPI should be set to communicate to users the degree to which the
role will be supported.
– Private if the role will not be supported at all.
– Public if use of the role is supported.
– Deprecated if the role is obsolete and support is being phased out. (This
setting is superceded by the Deprecated property.)
• Deprecated should be set when the element is obsolete.
– <Default> indicates the role is not deprecated, unless, for backward
compatibility, SupportedAPI is set to Deprecated.
– deprecated if the role is obsolete and support is being phased out.
• Java Properties
– Final should be set to True if the resulting field should be final.
– Transient should be set to True if the resulting field should be transient.
– Volatile should be set to True if the resulting field should be volatile.
– Constrain should be set to True if the resulting setter method should
declare that it throws a WTPropertyVetoException.
– ReferenceType specifies the class of ObjectReference that will be used
for first-class associations that are stored as with a ForeignKey and
thereby make use of a held ObjectReference. By default, the generic
ObjectReference will be used.
– AutoNavigate should be set to True if the object playing this role should
be automatically retrieved (instantiated) from the database whenever the
object on the other side is retrieved. Update operations are not impacted
by this property. This feature is dependent on the association being
implemented as a ForeignKeyLink.
– Persistent should be set to True if the field that holds the value will be
persisted to the database.

32-26 Windchill Customizer’s Guide


– GetExceptions specifies exceptions that will be declared as thrown by
the generated getter.
– SetExceptions specifies exceptions that will be declared as thrown by the
generated setter.
– ContainerClass specifies that class of container to use for roles of
unbounded multiplicity (cardinality). Default container is Vector.
– InitialValue specifies the value to which the field will be initialized upon
declaration.
– DelegatedInterface specifies that the object playing the role is a delegate
that supplies an implementation for the specified interface. All the
methods necessary to fulfill (implement) the interface will be generated as
methods that forward to the role object.
– BeforeStaticInitializer should be set to True if field declaration should
be placed prior to the static initializer.
• Datastore Properties
– ColumnName is the class attribute to column name mapping. Default is
the attribute name.
– ColumnType is used to indicate the relational storage type for the value-
type. By default a mapping, based on the attribute type, will be used.
– Index specifies whether an index is created for this attribute.
– Unique specifies whether a unique index is created for this attribute.
– Updatable specifies whether the column can be updated using standard
persistence mechanisms.
– Owner specifies if this role is an owner of the association. Owner means
when the is role is deleted, the association will be deleted also. Both roles
can be an owner. Default will be determined to be True for any role.
– Cascade specifies if association deletion should cascade to the role
object. Default will be determined to be False for any role.
• Oracle Properties
– TableSpaceName is the tablespace to use for storage option of the
table.
– TableSize indicates if the relative size required for the objects that
will be stored (the actual storage values are mapped from the size via
property file settings).

System Generation 32-27


• UI Properties
– Localizable indicates if the role will have a localizable display name
stored in the resource bundle for the package.
• The rest of the dialog is ignored by the code generator.

Implementing Interfaces
In Rose, an interface is modeled as a class that has the stereotype <<Interface>>.

Model of Implementing an Interface

In this example, MyItem, which is concrete, is said to implement the interface


named Timelineable, which aggregates Timeline. The following code is generated
for this example.
public class MyItem extends Item implements Timelineable,
Externalizable {

private Timeline timeline;

public Timeline getTimeline() {


return timeline;
}

public void setTimeline( Timeline a_Timeline )


throws WTPropertyVetoException {
timelineValidate( a_Timeline );
// may throw exception if not valid
timeline = a_Timeline;
}

private void timelineValidate( Timeline a_Timeline )


throws WTPropertyVetoException {
if ( a_Timeline == null ) {
// required attribute check
Object[] args = { new wt.introspection.PropertyDisplayName(
CLASSNAME, "timeline" ) };
throw new WTPropertyVetoException( "wt.fc.fcResource",
wt.fc.fcResource.REQUIRED_ATTRIBUTE, args,

32-28 Windchill Customizer’s Guide


new java.beans.PropertyChangeEvent( this, "timeline",
timeline, a_Timeline ) );
}
}
// The constant label is generated into the
// Timelineable interface
}

In general, system generation causes the following actions:


• Classes in the model that extend an interface cause an implements clause to be
created on the class declaration of the generated class.
• Stubs for the operations of the interface are created in the generated class if
the inheriting class is concrete. This is where you insert your implementation
code. (This applies even for protected methods modeled on an interface,
which will not appear on the generated interface since an interface can have
only public features.)
• Non-constant attributes modeled on the interface cause private fields to be
created on the generated classes that implement the interface, along with
generated accessor methods.
• Associations with non-persistable classes are handled similar to modeled
attributes, where the API is generated on the interface and the implementation
is generated into the concrete subclasses.

Implementing the NetFactor Interface


The vast majority of business classes provided with Windchill applications and
foundation components implement the NetFactor interface, either directly or
indirectly. Implementing this interface, in fact, indicates that a class is a business
class participating in the Windchill architecture.

Factory operations
To give flexibility to the system architecture, Windchill uses a factory design
pattern for the construction of Java objects. A constructor signature is one where
the operation name matches the name of the class and has no return type. Object
constructors are modeled in Rose but are not generated directly in Java code.
Instead of constructors, Windchill generates factory operations that are used to
construct objects.
Using factory operations instead of constructors provides the opportunity to vary
the class of the returned object. When constructors are used to create an object, the
class of the returned object must match exactly the class requested. However,
when factories are used, the class of the returned object will be polymorphically
compatible with the requested class but need not match the requested class
exactly. This allows the return of objects whose class may vary depending on the
context.

System Generation 32-29


When a constructor is specified in a Rose model, two operations are generated in
the Java code: a public factory operation and a protected initialization operation.
The factory operation is called directly by the application to create a Java
instance. The factory method calls the initialize operation to put the instance into
an initial state.
Note that for optimization reasons, an initialize method is generated only when
one having the same signature is not provided by a superclass. You can manually
supply an override initialize method if you wish.
If the modeled class (directly or indirectly) inherits from NetFactor, this is a cue to
the code generator to generate factory and initialize methods in the Java class. The
following modeled class has a constructor that takes an argument of a string.

Factory Operation for an Item

The following code is generated for this example (documentation omitted).


public class MyItem extends Item {
public static MyItem newMyItem( String arg1 )
throws WTException {
//##begin newMyItem% [ ]34F1E6BF02D9f.body preserve=no

MyItem instance = new MyItem();


instance.initialize( arg1 );
return instance;
//##end newMyItem% [ ]34F1E6BF02D9f.body
}

protected void initialize( String arg1 )


throws WTException {
//##begin initialize% [ ]34F1E6BF02D9.body preserve=yes

//##end initialize% [ ]34F1E6BF02D9.body


}
}

A factory method instantiates and initializes business objects. It invokes the


constructor of the implementation class and then invokes an initialize method with
the same parameters as the factory method.
The code generator also generates the correct method stubs so you can implement
the initialize method. This method is responsible for setting the initial state of a
new object.
Factory methods have the form:
public static <class> new <class> (args)

32-30 Windchill Customizer’s Guide


throws WTException
The factory method has the same name as the class in the Rose model plus the
prefix "new" (for example, newMyItem).
If no constructor is modeled for a class, the generator assumes a default, no-arg
constructor. For link classes, the default factory method includes a reference to the
two objects being related by the link. For details on link class generation, see the
Persistable Associations section.

Conceptual class name accessor


Every class that inherits from NetFactor implements a getConceptualClassname
instance method:
public String getConceptualClassname() {
return CLASSNAME;
}

This method returns the fully-qualified conceptual class name of the object.
Because the instantiated object may really be an instance of some other
implementation class, getConceptualClassname is a useful method to find the
business class in an object.
You should not use object.getClass().getName() to determine the class name for
software objects in the Windchill system because it may not return the name of the
conceptual class.

Info object accessor


Every class that inherits from NetFactor has an info object generated for it. The
code generator therefore ensures that each NetFactor instance supports the
getClassInfo method. This method is generated into the top class in each
hierarchy. For example:
public ClassInfo getClassInfo()
throws WTIntrospectionException {
return WTIntrospector.
getClassInfo( getConceptualClassname() );
}

This method returns the ClassInfo instance that contains the metadata from the
installed model.

Implementing the ObjectMappable interface


The database methods readExternal and writeExternal are code-generated for any
class that was modeled to implement the ObjectMappable interface. The
readExternal method reads the object’s state from the database. The writeExternal
method writes the object’s state to the database.
The class defers to its superclasses to read (or write) the state for the persistent
attributes that those classes declared. The class defers to its structured attribute

System Generation 32-31


classes, such as Address, to read (or write) the state for the persistent attributes
that those classes declared with the readObject and writeObject methods.
Because the class defers the reading of some of the fields from the database to its
superclass, the types of structured attributes are hard-coded into the super class.
The exception to this rule of hard-coded types is for ObjectReferences that are
generated for roles of Persistable associations. The Persistent Data Service (PDS)
does a runtime look-up in the introspection information to see if the
ReferenceType for the role was redefined at a lower level in the class hierarchy. If
so, the PDS uses that type. But even if the type is redefined, its persistent structure
must be compatible with the type that was used by the super class, because the
column definitions defined by a super class cannot be changed by a subclass.
The PersistentRetrieveIfc argument for readExternal contains the state for the
object being read. The PersistentStoreIfc argument for writeExternal receives the
state of the object being written.
Examples of the readExternal and writeExternal methods follow:
// Example of a database writeExternal method
public void writeExternal( PersistentStoreIfc output )
throws SQLException, DatastoreException {
super.writeExternal( output );
output.setString( "a1", a1 );
output.setDate( "a2", a2 );
output.setObject( "a3", a3 );
output.writeObject( "work", work,
wt.tools.generation.example.MyAddress.class, true );
output.setObject( "list", list );
output.setString( "size", size == null - null :
size.toString() );
output.writeObject( "timeline", timeline,
wt.tools.generation.example.Timeline.class, true );
}

// Example of a database readExternal method


public void readExternal( PersistentRetrieveIfc input )
throws SQLException, DatastoreException {
super.readExternal( input );

a1 = input.getString( "a1" );
a2 = input.getDate( "a2" );
a3 = (Xyz)input.getObject( "a3" );
work = (wt.tools.generation.example.MyAddress)input.readObject(
"work", work,
wt.tools.generation.example.MyAddress.class, true );
list = (Vector)input.getObject( "list" );
size = MySize.toMySize( input.getString( "size" ) );
timeline = (wt.tools.generation.example.Timeline)
input.readObject("timeline", timeline,
wt.tools.generation.example.Timeline.class, true );
}

32-32 Windchill Customizer’s Guide


Implementing the Persistable interface
The equals and hashCode methods are generated for non-interface subclasses of
Persistable. Any customized code with non-modeled equals or hashCode methods
will need to change the method's preserve flag in order to implement a non-default
equals or hashCode.

Caution: Certain core Windchill operations may depend upon these methods
being ObjectIdentifier-based. Changes to the default implementation should be
done with care, if at all.

Examples of the equals and hashCode methods follow:


// Example of an equals method
public boolean equals( Object obj ) {
//##begin equals%equals.body preserve=no

// WARNING: Do not change


return wt.fc.PersistenceHelper.equals(this,obj);
//##end equals%equals.body
}
// Example of a hashCode method
public int hashCode() {
//##begin hashCode%hashCode.body preserve=no

// WARNING: Do not change


return wt.fc.PersistenceHelper.hashCode(this);
//##end hashCode%hashCode.body
}

Implementing the Externalizable interface


A core feature of Java is the capability of streaming objects. This feature is used
for purposes such as persisting objects or passing Java objects by value on RMI
calls. There are two ways to support externalization: by using the tagging
interface Serializable or by using the interface Externalizable. When possible,
Windchill classes implement the more efficient Externalizable interface.
Sometimes it is not convenient to implement Externalizable and the less efficient
Serializable is used instead.
A class is generated to implement Externalizable, by default, if it meets the
criteria for Externalization. The criteria are as follows:
• Must have a public, no-argument constructor.
• Any parent class must be Externalizable.
A property in Rose allows you to override the default determination. This
property, named Serializable, is in the Java Properties on the Windchill tab for the
class. With this property, you can force the class to Serializable, Externalizable, or
neither.

System Generation 32-33


The Evolvable option has been added to this property to better manage which
classes can be serialized into BLOB columns in the database. This option was
added in conjunction with a change to the generated Externalization stream
format. Because of this change to the stream format, much externalization code is
generated to maintain backward compatibility. In a future release, only the
readExternal and writeExternal methods will be generated for classes that
implement Externalizable but not Evolvable. Until the backward compatibility is
removed, new classes can be forced to generate simplified externalization code by
selecting the "Externalizable (basic)" option. The evolvable aspects of
externalization will not be shown below. For details on when to use Evolvable and
how to manage Evolvable classes, see Evolvable Classes on page 43-1.

The serialVersionUID constant


The serialVersionUID is used to determine compatibility of classes when reading
them from an input stream. The mechanisms that perform the serialization and
externalization compute a serialVersionUID value at runtime when a class has not
explicitly defined the value to something other than zero.
When the code generator is generating externalization for a class, it sets the
serialVersionUID to 1 since compatibility is managed in the externalization
methods (as shown in the following section). This value must remain unchanged
to enable the hooks for reading old versions to be used.
The following is an example of defining the value for the constant:
static final long serialVersionUID = 1;

Externalization methods
In the generated externalization methods, all non-transient, non-static fields that
were modeled will be handled. The externalization is generated in a manner that
provides hooks for reading in previous versions of the class, unless "basic"
externalization is generated. Code generation detects when the externalizable
signature of a class changes, and changes its internal version UID accordingly.
You have the ability to take control of the externalization code, but it is not
recommended because it requires careful management of the externalizable
signature of the class.
Examples of the externalization methods follow:
// 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 );

32-34 Windchill Customizer’s Guide


output.writeObject( (size == null ? null :
size.getStringValue()) );
output.writeObject( theOneMoreReference );
output.writeObject( timeline );
output.writeObject( work );
//##end writeExternal%writeExternal.body

// Example of a readExternal method


public void readExternal( ObjectInput input )

throws IOException, ClassNotFoundException {

//##begin readExternal%readExternal.body preserve=no

long readSerialVersionUID = input.readLong(); //


consume UID

if ( readSerialVersionUID == EXTERNALIZATION_VERSION_UID ) {
// if current version UID

super.readExternal( input ); //
handle super class

a1 = (String)input.readObject();
a2 = (Date)input.readObject();
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();

else

throw new java.io.InvalidClassException( CLASSNAME, "Local


class not compatible:"

+ " stream classdesc


externalizationVersionUID=" + readSerialVersionUID

+ " local class


externalizationVersionUID=" + EXTERNALIZATION_VERSION_UID );

//##end readExternal%readExternal.body

System Generation 32-35


Extending the EnumeratedType class
The EnumeratedType class is a wrapper for a string whose valid values are
constrained to a defined set. A type, or class, can be created to define a specific set
of values by extending the EnumeratedType class.
The following model provides an example of creating an enumerated type.
MySize also shows the modeling of constants that reference certain values of the
set’s valid values.

Extending EnumeratedTypes

An example of the generated enumerated type follows:


public class MySize extends EnumeratedType {
// define the name of the resource bundle
private static final String CLASS_RESOURCE = MySizeRB;
// initialization of programmatic constants
public static final MySize SMALL = toMySize( "sm" );
public static final MySize MEDIUM = toMySize( "med" );
public static final MySize LARGE = toMySize( "lrg" );
// Obtain a MySize value from an internal value
public static MySize toMySize( String a_value )
// Obtain the default MySize "value"
public static MySize getMySizeDefault()
// Obtain the set of valid MySize "values"
public static MySize[] getMySizeSet()
// Obtain the set of valid MySize "values" (polymorphic)
public EnumeratedType[] getValueSet()
}

There should be no need for a developer to change any of the implementation of a


generated enumerated type, but they are generated with preserve markers to allow
for developer enhancements, if the need should arise. Note that the Windchill tab
on Rose specification dialogs for classes and attributes provides property set
sheets specific to EnumeratedType usage. These properties are detailed in the
model elements sections above.
For more information on working with enumerated types, see the Enumerated
Types chapter on page 34-1.

32-36 Windchill Customizer’s Guide


Stereotyping an interface as remote
When you model a service, you model interfaces and remote interfaces (see
Developing Server Logic chapter on page 36-1 for more information). The
<<RemoteInterface>> stereotype causes the code generator to generate a
forwarder class that clients can use to invoke the method on the server. A
forwarder class has the same name as the remote interface in the Rose model plus
the suffix "Fwd" (for example, TimelineServiceFwd).
The following is a model of a business service, stereotyped as a RemoteInterface.

Business Service Model

The following is an example of a generated remote forwarder:


public class TimelineServiceFwd implements
wt.method.RemoteAccess,
TimelineService, Serializable {
// constant that enables the object to know where it is
static final boolean SERVER =
RemoteMethodServer.ServerFlag;
// identifies what type of service to forward to
public Class getTypeClass() {
return example.TimelineService.class;
}
public void begin( Date beginDate ) throws WTException {
if (SERVER)
// invoke the service
else {
// remote call to the server
}
}
public void end( Date endDate ) throws WTException
}

System Generation 32-37


Services contain the complete business logic and are expected to run only on the
method server, but forwarders go back and forth between the server and the client.
From the client, they invoke the business service methods running on the server.
At runtime, the forwarder binds to a service which is determined by the
registration of services that is done in the wt.properties file.
The forwarder classes are completely generated and provide no preserve markers
for developer editing.

32-38 Windchill Customizer’s Guide


How Rose UML Maps to Info Objects
Introspection is part of the Java Beans specification. It is a standard method for
providing metadata information about an object, such as its attributes and the
methods it supports. Windchill extends that concept with Info objects.
Info objects contain class information from the Rose UML model that is needed
by the runtime system. One Info object is generated for each modeled class that
implements NetFactor, each modeled EnumeratedType subclass, and for each
modeled interface. The system generation tool creates Info objects by capturing a
subset of the class information stored in the Rose repository as serialized resource
files that are read by the runtime system.
Info objects contain information for the following elements:
• Classes and interfaces
– Descendents (that is, a list of subclasses, which allows you to determine
what classes are inherited from a specific class)
– Link membership
– Property descriptors for attributes
– Column descriptors containing attribute mapping information
– Database table, package, and other parameters
• Links (When you have a link, you can also create a link between objects that
are subtypes of the role A and role B objects. Therefore, you need to know
which are valid and how many there can be.)
– Role A and role B names
– Valid role A and role B classes
– Role A and role B cardinality
• Attributes of classes
– Standard JavaBeans PropertyDescriptor with extended information
– Derived flag
– Persistent flag
– Updateable flag
– Query name (name of its column descriptor)
– StringCase (if a String type is forced to either uppercase or lowercase)
– Required flag
– Upper limit
– Method that returns set of valid values

System Generation 32-39


– ConstrainedType (if type overridden in subclass)
– DefinedAs (class and attribute name as originally modeled)
– ModeledPersistentType (modeled column type)
For a complete description of the introspection information that is provided, see
the wt.introspection package entry in your installed Windchill Javadoc.
Windchill provides a utility to print the content of a serialized Info object. You
can run the utility as follows:
InfoReport <fully.qualified.classname>
The resulting report is in a file named <qualified.classname >.out, which is
located in the directory specified by the wt.temp property in wt.properties.
To print the info contents for each class of an entire package, you can run the
utility as follows:
InfoReport <fully.qualified.*>
Windchill also provides a utility that will verify the environment as it relates to
introspection information. That is, it will verify the existence and ability to load
all classes and serialized info objects that are referenced in the registry files. The
utility simply writes its output to the console, with reported problems being
preceded by three asterisks (***).
To verify the entire registry (the complete environment), enter the following
command:
executeTool wt.introspection.VerifyEnvironment registry
To verify a single package, enter the following command:
executeTool wt.introspection.VerifyEnvironment <fully.qualified.*>

32-40 Windchill Customizer’s Guide


How Rose UML Maps to Database Schema
Table 8-1 shows the possible Rose Types and the associated JDBC specification
standard SQL types and datastore SQL types (both Oralce and SQLServer). Table
8-2 shows how common Java types map to Rose Types. This table also shows
other allowable Rose Types for the given Java type. In the table below, the fully
qualified classnames for Types and WTTypes are java.sql.Types and
wt.introspection.WTTypes, respectively.

System Generation 32-41


Table 8-1: Possible Rose Types and the associated JDBC specification standard SQL
types and datastore SQL types

Rose Type JDBC Type Oracle Type SQL Server Type

INTEGER Types.INTEGER NUMBER INT

BIGINT Types.BIGINT NUMBER BIGINT

SMALLINT Types.SMALLINT NUMBER SMALLINT

TINYINT Types.TINYINT NUMBER TINYINT

REAL Types.REAL NUMBER FLOAT(24)

DOUBLE Types.DOUBLE NUMBER FLOAT(35)

BIT Types.BIT NUMBER(1) TINYINT

CHAR Types.CHAR CHAR(3) NCHAR(1)

VARCHAR Types.VARCHAR VARCHAR(length) where NVARCHAR(length)


length is the UpperLimit where length is the
value (default=200). The UpperLimit value
length value may also be (default=200).
multiplied by the
wt.db.maxBytesPerChar
value for multi-byte
configurations

NUMERIC Types.NUMERIC NUMBER DECIMAL(28)

DATE Types.DATE DATE DATETIME

BLOB Types.BLOB BLOB IMAGE

SMALLBLOB WTTypes.SMALLBLOB VARCHAR (4000) VARCHAR (4000)

INLINEBLOB WTTypes.INLINEBLOB VARCHAR (4000) VARCHAR (4000)


BLOB IMAGE
Two columns are Two columns are
generated. The encoded generated. The
object is stored in the encoded object is
VARCHAR column if it stored in the
fits, otherwise the BLOB VARCHAR column
column is used. if it fits, otherwise the
IMAGE column is
used.

SEQUENCE WTTypes.NUMERIC NUMBER BIGINT

32-42 Windchill Customizer’s Guide


Table 8-2 : How common Java types map to Rose Types

Java Type Default Mapping JDBC Type Allowable Mappings

java.lang.Integer(int) INTEGER Types.INTEGER

java.lang.Long (long) BIGINT Types.BIGINT SEQUENCE

java.lang.Short (short) SMALLINT Types.SMALLINT

java.lang.Byte (byte) TINYINT Types.TINYINT

java.lang.Float (float) REAL Types.REAL

java.lang.Double
(double) DOUBLE Types.DOUBLE

java.lang.Boolean
(boolean) BIT Types.BIT

java.lang.Char (char) CHAR Types.CHAR

BLOB
java.lang.String VARCHAR Types.VARCHAR INLINEBLOB

java.math.BigDecimal NUMERIC Types.NUMERIC

java.sql.Date DATE Types.DATE

java.sql.Time DATE Types.TIME

java.sql.Timestamp DATE Types.TIMESTAMP

java.sql.Blob BLOB Types.BLOB

wt.fc.LobLocator BLOB Types.BLOB

SMALLBLOB
All other types BLOB Types.BLOB INLINEBLOB

System Generation 32-43


Java to SQL Mapping
Each persistable class maps to a database table. Each persistent attribute in the
class is mapped to a column name in the table. Structured attributes, like the
Address class shown earlier, are decomposed into their simple attributes.
Attributes are stored as lobs when no SQL-supported mapping is found, or if the
cardinality is greater than one (because SQL cannot allocate space for an
indefinite number of columns and rows).
Tables contain all the attributes they inherit from classes above them. Because a
class must be persistable to be in the database, all tables contain the persistInfo
attributes, including the object identifier.
The figure below shows a representation (not the actual columns) of the table that
is generated for the modeled class.

Mapping a Model to the Database

MyItem is persistable because it extends Item, which extends WTObject, which


implements the Persistable interface. Therefore, a table is created in the database
for the objects in MyItem.
The first element shown in the table, Attributes of superclasses, represents the
persistent attributes (from persistInfo) that MyItem inherits from its superclasses.
Each of the attributes would be mapped to a separate column in the actual table.
One of those columns would be the object identifier.
Attribute a1 is a String, so column A1 is a VARCHAR (NVCHAR for
SQLServer). Attribute a2 is a Date (actually a java.sql.Date), so column A2 is a
DATE (DATETIME for SQLServer). Attribute a3 has no SQL mapping support
but is serializable so the value for a3 is stored in column A3 as a BLOB (IMAGE
for SQL Server).

32-44 Windchill Customizer’s Guide


MyItem has a one-to-one composite aggregation relationship with Address, so the
attributes of the Address class are mapped to the MyItem table. Windchill uses a
naming algorithm to map attributes of an embedded structured attribute to table
column names. To list the mapping, use the InfoReport utility mentioned in the
section on how Rose UML maps to Info objects, earlier in this chapter.
MyItem has a one-to-many composite aggregation relationship with NameValue,
so NameValue is stored as a BLOB.
By default, the class name is mapped to the table name. You can specify a
different name with the Rose specification table name property.

Caution: Each class must be mapped to its own unique table name. If the table
name of a customized class conflicts with that of an out-of-the-box class or
another customized class, then it must be changed using the Rose specification
table name property. Similarly, you should change the table name to avoid
matching a datastore reserved word used in your database (such as VIEW).

Some additional properties can be specified to influence storage options. The


storage for tables, indexes, and blob data is referred to as a tablespace in Oracle
and a filegroup in SQLServer. The Windchill datastore term for both of these is
tablespace. By default, all Windchill tables and indexes are created in the
Windchill user’s default tablespace. Data for the table can be stored elsewhere by
specifying a TableSpaceName. If an IndexTableSpaceName is specified, it is used
to store the indexes for the table. The TableSize (TINY, SMALL, MEDIUM,
LARGE, or HUGE) is used together with the associated properties in the tools
properties1 to specify storage parameters for tablespace.
The default storage mechanism for BLOB attributes is to store them in their own
tablespace. The name of the tablespace is a configurable property in the tools
properties. The default name is BLOBS. For further information, see the section
on creating large objects in the Creating Large Objects (LOBs) chapter on page
44-1.
By default, generated SQL files explicitly reference two different tablespaces,
blobs and indx. All blob data storage is allocated in the blobs tablespace and all
index storage is allocated in the indx tablespace. The storage for all other schema
objects (e.g., tables) is not specified, so their storage is allocated in the default
tablespace configured in the datastore. The default values for all of these
tablespaces can be overridden in user.properties using the properties,
wt.generation.sql.BLOBTablespaceName,
wt.generation.sql.indexTablespaceName,
wt.generation.sql.defaultTablespaceName, and
wt.generation.sql.auditTablespaceName.In addition, the table and index
tablespaces for a given table can be overridden using the Class Specification,
Windchill tab, tablespace fields.

1. See the tools.properties file and user.properties file descriptions in the The Windchill
Development Environment chapter on page 2-13.

System Generation 32-45


Each attribute of the table also has properties which can be specified for the DDL
generation, such as whether to allow NULLS or whether to index the attribute. If
more complex indexing is required, then the Rose Class specification Windchill
index properties should be used. There are several index entries available for
specifying composite indices. Composite unique indices are also supported. See
the Rose Windchill Help documentation for more information. Typically indices
are generated into the associated table creation script. However, a utility,
IndexGenerator, is also available that generates scripts containing only indices.
For complex DDL statements associated with a class that cannot be handled by
the SQL generation support, the user additions script feature is available. It is
recommended that this feature only be used if absolutely necessary. When the
Rose modeling DDL generation features are used, this information can also be
used by the upgrade tools to ensure that the DDL is migrated properly. Every
generated sql script contains a line at the end to execute the statements in an
associated sql file. If the <tablename>_UserAdditions script is located in the same
directory as the table script, then this line is not commented out of the script that
creates the table.
For a many-to-one aggregation implemented via a foreign key, the autoNavigate
property can be used. When the autoNavigate property is set to true, the runtime
query APIs treat the columns on the base table along with the columns of the
aggregated table in much the same was as a database view. The two tables are
implicitly joined via the foreign key.
There are two types of modeled sequence data types. For attribute-based
sequences, you can make the attribute type Long and select SEQUENCE from the
WT_Oracle tab for the column type. This causes the DDL generation to create a
sequence (if it does not already exist) with a name that consists of the
attributeName and the suffix "_seq". When an object that uses an attribute-based
sequence is created and persisted in the datastore, the sequence value is
incremented and used for that attribute's value.
Sequences can also be created as standalone datastore elements. A sequence will
be generated for any class that extends wt.fc.DatastoreSequence. The datastore
schema name, initial seed value, and increment value can all be set from the Rose
model. You can use PersistenceManager.getNextSequence() to obtain the next
available sequence number. This method returns a String, so you would either use
the value as a String or convert it to whatever you need.
All the database scripts necessary for a given java package are generated to an
associated subdirectory of the database generation directory. In addition, "make"
scripts are generated for the entire package. The "Make_<package name>" script
calls all the scripts for creating the datastore schema objects. The "make" scripts
will also call the associated make scripts in any nested packages.

32-46 Windchill Customizer’s Guide


How Rose UML Maps to Localizable Resource Info Files
Since Windchill is localized to run in a variety of locale specific languages,
default display names are generated into localizable resource info (.rbInfo) files,
for each model element name that might need to appear on a user interface.
Language translators can then create localized versions of these files, so that
modeled elements can be displayed in a locale specific language.
The Localizable property is available on the Windchill tab of the Package, Class,
Attribute and Association Role specifications in Rose. The purpose of this
property is to limit the entries in the resource info files to those that need to be
translated.
The Class Localizable property is an enumerated type, and has three possible
values: <Default>, True and False. The default value is <Default>. The Class will
be considered Localizable by the localizable display generator only under the
following circumstance:
• The Class Localizable property is explicitly set to True
The Localizable property for Attributes and Roles is also an enumerated type, and
thus has possible values: <Default>, True and False. The default value is
<Default>. These elements will be considered Localizable by the localizable
display generator only under the following circumstance:
• The element's Localizable property is explicitly set to True
If the resource info file contains an entry for a particular model element, the
generator will not overwrite it, but it can remove it if the modeled element no
longer exists, or if it is no longer considered localizable. The removal of elements
is controlled by the wt.generation.cleanupDisplayNames property in the tools
properties. For more information on creating localizations, see the
Internationalization and Localization chapter on page 40-1.
The generated resource info files should only be edited by the owner of the
package. The resource info tool set provides a means of customization, where the
customers of the package can define customizations in a separate file.
The name of the file is "ModelRB.rbInfo", with the simple package name
prepended, for example, partModelRB.rbInfo. The following sections describe the
generated resource info files.

Metadata Resource Info Header


Each resource info file contains the following lines that define certain file level
information:
ResourceInfo.class=wt.tools.resource.MetadataResourceInfo
ResourceInfo.customizable=true
ResourceInfo.deprecated=false

System Generation 32-47


Resource Entry Format
See Resource Entry Format in the Internationalization and Localization chapter on
page 40-9.
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.

Metadata Resource Entry Examples


Below are examples of the default entries that are generated.
WTPart.value=Part
WTPart.partType.value=Part Type

The first entry is the display name for the WTPart class, and the second is the
display name for partType attribute of the WTPart class. These values will only be
generated once, so that the package owner can override the default values, if
desired. For example, the value for the partType attribute could be changed as
follows:
WTPart.partType.value=Type

In addition, any of the keys described in the Resource Entry Format on page 40-9,
could be added for an element. For example, the following information could be
added for the partType attribute.
WTPart.partType.fullDisplay=Part Type
WTPart.partType.longDescription=Classification of parts
according to predefined types.

Note: Follow the practices described in the Managing Customizations chapter on


page 5-1 when customizing rbInfo files.

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 modelRB file, use
the following command:
ResourceBuild <absolute_directory>
For example:
ResourceBuild <Windchill>/src/wt/part

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

32-48 Windchill Customizer’s Guide


The resulting resource file is named <name>RB.ser, which is a serialized instance
of SerializedResourceBundle. For example, src/wt/part/partModelRB.rbInfo will
build to codebase/wt/part/partModelRB.RB.ser.
To print the contents of the serialized resource bundle, you can run the following
utility:
windchill wt.util.resource.ResourceBundleUtil
<fully_qualified_name> [<locale>]

For example:
windchill wt.util.resource.ResourceBundleUtil
wt.part.partModelRB en_GB

The output goes to: $(wt.temp)part.partModelRB_en_GB.lst

System Generation 32-49


Using the Windchill System Generation Tool
When you are ready to generate code, the packages being generated must be
loaded in the model. Any model dependencies will automatically be loaded as a
result of generating. Therefore, it is not necessary to load the entire model, or even
to manually load dependent packages. Also, ensure that your WT_WORK Rose
Edit Path variable specifies the correct location for the generated mData (model
data) files.
To use the Windchill System Generation Tool from Rose, select the classes and
packages for which you would like to generate code. Go to the Tools menu, select
the Windchill menu item, and then select the System Generation option. A popup
window allows you to select the desired system generation options. WT
Introspector Support creates the Info objects. Database Support creates the DDL
scripts for the database. Localizable Displays updates the resource info (rbInfo)
files for the generated packages.

System Generation Dialog

As mentioned in the overview at the beginning of this chapter, the system


generator creates mData files which, in turn, are used to create Java code, Info
files, SQL files and Resource Info files. The system generator also updates the
classRegistry, descendentRegistry and associationRegistry, properties files.

Registry Files
The classRegistry, descendentRegistry, and associationRegistry files are located
in the directory specified by the wt.generation.bin.dir entry in the tools properties.
The classRegistry file contains all the information the code generator needs to
create import statements for the generated Java classes. When classRegistry is

32-50 Windchill Customizer’s Guide


initialized, it goes through all the directories in your CLASSPATH variable and
makes an entry for every class it finds. The classRegistry must be deleted and
regenerated if you change your CLASSPATH to include new packages that
contain classes for which the code generator will need to generate imports.
As the number of CLASSPATH packages increases, the potential for conflicts
increases. These conflicts are best resolved by explicitly modeling package level
dependencies in Rose. The generator will then use this information to resolve any
ambiguities that occur due to having multiple classRegistry entries for a particular
class name.
The descendentRegistry file contains genealogy information about which classes
extend the classes above them. It is required to support subclass queries. The
associationRegistry contains information about Persistable associations.
Classes that are renamed or removed from a package will be automatically
removed from the registries upon a regeneration of that package. A complete
package can be removed from the registries (uninstalled), by using the
modelUnInstall script.

Generating mData Files


An mData file is an ASCII file in non-proprietary format that contains all the
information the Windchill system generation tool needs. It is an intermediate file
format that allows for support of other model specification tools in the future.
The mData files contain all of the information about the models. The export tool
creates one mData file for each package in Rose and puts them in the WT_WORK
directory.
The mData files have a directory structure that maps to the package structure
inside Rose. For example, because there is an fc package in Rose, there is a
corresponding fc directory in the WT_WORK directory. In that fc directory is one
mData with the name of the package (for example, fc.mData).
Using mData files, the system generator creates Java classes and Info files. Java
classes are source code that is generated into the source tree directory. Info files,
because they are serialized resource files, are generated into the directory where
Java classes are located.

Generating Java Code


As described earlier in this chapter, one Java class is generated for each modeled
class. In addition, classes modeled as remote interfaces (such as
TimelineService.java) will have forward classes generated for the service (such as
TimelineServiceFwd.java).
All the generated Java classes are put into directories, specified by the
wt.generation.source.dir entry in the tools properties, which follow the package
structure. All the classes generated for a particular package are placed in the
corresponding directory.

System Generation 32-51


Generating Info Files
Info files contain all the metadata needed by the run time system. They are
generated from the corresponding mData files, one Info file for every interface,
and one for each class that implements NetFactor. Info files are put into
directories, specified by the wt.generation.bin entry in the tools properties, using a
directory structure that follows the package structure. The generated file name is
the same as the class name plus the suffix ClassInfo.ser (such as
MyItem.ClassInfo.ser).

Generating SQL Files


SQL files contain DDL for generating datascore schema objects for persistable
classes. On the System Generation window, you can choose Database Support and
the system generator creates the SQL files for you. If you do not choose that
option, the system generator creates the information necessary for you to generate
the SQL files yourself. Input always comes from the corresponding Info files.
A utility is provided which allows you to generate SQL yourself. For each
persistent class from your model, enter the following command:
JavaGen "<your package .your classname>"F F True F F
Or, to generate the SQL for an entire package, enter the following command:
JavaGen "<your package >.*" F F true F F
When specifying your class, include the fully qualified name of the class, which
includes the parent package names.
If you want to change the default storage parameters in the user.properties file and
recreate all the SQL, Windchill DDL can be regenerated for all modeled and
registered classes by entering the following command:
JavaGen registry F F true F F
DDL is generated into a datastore specific sql subdirectory named by the
wt.generation.sql.dir property you specified in the user.properties file. For
SQLServer, the directory name is sqlServer. For Oracle, the directory name is sql.
For Oracle, if the wt.db.maxBytesPerChar property is greater than one, then the
numeral is appended to the "sql" name. For example, if wt.db.maxBytesPerChar is
3, then the directory name would be sql3. File names are of the form create_
<tablename >.sql.
Regardless of how you generated the SQL files, you must execute the DDL in
these files to create the schema object.
For Oracle, Oracle’s SQLPLUS application is used. Ensure that your SQLPATH
environment variable is correct or, in the command you enter next, specify the full
path to the SQL file. Use the following command:
sqlplus <user/password >serviceName > @create_ <your table name >

32-52 Windchill Customizer’s Guide


If you have classes and tables, it is useful to create a single SQLPLUS script that
can execute each @create script. (The create_ddl_wt.sql script is an example.)
For SQLServer, a java command line application is provided in Windchill
codebase. In addition, a bat file has also been created in $wt.home/db/sqlServer.
Use the following command:
execute_sql_script create_ <your table name >

System Generation 32-53


Using Windchill System Generation in a Build Environment
Using the Windchill System Generation tools in an integrated build environment
requires an understanding of the dependencies that need to be managed. The
following table shows the input and output relationships between the various
artifacts of system generation.

Process Input(s) Outputs

Export Model Data Rose model (.mdl and/or .cat) mData file

Populate Model Registries mData files for all dependent modelRegistry.properties


packages –
descendentRegistry.properties 1
associationRegistry.properties 1

Populate Class Registry tools properties – classRegistry.properties


wt.classRegistry.search.path
tools properties –
wt.classRegistry.search.pattern

Generate Java Source classRegistry.properties .java files


– modelRegistry.properties
modelRegistry.properties descendentRegistry.properties
registered mData files associationRegistry.properties

mData file for target package

Generate Info Objects modelRegistry.properties .ClassInfo.ser files


registered mData files . modelRegistry.properties
mData file for target package descendentRegistry.propertiesN
associationRegistry.properties

Generate SQL Scripts .ClassInfo.ser files for target .sql files


package and dependents

Generate Resource Info .mData file for target package .rbInfo files

Build Resource Bundles .rbInfo files for target package .RB.ser files

1. Accumulated during generation, but used to define the modeled relationships for the installed runtime application.

Management of the mData File


An mData (model data) file is generated from the Rose .mdl and/or .cat file by
using the Windchill Generation option on the Tools menu in Rose. If the mData
will be used to generate code in an integrated build environment, the mData file
must be kept synchronized with the cat file. This is best accomplished by always

32-54 Windchill Customizer’s Guide


checking in and checking out the two files in tandem, and ensuring that the
generated mData reflects the saved version of the cat file.

Build Sequence
The following table describes the steps and commands used in a build sequence.

Step Description Command

1 Create classRegistry, based on search path and tools class_registry


pattern defined in tools properties.1 -Dclass_registry.use_env=true

2 Register all models that will be integrated ModelInstall "<package>.*"

3 Generate Java source code, info objects, SQL JavaGen "<package>.*"


and resource bundle files scripts for target
packages.2

4 Build the resource bundles for target directory. ResourceBuild"<dir\sub>"

5 Compile Java source code. javac ...

1. The system generation tool will create a classRegistry if one does not exist.
2. Remember to update database table structures after generating SQL scripts that have structural changes.

Command Line Utilities


Most of the utilities below are wrappers around Ant tasks that reside in bin\
tools.xml. Therefore, the utilities below, plus others, can also be executed directly
with Ant.
tools
Access point to Ant targets that implement most of the utilities listed below.
Executing this script with no arguments will list the targets that are available
and explain how to get configuration options help for each target.
tools class_registry
Creates a class registry from scratch, searching for *.class & *.java files in the
specified classpath. To specify the classpath, use one of these properties:
– class_registry.use_env - if true, will use the environment's classpath
– class_registry.classpath - can define any specific classpath
ModelInstall
Updates the model registries with all the modeled packages specified by
Arg1. Arg1 can be either of the following:
"<package>.*"

System Generation 32-55


Registers the single package specified.
"<package>.**"
Registers the package for each mData found recursively under the
<package> directory.
ModelUnInstall
Removes the modeled packages specified by Arg1 from the model registries.
Arg1 can be either of the following:
"<package>.*"
Removes the single package specified.
"<package>.**"
Removes the package for each mData found recursively under the
<package> directory.
JavaGen
Generates the outputs specified by the arguments for the classes/packages
specified by Arg1. Arg1 can be any of the following:
“<package>.<Class>”
Generates outputs for the single class specified.
“<package>.*”
Generates outputs for the single package specified.
“<package>.**”
Generates outputs for each mData found recursively under the
<package> directory.
registry
Generates outputs for all registered packages.
The following additional arguments can be specified:
Arg2
Specifies if Java Source will be generated.
Arg3
Specifies if Introspector Info Objects will be generated. When using this
argument, it is recommended to comment out the following line in the
moduleRegistry.properties file:
Module1=WNC/Windchill

Therefore, you should generate Info Objects separately from any other
generations you are performing. For example, when generating info
objects for all registered packages, do the following:

32-56 Windchill Customizer’s Guide


1. Comment the moduleRegistry entry indicated above.
2. Execute JavaGen registry f true f f f
3. Uncomment the moduleRegistry entry.
Any other generations should be performed with Arg3 set to f.
Arg4
Specifies if SQL scripts will be generated.
Arg5
Specifies if Model Check will be performed.
Values for arguments not passed will be obtained from the tools
properties.
Arg6
Specifies if Display Names will be generated into resource info files.
ResourceBuild
Builds the runtime resource bundles for the packages/directories specified by
Arg1. Arg1 can be any of the following:
“<package>.<resource>”
Builds resource bundle for the single resource info.
"<absolute_dir\sub>"
Builds resource bundles for each resource info found under in the
directory. ( “<absolute dir\sub>”is an absolute directory.)
The following additional arguments can be specified:
Arg2
Specifies if locale specific files will be built. (wt.locale.set in
wt.properties define valid locales)
InfoReport
Reports the contents of info objects to a text file for classes/packages
specified by Arg1. Arg1 can be any of the options below.

Note: To display characters entered using something other than the default
encoding, set the wt.locale.encoding property to the encoding appropriate to
your locale before running this utility.

“<package>.<Class>”
Reports for the single class specified.
“<package>.*”

System Generation 32-57


Reports for the single package specified.
registry
Reports for all registered packages.
VerifyEnvironment
Verifies the existence and ability to load all classes and serialized info objects
that are referenced in the registry files. One caveat is that classes that have
static initialization that requires a running method server environment will fail
to load. Arg1 can be any of the following:
executeTool wt.introspection.VerifyEnvironment "<package>.<Class>"
Verifies the single class specified.
executeTool wt.introspection.VerifyEnvironment "<package>.*"
Verifies the single package specified.
executeTool wt.introspection.VerifyEnvironment registry
Verifies all registered packages.

32-58 Windchill Customizer’s Guide


IndexGenerator
Generates index creation (and drop) DDL to a standalone SQL script. The
utility supports both a single package and all indices for all modeled
packages.
executeApp wt.tools.generation.sql.OracleIndexGenerator "*" "create file
name" "drop file name"
Generates index creation DDL for all modeled packages to the specified
files. Files names must be absolute. The "*" parameter must be specified
in quotes.
executeApp wt.tools.generation.sql.OracleIndexGenerator
“<package>.*" "create file name" " drop file name"
Generates index creation DDL for the package to the specified files. If a
file path is not absolute, then it is treated as path relative to the
wt.generation.sql.dir directory.

System Generation 32-59


Deploying Modeled Customizations

Objective
You have created some modeled customizations on a development system, using
Windchill InfoModeler. You want to deploy these customizations on your
deployment system.

Background
It is recommended that you develop Windchill customizations on a development
system that is separate from your deployment system. If you create modeled
customizations (that is, using Windchill InfoModeler), follow this best practice to
deploy your generated artifacts, rather than regenerating them on the deployment
system.
For example, your deployment system may run on an operating system (such as
HP-UX) that does not support Windchill InfoModeler. To create modeled
customizations, you could use a Windows server as your development system and
run Windchill InfoModeler on that system. You would then follow this best
practice to copy the necessary generated artifacts to your deployment system.

Scope/Applicability/Assumptions
Assume you have created new modeled customization packages on your
development system.
Assume that, prior to your new customization, your development environment
included all the packages the production environment has. This best practice does
not apply if, for example:
·Your production environment is an aggregation of multiple development
environments;
·You have installed anything (such as an upgrade or module) into production that
is not also in your development environment.

Intended Outcome
Your deployment environment will again mirror your development environment,
including your new customizations.

Solution
Copy the relevant files from your development system to your deployment
system.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:

32-60 Windchill Customizer’s Guide


• Some method for transferring files from your development system to your
deployment system.
• Executing SQL scripts on your database server.

Solution Elements

Element Type Description

Customized packages Filesystem folders Any folder corresponding to a


and their contents customized package, containing
compiled Java classes and related
artifacts for the modeled and
generated customization. This
includes .class files, .RB.ser files, and
.ClassInfo.ser files.
Located under
<Windchill>/codebase.

Registry files Property files Specifically, this includes the


following registry files:
modelRegistry.properties
descendentRegistry.properties
associationRegistry.properties

Located in <Windchill>/codebase.

SQL files SQL files These contain generated SQL scripts


for creating the necessary database
tables for your customized objects.
Located in <Windchill>/db/sql.

Procedure - Deploying Modeled Customizations


Copy the folders and files described above from your development system to
corresponding locations in your deployment system.
1. Place customized package folders in an equivalent folder structure relative to
the <Windchill>/codebase directory.
2. Place the modified registry files in the <Windchill>/codebase directory on the
deployment system, replacing existing registry files.
3. Place the generated SQL files in the <Windchill>/db directory on the
deployment system.
4. Execute the SQL scripts (for example, by running SQL*Plus against an
Oracle server) to create the customized database tables.

System Generation 32-61


32-62 Windchill Customizer’s Guide
33
Customizing Modeled Elements

This chapter describes how to customize modeled elements.

Topic Page
Customizing Column Lengths...........................................................................33-2

33-1
Customizing Column Lengths
A column length for a modeled attribute can be customized. These column lengths
are obtained through the wt.introspection package. The default column lengths are
defined in the delivered Rose models with the attribute’s UpperLimit property.
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 properties1. Create this directory
if it does not already exist.
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

d. Based on this information, use the following values:


• The customization property file is <Windchill>\wtCustom\wt\doc\
docModel.properties.

1. See the tools.properties file and user.properties file descriptions in The Windchill Development
Environment chapter on page 2-13.

33-2 Windchill Customizer’s Guide


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


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

b. Inspect the infoReport’s descendents list for the WTDocumentMaster


class:
getDescendentInfos():

ClassInfo wt.build.buildtest.SourceMaster
ClassInfo wt.federation.ProxyDocumentMaster

c. If the customized class has descendants that are concrete, their tables
must also be adjusted with the following commands (one line each):
ant -f <Windchill>\bin\tools.xml custom_column -
Dgen.input=wt.build.buildtest.SourceMaster

ant -f <Windchill>\bin\tools.xml custom_column


-Dgen.input=wt.federation.ProxyDocumentMaster

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, perform the following steps:
i. Verify that the generate step actually updated the following serialized
info file:
<Windchill>\codebase\wt\doc\WTDocumentMaster.ClassInfo.ser

ii. Verify that a class or interface in WTPartMaster’s hierarchy does not


also define the name attribute. This is done most easily by viewing
the Attributes tab of the Class Specification dialog in Rose, with
Show inherited selected. If the name attribute is defined in the
hierarchy, the name attribute that was modeled originally must be
customized.

Customizing Modeled Elements 33-3


5. Create the database tables, if they don’t 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. Execute the Upgrade Manager to run the Compare Schema step only. See
"Comparing a Database Schema with Persistence Model" in the Windchill
Upgrade Guide.
b. 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

c. Execute the relevant SQL scripts.


Because, in this example, WTDocumentMaster.name is also the source for the
derived attribute WTDocument.name, the derived attribute must also be
customized in this manner. This customization is necessary because the derived
attribute, WTDocument.name, does not get its UpperLimit from the source
attribute, WTDocumentMaster.name. The derived attribute also explicitly set the
UpperLimit property in the model. Therefore, the customization must be defined
explicitly for the derived attribute WTDocument.name. Following the preceding
steps would determine that a WTDocument.name.UpperLimit entry would be set
in the customization property file <Windchill>\wtCustom\wt\doc\
docModel.properties. This additional step applies specifically to the way derived
attributes work and is not necessary for normal attributes.

33-4 Windchill Customizer’s Guide


34
Enumerated Types

This chapter describes enumerated types.

Topic Page
The EnumeratedType Class...............................................................................34-2
Creating an EnumeratedType Subclass.............................................................34-3
Editing the Resource Info for an Enumerated Type..........................................34-7
Localizing an Enumerated Type........................................................................34-9
Extending an Enumerated Type ......................................................................34-10
The Enumerated Type Customization Utility .................................................34-11
GUI Usage of an Enumerated Type ................................................................34-12

34-1
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.
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().

34-2 Windchill Customizer’s Guide


Creating an EnumeratedType Subclass
To create an EnumeratedType subclass, perform the following steps:
1. Model a class that extends wt.fc.EnumeratedType.

Select the EnumeratedType property set on the Windchill tab of the Class
Specification. This property set provides just the properties that apply to
EnumeratedType classes, and changes the default values of certain properties,
such as PrimitiveType to String.
If the values are to be ordered explicitly, set the ExplicitOrder property to
True. Otherwise, the values will be ordered alphabetically at runtime, using
the locale-specific display.

Enumerated Types 34-3


The Localizable property under the UI Properties section refers to the name of
the class being localizable, not the display values.

2. Generating the EnumeratedType also generates its companion resource info


file. For MySize, it will be named MySizeRB.rbInfo.

If the wt.resource.updateLocales property of the tools properties1 is set to


true, any locale-specific versions of the rbInfo file will also be updated,
indicating which entries need to be translated.

1. See the tools.properties file and user.properties file descriptions in the The Windchill
Development Environment chapter on page 2-13.

34-4 Windchill Customizer’s Guide


3. Optionally, model any desired programmatic constants. For example:
SMALL : MySize = toMySize( "Sm" )

Modeled constants are Static and Final. A value definition for each modeled
constant will be generated in the resource info file.

Enumerated Types 34-5


Select the constantEnumeratedType property set on the Windchill tab of the
Attribute Specification. This property set provides just the properties that
apply to EnumeratedType constants, and changes the default values of certain
properties, such as BeforeStaticInitializer to False. If the constant represents
the default value for the EnumeratedType, set the DefaultValue property to
True. To explicitly define the display name to generate into the resource info
file, set the Display property. Otherwise, the generated display name will be
based on the initial value of the constant.

34-6 Windchill Customizer’s Guide


Editing the Resource Info for an Enumerated Type
The name of the generated resource info file is RB.rbInfo, with the simple
package name prepended, for example, MySizeRB.rbInfo. The following sections
describe the resource info files that are generated.

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 in the Internationalization and Localization chapter on
page 40-9.
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 that are generated:
lrg.value=lrg
lrg.order=30

med.value=med
med.order=20

sm.value=sm
sm.order=10

These default values are generated only once, so that the package owner can
override the default values, if desired. If the class’s ExplicitOrder property is set
to True, the orders are controlled by the generator, and should not be edited
directly in the resource info file. If one of the constants has DefaultValue set to
True, it is controlled by the generator. For example, the value for the "sm" value
could be changed as follows:
sm.value=Small
sm.shortDescription=Small Comment
sm.order=10
sm.defaultValue=true

Enumerated Types 34-7


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_name>
For example:
ResourceBuild wt.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 wt/example

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.

34-8 Windchill Customizer’s Guide


Localizing an Enumerated Type
To have a locale-specific set of display values for an enumerated type, a locale-
specific version of the enumerated type’s 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 34-9


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.

34-10 Windchill Customizer’s 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, this utility should be
used 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.

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.

Enumerated Types 34-11


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

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 the
Managing Customizations chapter on page 5-14) 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.)

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

34-12 Windchill Customizer’s Guide


35
Windchill Design Patterns

This section describes design patterns that represent Windchill’s 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.

Topic Page
The Object Reference Design Pattern ...............................................................35-2
The Business Service Design Pattern................................................................35-3
The Master-iteration Design Pattern .................................................................35-7

35-1
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 object’s 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
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.

35-2 Windchill Customizer’s Guide


The Business Service Design Pattern
The most prevalent design pattern referenced to build Windchill services is the
business service design pattern (figures B-2, B-3, and B-4).

Business Service Interface

Business Service Classification

Windchill Design Patterns 35-3


Business Service Information

This pattern has the following major kinds of abstractions:


• Type
• Cookie
• Helper
• Service
• ServiceEvent
• ServiceException
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.
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 Cookie’s
cardinality is 0..1, the Cookie and all its nested attributes can be stored as null if
none of the Cookie’s 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.
The Helper abstraction provides a class representing the service’s 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. The static attribute is a remote reference to the service’s server-

35-4 Windchill Customizer’s Guide


side functionality by means of initializing the "service" attribute as shown in the
following example.

Initializing the Service Attribute

Notice the property in bold type named "InitialValue" and its value, "new
ServiceFwd()." This property setting directs the code generator to make an
initializer for the "service" instance to what is specified as the value. The service
name appended with "Fwd" is the name of the class generated for a class
stereotype as being a "RemoteInterface."
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
stereotyped as a "RemoteInterface." Otherwise, the service’s 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 service’s methods exists. This standard implementation is a
singleton executing on the server and is the default for all Windchill services.
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 35-5


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 service’s 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.

35-6 Windchill Customizer’s Guide


The Master-iteration Design Pattern
The design pattern that you must adhere to for all versioned data is the master-
iteration 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 service’s API. The business object must assert itself as being a kind of
mastered object in order for its instance to be iterated.
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

Windchill Design Patterns 35-7


superseded, rolled back, and rolled up through the version control service’s 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.

35-8 Windchill Customizer’s Guide


36
Developing Server Logic

This chapter describes how to develop server logic.

Topic Page
Overview ...........................................................................................................36-2
Service Management .........................................................................................36-2
Service Event Management...............................................................................36-4
Implementing Business Data Types ..................................................................36-8
Lightweight Services.......................................................................................36-18
Customizing service.properties .......................................................................36-24
Windchill Multi-object Operations .................................................................36-26

36-1
Overview
Developing server logic is primarily a task of designing and implementing
business data types and services. To develop these kinds of abstractions, you must
understand applicable Windchill design patterns, service and event management
in general, and guidelines used in detailed design and implementation.
A business data type can be characterized as an important piece of information
known in the business domain. This information consists of data and/or state once
it exists and is recognized in the system. A business service can be characterized
as a set of one or more functions that carry out business-specific processing. The
purpose of these kinds of abstractions is to separate the entity objects from control
objects. Once they are separated, developmental impacts and risks, typically
caused by evolving requirements and behavior, are reduced. That is, data and
behavior changes are less likely to directly affect each other given sound
abstraction and encapsulation.
In addition to the information presented here, see the Windchill Design Patterns
chapter on page 35-1. That chapter describes design patterns that represent
Windchill’s current best practices regarding development of server logic.
See the Windchill Services chapter on page 31-1 for a description of standard,
reusable Windchill services.

Service Management
The development of the standard, reusable Windchill services caused the need for
a general mechanism to manage the behavior of and interaction between these
services. This service management mechanism specifies a protocol for startup,
shutdown, and communication between Windchill services.

Automatic Service Startup


The wt.properties configuration file includes entries that specify which services
should be started automatically when the Windchill server is launched. In
addition, each entry specifies a pairing between the service interface and which
implementation of the service should be constructed. That is, if other
implementations are supplied in addition to the standard implementation of the
service, one of the other implementations can be declared to execute in these
entries. On the other hand, multiple service interfaces can also be implemented by
a single class. For example, the PersistenceManager and PersistenceManagerSvr
are both implemented by StandardPersistenceManager. The following is an
example of several entries for the standard Windchill services:
# Application Services
wt.services.service.10 = wt.session.SessionManager/
wt.session.StandardSessionManager
wt.services.service.20 = wt.fc.PersistenceManager/
wt.fc.StandardPersistenceManager
wt.services.service.30 = wt.fc.PersistenceManagerSvr/
wt.fc.StandardPersistenceManager

36-2 Windchill Customizer’s Guide


wt.services.service.40 = wt.queue.QueueService/
wt.queue.StandardQueueService

Numbering of Service Entries


The service number dictates the startup order of the service. Services are started
from lowest to highest number. If a service depends on other services, those
services must be started first.
There are no reserved ranges or values for Windchill services or customized
services. At each new release, any out-of-the-box Windchill service may be
renumbered, and any new number may be assigned. The maximum value for a
service number is 231-1 (=2147483647).
When defining customized services, you should choose a minimum service
number that is significantly higher than the highest number used by any Windchill
service. The numbers for the Windchill services can be determined by inspecting
the wt.services.service.#### entries in <Windchill>/codebase/wt.properties in
your installation. Each time you install a new release of Windchill, you need to
check the entries in wt.properties to ensure that all of your customized services
still have numbers higher than the highest Windchill service number.
For each customized service, you must ensure that its number does not duplicate
any number for an existing Windchill service or customized service.

Services and Managers


There are entries that are termed either a service or a manager. During the initial
stages of Windchill development, the use of the terms manager versus service was
unclear. It has been agreed that service represents the more general concept and
manager represents those services that are characterized more as managing groups
of objects. Currently the terms manager and service appear interchangeably.

Service Startup and Shutdown


In order for services to be managed, they must implement the
wt.services.Manager interface. This interface specifies methods for starting and
stopping services.
A reference implementation of wt.services.Manager, named
wt.services.StandardManager, provides most of the base functionality required for
service management. If a new type of service does not require any special startup
or shutdown processing, it can extend the base class wt.services.StandardManager
without overriding any of its methods.
Two methods in class wt.services.StandardManager are intended to be overridden
to specialize startup and shutdown processing. These methods are
performStartupProcess and performShutdownProcess. Examples of startup
processing include subscribing to service events and establishing queues for use in
background processing. For further information, see Service Event Subscription
later in this chapter (page 36-5).

Developing Server Logic 36-3


Service Management
ManagerService is a manager which is used to startup and provide access to a pre-
defined list of managers. This list includes different managers for services
mentioned in the Windchill Services chapter on page 31-1.
In addition to managing managers, the ManagerService provides a synchronous
event dispatch service. This service can dispatch a vetoable or non-vetoable event
to all listeners for the event key. Each listener may or may not object to the event.
The service performs a synchronous "in thread/transaction" notification of each
event listener for the event branch identified by the event key. It calls the
notifyEvent operation on each subscriber.

Service Event Management


One means of interservice communication is by direct peer-to-peer cooperation
and collaboration. No special mechanisms are required to support this kind of
communication because it is already defined as explicit invocations.
However, with a plug-and-play architecture, services become more independent
and unaware of other services. To facilitate interservice communication between
these autonomous services, general mechanisms are needed to convey information
between these services and to manage unordered synchronous communications.
Each service is responsible for specifying service events that can be emitted when
significant events that may be of interest to other services occur within the
service. Also, each service must establish listeners to other services’ events in
order to be notified of and react to other significant events occurring within the
system.

Service Event Registration


Services can register their events with the wt.services.StandardManager when
they are started. Registering service events at startup time makes the events
known to processes, such as access control. The following example illustrates
how events are registered in an overridden wt.services.StandardManager’s
registerEvents method for the version control service:
public void registerEvents( ManagerService manager ) {
manager.addEventBranch(
VersionServiceEvent.generateEventKey(
VersionServiceEvent.NEW_VERSION ),
VersionServiceEvent.class.getName(),
VersionServiceEvent.NEW_VERSION );
manager.addEventBranch(
VersionServiceEvent.generateEventKey(
VersionServiceEvent.PRE_SUPERSEDED ),
VersionServiceEvent.class.getName(),
VersionServiceEvent.PRE_SUPERSEDED );
manager.addEventBranch(
VersionServiceEvent.generateEventKey(
VersionServiceEvent.POST_SUPERSEDED ),

36-4 Windchill Customizer’s Guide


VersionServiceEvent.class.getName(),
VersionServiceEvent.POST_SUPERSEDED );
manager.addEventBranch(
VersionServiceEvent.generateEventKey(
VersionServiceEvent.PRE_ROLLBACK ),
VersionServiceEvent.class.getName(),
VersionServiceEvent.PRE_ROLLBACK );
manager.addEventBranch(
VersionServiceEvent.generateEventKey(
VersionServiceEvent. POST_ROLLBACK),
VersionServiceEvent.class.getName(),
VersionServiceEvent. POST_ROLLBACK);
manager.addEventBranch(
VersionServiceEvent.generateEventKey(
VersionServiceEvent. PRE_ROLLUP),
VersionServiceEvent.class.getName(),
VersionServiceEvent. PRE_ROLLUP);
manager.addEventBranch(
VersionServiceEvent.generateEventKey(
VersionServiceEvent. POST_ROLLUP),
VersionServiceEvent.class.getName(),
VersionServiceEvent. POST_ROLLUP);
}

Note: A more implicit means of registering events is by not doing so in the


registerEvents method, but by allowing the event to be registered when it is first
emitted. Once this occurs, all listeners subscribing to this event will be notified.

Service Event Subscription


In order for services to be notified of events occurring within the system, they
must subscribe to each particular service event of interest. To do this, you must
invoke the wt.services.ManagerService.addEventListener method with a listener
and key identifying the event of interest.
The listener specified during subscription must implement the
wt.events.KeyedEventListener interface. It defines the notifyEvent and
notifyVetoableEvent methods. The wt.services.ServiceEventListenerAdapter
class is provided as a utility whereby a listener can extend it and override only the
methods that are required for notification. The notifyEvent is a general method
that can be used in all subscription cases. The notifyVetoableEvent method is
more specialized; its intended use is to provide a means of vetoing an event via an
exception.
Typically event listeners are implemented using either anonymous or named
instances of inner classes. This allows the outer class to be designed without
implementing the wt.events.KeyedEventListener interface. This keeps the outer
class pure in that its type directly reflects its purpose without having to implement
a listener interface. The following is an example of how to override the
performStartupProcess method and define and add a listener for a specific event:

Developing Server Logic 36-5


protected void performStartupProcess()
throws ManagerException {

// At a request prior to a modification, if the target is a


// lockable object then
// validate if a modify on the object would be accepted. If
// not then veto it.

getManagerService().addEventListener(
new ServiceEventListenerAdapter(
this.getConceptualClassname() ) {
public void notifyVetoableEvent( Object event )
throws WTException

PersistenceManagerEvent pmEvent =
(PersistenceManagerEvent)event;
Persistable target = pmEvent.getTarget();

if (target instanceof Lockable)


validateLock( (Lockable)target);
}
},
PersistenceManagerEvent.generateEventKey(
PersistenceManagerEvent.PREPARE_FOR_MODIFICATION ));
}

protected void validateLock( Lockable object )


throws WTException, LockException {

if (object.getLock() != null) {

if (object.getLock().isSeized()) {

if (!object.getLock().getLocker().getObjectId().equals(
(Object) PersistenceHelper.getObjectIdentifier(
SessionHelper.manager.getPrincipal() )))

throw new LockException( RESOURCE, "5", null );


}
}
}

Service Event Notification


A list of all listeners subscribed to a particular event is maintained by the
ManagerService. This list is traversed in an unordered fashion and each listener is
executed one after the other using synchronous Java method invocations. Listener
notification methods execute in the same thread and database transaction as the
event emitter. This means that database operations performed by a listener in
response to a notification call are included in the transaction of the event emitter.
The following is an example that shows the dispatching of an event like
PersistenceManagerEvent.PREPARE_FOR_MODIFICATION:
protected void dispatchVetoableEvent( String eventType,
Persistable obj )
throws WTException {
PersistenceManagerEvent event =

36-6 Windchill Customizer’s Guide


new PersistenceManagerEvent( this, eventType, obj );
getManagerService().dispatchVetoableEvent( event,
event.getEventKey() );
}

Service Event Exception Handling


When a listener vetoes an event, it does so by throwing an exception. When an
exception is thrown, each listener that has already been notified of this event can
handle this exception by either passing the exception through, catching and re-
throwing it to clean up, or by implementing a "finally" clause to clean up.
As discussed earlier, event notification is dispatched within the same thread and
transaction frame as the event emitter. This means that an event emitter must roll
back any database updates that it has made if there has been a veto by another
listener. The following example illustrates this guideline. If the POST_STORE
event is vetoed, control is transferred to the "finally" clause, where the transaction
will be rolled back because the line that set the transaction to null was never
reached.
public Persistable store(Persistable obj) throws WTException {
checkStore(obj);
obj.checkAttributes();
dispatchVetoableEvent( PersistenceManagerEvent.PRE_STORE,
obj );
Transaction trx = new Transaction();

try {
trx.start();
insert(obj);
dispatchVetoableEvent( PersistenceManagerEvent.POST_STORE,
obj );
trx.commit();
trx = null;
}

finally {
if ( trx != null )
trx.rollback();
}

return obj;
}

Service Event Conventions


The meaning of any particular service event is up to the designer of the event.
Events should include all the information required by event listeners for follow-on
processing. The wt.events package includes a base event class,
wt.events.KeyedEvent, which can be extended to create new event types.
A common event design pattern includes pre- and post-events. Pre-events are used
to indicate to listeners that an event is about to begin. They are typically intended
to give listeners the opportunity to validate and possibly veto the event. Post-

Developing Server Logic 36-7


events are used to notify listeners that an event has finished. They are most useful
when a service needs to perform some kind of post-processing as a result of the
event. Not all events have to be either pre- or post-events. A singular definition of
an event can be used to indicate some special occurrence, which may or may not
have happened.

Implementing Business Data Types


A business data type can be characterized as an entity object (that is, a knower)
that deals basically with abstracting some crisp and clearly definable piece of
information in the problem domain. Therefore, business data types are primarily
defined by data, not behavior, as in control objects (that is, doers). Because most
of the specification of a business data type is by its attributes, implementation of
this business information typically focuses on the classes’ attributes.
In addition, because business data types are entity objects and are typically
lightweight compared to control objects, they efficiently transport information
between an application and the server in the three-tier (client, server, and
database) architecture.

Initializing Business Attributes


Initialization of business data type attributes is done by implicitly code generated
"initialize" methods. No constructors are generated for modeled business data
types. Instead, factories are created for each modeled constructor and, within the
factory, an instance is made. Then the initialize method with a signature that
matches the factory is invoked.
These initialize methods are empty at the first code generation and must be hand-
implemented because the code generator currently cannot make any assumptions
on what attributes should or should not be initialized. By default, once these
methods are implemented, their code is preserved for subsequent use. To mimic
Java constructor chaining, each initialize method should always invoke its parent
initialize method before doing anything else.

Business Attribute Accessors


Attributes are always generated as private fields with two accessors: a getter and
setter method, like JavaBean properties. The getter is generated as a no-arg
method that returns the value of the attribute.
The setter is generated as a single-arg method which sets the attribute to the value
of the arg. Depending on whether the attribute is constrained, the setter is
generated with or without a wt.util.WTPropertyVetoException throws clause.
This exception extends java.beans.PropertyVetoException and allows for a

36-8 Windchill Customizer’s Guide


customized message. The following example shows the property for constraining
an attribute, and a getter and setter for an attribute named "note".

Constraining an Attribute

public String getNote() {


//##begin getNote% [ ]348C64E401C5g.body preserve=no
return note;
//##end getNote% [ ]348C64E401C5g.body
}

protected void setNote( String a_Note )


throws WTPropertyVetoException {
//##begin setNote% [ ]348C64E401C5s.body preserve=no

noteValidate( a_Note ); // throws exception if not valid


note = a_Note;
//##end setNote% [ ]348C64E401C5s.body
}

Note that the body of the methods are flagged as "preserve=no." This instructs the
code generator to overwrite the code within a method. Getters and setters can be
preserved by setting this flag to "yes", but in general this is not recommended. On
the other hand, the code generator can be instructed to not generate a getter and
setter for an attribute with the "GenerateAccessors" property on the Windchill tab
set to "False."

Overriding Accessor Methods


Typically, overridden accessors do the following:

Developing Server Logic 36-9


• Attribute validation (as shown in the example)
• Lazy attribute initialization
• Computed attribute access
The following is an example of overriding accessor methods.
public void setStatus(int status)
throws PropertyVetoException {
// Set the status to the closed-code only if
// closure comments were provided.
if (status == CLOSE_CODE) {
if ((getClosureComments() == null) ||
(getClosureComments().equals("")) {
throw new PropertyVetoException();
}
}
super.setStatus(status);
}

Validating Business Attributes


Validating business data type attributes is handled at two distinct levels. The
simplest and completely code-generated level is implemented as a validation
method for a constrained attribute that is invoked by its setter. The mechanism
used to veto the setting of an attribute is a wt.util.WTPropertyVetoException
capable of being thrown from the setter. If an attribute is not constrained, the
setter is generated without the capability of an exception being thrown.
The properties for specifying limits on a String or numeric attribute are
LowerLimit and UpperLimit. In both cases, the value supplied is treated as a
literal or constant. This means that the validation method is code generated with
"if" statements that use Java less than or greater than operators to test against the
specified value in the LowerLimit or UpperLimit property, respectively. The

36-10 Windchill Customizer’s Guide


following examples illustrate the use of these two properties and the validation
code that is generated automatically:

Validation Example

private void noteValidate( String a_Note )


throws WTPropertyVetoException {

if ( a_Note != null &amp;&amp; a_Note.length() > MAX ) { // upper limit check


Object[] args = { "note", "MAX_LENGTH" };
throw new WTPropertyVetoException( "wt.fc.fcResource",
wt.fc.fcResource.UPPER_LIMIT, args,
new java.beans.PropertyChangeEvent( this, "note", note, a_Note ) );
}

if ( a_Note != null &amp;&amp; a_Note.length() < MIN ) { // lower limit check


Object[] args = { "note", "MIN_LENGTH" };
throw new WTPropertyVetoException( "wt.fc.fcResource",
wt.fc.fcResource.LOWER_LIMIT, args,
new java.beans.PropertyChangeEvent( this, "note", note, a_Note ) );
}
}

The other more general level of validating one or more attributes is to override
and implement the "checkAttributes" method inherited from wt.fc.WTObject.
This method is invoked before the object is stored in the database initially and
every time it is modified. In this case the exception thrown is
wt.fc.InvalidAttributeException, not wt.util.WTPropertyVetoException.

Developing Server Logic 36-11


Implementing the checkAttribute Method
The checkAttributes method shown in the following example is an alternative to
the setStatus method shown in the example in Overriding Accessor Methods
earlier in this section. It ensures that closure comments are provided if the status is
to be set to 2.
The checkAttributes method is called by the PersistenceManager to ensure the
state of the object is correct before storing it in the database.
The following is an example of implementing the checkAttribute method.
// Example checkAttributes method
public void checkAttributes() throws
InvalidAttributeException {

// Ensure that closure comments are provided if the


// status is set to the closed-code.
if (getStatus() == CLOSE_CODE) {
if ((getClosureComments() == null) ||
(getClosureComments().equals("")) {
throw new InvalidAttributeException ();
}
}
}

Business Attribute Aggregation


Structured attributes (that is, non-first-class) at all levels of associations are placed
in the same database table as the first-class object that stores the structure
attributes. The aggregated attributes must be object mappable and, regardless of
cardinality, will always exist in the database table as a flat structure. The flatness
of the tables is due to the fact that the database tier in the three-tier architecture is
assumed to be a relational database, not an object-oriented database.
However, if the top-level structured attribute’s cardinality is 0..1 or 0..* and it is
not flagged as being required, it can be nullified in the database. Care must be
taken if this top-level structured attribute aggregates any other structured attribute
because the nested structured attributes will not be nullified.

36-12 Windchill Customizer’s Guide


Business Attribute Persistence
A business attribute is persisted as a column in a first-class object’s database table
if it is flagged as being "Persistent" as shown in

Persistent Attribute

Otherwise, it is treated as an in-memory attribute only and is not mapped to a


column in the database table.

Business Attribute Derivation


Derived attributes are strictly generated as getters and setters without any such
named field for the modeled derived attribute. Typically, the purpose of modeling
a derived attribute is to make it act as a computed value when accessed. One side
effect of derived attributes is they are neither serializable nor externalizable. They
could be an implementation detail in the body of a class, but Windchill’s
generated externalization methods will not recognize the attribute as existing.
That is, the externalization methods to read and write an object’s data are
generated based on what is known in the object model, not the implementation.
If an object with a derived attribute is either being transmitted across-the-wire, or
is being stored/retrieved externally, the derived attribute within it is non-existent.
Any assumption made in implementation where a derived attribute is required for
processing after the object has been serialized or externalized may produce
erroneous results unless the accessor is called to re-derive the attribute.

Developing Server Logic 36-13


Implementing Business Services
A business service can be characterized as a set of abstractions — based on the
business service design pattern — that collectively provide essential behavior and
processing for a problem domain. For further information on the business service
design pattern, see the Windchill Design Patterns chapter on page 35-1. The main
kinds of classes in a business service act as control objects (that is, doers) that
carry out processing on business objects. Additionally, cookies are maintained by
the business service that hold state and key information on a per object basis.
Cookie classes are aggregated to interfaces that are managed by business services.
For example, PersistInfo is a cookie class that is aggregated to the Persistable
interface. Any class that implements Persistable will also aggregate PersistInfo,
and the PersistenceManager business service will manage the attributes of
PersistInfo such as createStamp and modifyStamp.

Initializing Business Services


Business services are designed to execute as singletons in the server only. When
the server is launched, the wt.properties file is read to determine what services are
to be started automatically. These specified services are constructed and statically
initialized, service events are registered, and the services are then started. The
ordering specified by wt.services.service entries in the wt.properties file controls
the order in which services are started.
If administrative access is required on service startup, it is necessary to create a
new SessionContext and set the current user to the Administrator. It is equally
important to reset the session context at the end of a service’s startup processing.
To guarantee that a session context is always reset, it should be done in a "finally"
clause.
protected void performStartupProcess()
throws ManagerException {

SessionContext previous = SessionContext.newContext();


// create new SessionContext
try {
// do startup processing such as registering
// event listeners

try {
SessionHelper.manager.setAdministrator(); //
}
catch (UserNotFoundException wex) {
System.err.println ("Administrator user
doesn’t exist (OK if installation)");
return;
}

// do startup processing that requires


// administrative permissions such as
// creating a queue
}
catch (WTException wex) {

36-14 Windchill Customizer’s Guide


throw new ManagerException (this,
"Failed to initialize service.");
}

finally {
SessionContext.setContext(previous);
// restore initial SessionContext
}
}

Business Service Operations


Business service operations can be invoked either locally or remotely. Only
remote invocations are made by a client. Local invocations can be either from a
client or server.
The business service’s Helper abstraction contains only methods that can be
invoked locally. These methods are generally used for the accessing of the
service’s cookie information. Other types of methods that aid in processing may
also be implemented in a Helper. The Service abstraction contains methods that
can be invoked locally on the server and invoked remotely from the client if the
Service is stereotyped as being a "RemoteInterface." With this stereotyping and
aggregation of the "service" in the helper, all public methods are available for use.
The business service should ensure that all externally available operations are
exposed either through the Helper or Service class. All other operations should
only be available internally with the possible exception of methods on utility
classes that are used by other services.
Often business service operations executing on the server must perform database
actions. To maintain database integrity, service independence, and loose coupling
between other services, database changes should be protected by the use of
transaction blocks. The following section of sample code serves as a guideline on
how to implement transaction blocks:
public Persistable store( Persistable obj )
throws WTException {
//##begin store% [ ]3458AD98008C.body preserve=yes

Transaction trx = new Transaction();

try {
trx.start();
dispatchVetoableEvent( PersistenceManagerEvent.PRE_STORE,
obj );
checkStore(obj);
obj.checkAttributes();
insert(obj);
dispatchVetoableEvent( PersistenceManagerEvent.POST_STORE,
obj );
trx.commit();
trx = null;
}
finally {

Developing Server Logic 36-15


if (trx != null)
trx.rollback();
}

return obj;
//##end store% [ ]3458AD98008C.body
}

Vetoing Business Service Events


When a business service is notified of an event occurring within the system, it has
the option of vetoing the event. This is done by subscribing as a listener and
implementing the notifyVetoableEvent method. The listener must process the
event’s data and determine if a veto is applicable. If so, the listener throws an
appropriate exception. Otherwise, the listener does whatever processing is
required and allows the event to continue.

Business Service Rules


If applicable, a business service should implement rules to enforce consistent and
correct functionality of its operations. The two basic forms of business rules are
access control and problem domain integrity.
Access control establishes who can act upon what and in what manner. The
enforcement of access control in a business service is explicitly implemented. In
the locking service, for example, when an object is requested to be locked, the
service guarantees that the principal attempting to place the lock has modify
access to the object such that the lock for it can be persisted in the database as
shown below:
public Lockable lock( Lockable object, WTPrincipalReference locker,
String note )
throws WTException, LockException, WTPropertyVetoException,
PersistenceException {
//##begin lock% [ ]342A8DDB0271.body preserve=yes
Transaction trx = new Transaction();

// Check if the object is not currently locked and the locker


// has modify
// access rights then dispatch a vetoable event to signal
// listeners that
// a lock is about to commense. If no listener vetos the lock
// (i.e., no
// exception was thrown) then go ahead and set the object’s
// lock state
// (i.e., cookie).

if (!object.getLock().isSeized()) {

if (AccessControlHelper.manager.hasAccess( locker.getPrincipal(),
object, WTPermission.MODIFY )) {
dispatchVetoableEvent( LockServiceEvent.PRE_LOCK, object );
object.getLock().seize( locker, note );

36-16 Windchill Customizer’s Guide


// Now update the object without changing the objects
// modify date.
// The modify date is left as is since all that is
// being updated
// is the cookie information, not the object.

try {
trx.start();
PersistenceServerHelper.manager.update( (Persistable)
object, LEAVE_MODIFY_DATE );
trx.commit();
trx = null;
}
finally {

if (trx != null)
trx.rollback();

dispatchVetoableEvent( LockServiceEvent.POST_LOCK, object );


}
}

return object;
//##end lock% [ ]342A8DDB0271.body
}

Enforcement of problem domain integrity is somewhat different than access


control. Maintaining correct problem domain behavior within the business service
should always be a goal, but in particular there may be some special requirements
that must be satisfied. As in version control, for example, when an object is
checked in, it is then once again available to be checked out. However, if the
object is already checked out, it can not be checked out again unless some sharing
and merging rules are in place.

Business Service Communication


Business services can communicate with one another either directly through
synchronous Java invocations or by events. Direct peer-to-peer communication to
another service is how access control is implemented in all of Windchill’s
services. This is the most rudimentary means of communication.
Event-based communication is a more sophisticated means of communicating
between services. Services can register their events and subscribe listeners to
another service’s events when they are started. When a service event is emitted,
all subscribed listeners are notified of the occurrence of the event. The event
notification and responses are synchronous. Therefore, it is equivalent to method
invocations to the services, except that services which cause events do not know
which other services will be notified. If one of the notified services vetoes the
event, the other services not yet notified are not informed.

Developing Server Logic 36-17


Lightweight Services
Lightweight services reside in the application layer between the client and the
business service layer. Lightweight services are light because they do not start
automatically and dispatch events. Consequently, lightweight services are not
specified in the wt.properties file with wt.services entries.
Lightweight service methods should be designed to do the following:
• Reduce the number of round trips between the client and the server.
• Provide task-specific and higher-level functionality than business service
methods.
• Ensure client transactional integrity.
Lightweight services can dispatch events but should not listen for them. If a
service is not started automatically, it will not be able to hear events that it is
supposed to listen for until it is started.
Lightweight services are an effective means to ensure client transactional
integrity. Several client-server operations can be grouped into a single,
lightweight service method call that will carry out these operations on the server
in a single transaction.
Lightweight services can be implemented in the following two ways:
• Through a modeled class that extends wt.services.StandardManager
• Through a non-modeled, inner class that implements
wt.method.RemoteAccess
The following subsections describe both implementations.

The Modeling Implementation


Lightweight services are modeled like business services in that they are defined
by a remote interface and have an implementation class that extends
StandardManager. The remote interface enables the service to run in the method
server and be invoked by remote clients (for example, applets). The mapping
between the service interface and implementation class is accomplished with a
naming convention. The implementation class for a lightweight service must have
the same name as the interface with "Standard" at the beginning of the name.
To use a lightweight service, create an instance of the generated Forwarder class
and call the service’s methods through the Forwarder. This is similar to a business
service where a static attribute on the Helper class is initialized with an instance of
the Forwarder class. In both cases, the mechanism for invoking service operations
is identical.

36-18 Windchill Customizer’s Guide


The following is an example of a lightweight service named CommentLogger.
This model can be found in WTDesigner.mdl in the wt.services.test package.

CommentLogger Service Example

In this example, the CommentLogger interface defines a lightweight service that


will log a message to the server log file. This service could be useful for applet
clients that want to include a message in the server log. Without such a service, all
System.out.println calls will send their output to the browser’s Java console
window instead of the server log file. StandardCommentLogger implements this
service by extending wt.services.StandardManager and the CommentLogger
interface. Note that the name must be StandardCommentLogger in order for the
ManagerService to find the implementation class for the CommentLogger service.
Since CommentLogger has a stereotype of RemoteInterface, a Forwarder class
named CommentLoggerFwd is automatically generated. It is this class that is used
to invoke the CommentLogger service methods:
CommentLoggerFwd logger = new CommentLoggerFwd();

logger.log("a message");

The Inner Class Implementation


The second way of implementing a lightweight service is through a non-modeled,
inner class that implements wt.method.RemoteAccess. An example of an inner
class implementation follows. The objectives are to invoke a complex server-side
activity, collecting information of interest to the client, while minimizing the
number of classes loaded by the client. These techniques improve performance for
the client because loading classes can be slow and expensive.
In this example, note the type of the inner class. To avoid IllegalAccess violations,
the forwarder must be declared as a "public static class". Using this declaration,
the MethodServer is able to instantiate and invoke methods on the inner class.
Note also the technique for invocation of the desired server method. To avoid
loading classes specified as part of the action to be carried out in the
MethodServer, we specify the target inner class and method of interest as Strings.
Any reference to the class itself will cause it and all the classes it needs to be
loaded into the client VM, which is not desirable.
package wt.appfwd;

Developing Server Logic 36-19


import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;
import java.io.Serializable;
import java.util.Vector;

import wt.util.WTContext;
import wt.method.RemoteMethodServer;
import wt.method.RemoteAccess;

import wt.fc.QueryResult;
import wt.fc.PersistenceHelper;
import wt.fc.PersistenceManager;
import wt.part.WTPart;
import wt.part.WTPartMaster;
import wt.query.QuerySpec;
import wt.query.SearchCondition;

public class AppLightFwd extends Applet {

// Class name of our inner class that runs in the server


private static final String SERVER_CLASS =
AppLightFwd.class.getName() + "$Server";

private Button action;


private RunnerEventListener rel;
private Label partNames;
private TextField text;
private Label queryCount;
private TextField countVal;
private TextArea feedback;

public void init() {

WTContext.init(this);
action = new Button ("Get Parts");
this.add(action);
rel = new RunnerEventListener();
action.addActionListener(rel);
partNames = new Label( " with names like ... " );
this.add(partNames);
text = new TextField("", 25);
this.add(text);
queryCount = new Label( "Number of parts to return" );
this.add(queryCount);
countVal = new TextField( "5", 4);
this.add(countVal);
feedback = new TextArea("",10, 40);
this.add(feedback);

public void start() {


WTContext.getContext(this).start(this);
super.start();
}

36-20 Windchill Customizer’s Guide


public void stop() {
WTContext.getContext(this).stop(this);
super.stop();
}

public void destroy() {


WTContext.getContext(this).destroy(this);
super.destroy();
}

// Applet event listener


class RunnerEventListener implements ActionListener {

public void actionPerformed (ActionEvent event) {


Object o = event.getSource();
if (o == action) {
String name = text.getText();
String count = countVal.getText();
if (!name.equals(""))
doSomeWork(name,count);
else
text.setText("must enter a part name search key" );
}
}
}

// Food for thought:


// here we should disable appropriate GUI components and
// spin off a separate thread to do the actual work so
// we don’t hang the AWT-Thread ( the GUI thread )

public void doSomeWork(String name, String count) {


Vector results = null;
String like = "% [ ]"+name.toUpperCase()+"% [ ]";

feedback.setText("");
try
{
Integer cnt = null;
try {
cnt = new Integer(count);
}
catch (Exception e) {
// some parse exception, just get default count
try {
cnt = new Integer(5); // this will work
} catch (Exception e2){}
}

// construct arguments for call


Class [] argTypes = { String.class, Integer.TYPE };
Object [] args = { like, cnt };

// Run to server and do some work there.


// Build Server inner class name as a string so we don’t
// load the class here.
results = (Vector) RemoteMethodServer.getDefault().invoke(
"doSomeWork", SERVER_CLASS, null, argTypes, args);

Developing Server Logic 36-21


// display results in text area
for (int i=0;i results.size(); i++) {
PartMasterInfo pmi
= (PartMasterInfo)results.elementAt(i);
feedback.append("> "+pmi.getName()+"
# "+pmi.getNumber()+’\n’);
}
}
catch (RemoteException e)
{
//
// Put localized Exceptions
// into a Dialog popup
//
feedback.append(e.toString());
}
catch (InvocationTargetException e)
{
// Localize in a dialog
feedback.append(e.toString());
}
}

// "Public" static inner class.


// Yes 2 public classes in the same file, this is the
// only exception

public static class Server implements RemoteAccess {

public static Vector doSomeWork (String name, int count)


{
int i=0;
Vector parts = new Vector(count);
WTPartMaster wtpm;

try {
//
// Use feedback mechanism to send progress updates
// to the user
// and of course be sure to Localize it
//
QuerySpec queryspec = new QuerySpec(WTPartMaster.class);
queryspec.appendSearchCondition(
new SearchCondition(WTPartMaster.class,
WTPartMaster.NAME,
SearchCondition.LIKE,
name) );
QueryResult queryresult =
PersistenceHelper.manager.find(queryspec);
// create a vector of PartMasterInfo object to return
// to the client
while (queryresult.hasMoreElements()) {
wtpm = (WTPartMaster)queryresult.nextElement();
parts.addElement(new PartMasterInfo(wtpm.getName(),
wtpm.getNumber()));
if (++i >= count)
break;
}

36-22 Windchill Customizer’s Guide


}
catch (Exception e) {
// Localize
parts.addElement(new PartMasterInfo(e.toString(),"-1"));
e.printStackTrace();
}
return parts;
}
}

// simple support (inner) class which contains


// the information we are interested in returning to the
// client for display purposes

public static class PartMasterInfo implements Serializable {


String name;
String partNumber;

public PartMasterInfo( String name, String number ) {


this.name = name;
partNumber = number;
}

public String getName() { return name; }


public String getNumber() { return partNumber; }
}
}

Developing Server Logic 36-23


Customizing service.properties
The service delegate mechanism uses Java property files to specify the delegates
that are used for each service for a given set of criteria. The main property file is
named service.properties and is located in /Windchill/codebase/. For further
information, see the section on property files in the The Windchill Development
Environment chapter on page 2-1)
Instead of adding new entries to the service.properties file, or overriding existing
entries in it, use a separate file. This file must have entries with the same format as
those in service.properties. To use the new property file, add the file’s full path
(relative to the system classpath) to a comma-separated list of files in the
following property located in wt.properties:
wt.services.applicationcontext.WTServiceProviderFromProperties.
customPropertyFiles

Consider the example of creating a new wt.identity.DisplayIdentification


delegate. The DisplayIdentification service is an interface that defines methods
for creating strings that identify an object for user interface display purposes. In
service.properties, several entries exist for the DisplayIdentification service, as
follows:1
# The wt.identity.DisplayIdentification service.
#
# Delegate definitions for all objects
#################################################
wt.services/svc/default/wt.identity.DisplayIdentification/null/
java.lang.Object/0=
wt.identity.DisplayIdentificationObjectDelegate/
duplicate
wt.services/svc/default/wt.identity.DisplayIdentification/null/
wt.fc.Persistable/1=
wt.identity.DisplayIdentificationPersistableDelegate/
duplicate
wt.services/svc/default/wt.identity.DisplayIdentification/null/
wt.folder.Folder/2=
wt.folder.DisplayIdentificationFolderDelegate/
duplicate
wt.services/svc/default/wt.identity.DisplayIdentification/null/
wt.folder.Shortcut/2=
wt.folder.DisplayIdentificationShortcutDelegate/
duplicate
wt.services/svc/default/wt.identity.DisplayIdentification/null/
wt.doc.WTDocumentMaster/2=
wt.identity.DisplayIdentificationWTDocumentMasterDelegate/
duplicate
wt.services/svc/default/wt.identity.DisplayIdentification/null/
wt.enterprise.RevisionControlled/2=
wt.identity.DisplayIdentificationRevisionControlledDelegate/

1. Indentation in this example indicates a continuation of the preceding line, necessary for
presentation in the manual. The entry for each property in a property file can be on only one
line.

36-24 Windchill Customizer’s Guide


duplicate
wt.services/svc/default/wt.identity.DisplayIdentification/null/
wt.part.WTPartMaster/2=
wt.identity.DisplayIdentificationWTPartMasterDelegate/
duplicate
wt.services/svc/default/wt.identity.DisplayIdentification/null/
wt.part.WTPart/3=
wt.identity.DisplayIdentificationWTPartDelegate/
duplicate
Each entry maps a class or interface, such as wt.part.WTPart, to a class that
implements the interface wt.identity.DisplayIdentification, such as
wt.identity.DisplayIdentificationWTPartDelegate. If a customization includes a
subclass of WTPart named AcmePart, and that part has different display
identification needs than WTPart, a new delegate must be implemented. After the
delegate class is implemented, it is used only when the correct entry has been
added to a service delegate property file. To do so, perform the following steps:
1. Create a new property file named acme_part_services.properties to contain all
entries for service delegates that apply to the AcmePart class.
2. Put this property file in a directory where it will not be deleted if your
Windchill installation is reinstalled or upgraded, for example:
<Windchill>/src/com/acme/part. Place a copy in
<Windchill>/codebase/com/acme/part.
3. Add the name of the new property file to the list of files specified in the
wt.properties file property named
wt.services.applicationcontext.WTServiceProviderFrom
Properties.customPropertyFiles, using the following procedure:
– Create a new declarative xconf file, for example,
<Windchill>/src/com/acme/part/acme_part_services.xconf that looks like
the following:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configuration SYSTEM "xconf.dtd">
<Configuration targetFile="codebase/wt.properties">
<!-- Ensure that the file com/acme/part/acme_part_services.properties is
appended to the list of custom property files.
-->
<Property default="com/acme/part/acme_part_service.properties"
name="wt.services.applicationcontext.WTServiceProviderFromProperties.customProperty
Files"/>
</Configuration>

– Modify the customPropertyFiles property in


<Windchill>/codebase/wt.properties and generate the
acme_part_services.properties file by executing the new xconf file from a
windchill shell as follows:
xconfmanager -i
src/com/acme/part/acme_part_services.xconf -p

4. Restart the method server in order for the change to take effect.

Developing Server Logic 36-25


Windchill Multi-object Operations
Windchill's multi-object API infrastructure support makes it possible to perform
an operation against a collection of objects without resorting to looping
somewhere in the process to persist the changes, call other APIs, or dispatch
events. This reduces the number of trips to the database and the number of
method calls: an operation to persist 100 objects can call the database once (using
a batch operation) and dispatch, again once, the events pertinent to the operation.
Similarly, the event listeners can operate against the entire collection, replacing
duplicative persistence (CRUD2) operations with multi-object operations that hit
the database as little as one time (as opposed to n times). The multi-object API
should significantly outperform the looping equivalent even when the collection
has only one element, as event listeners to copy associations, etc., can benefit
from the multi-object APIs.
Windchill's support for multi-object APIs consists of:
• Windchill-specific collections
• Multi-object event dispatch and notification
• Multi-object delegation
• Multi-object exceptions
• Multi-object "CRUD" persistence manager APIs
• Batch ("UPDATE WHERE" and "DELETE FROM") statement capabilities
• Transaction context and listeners
• Referential integrity association validation during object delete
Windchill-specific collections utilize the Java Collections framework to provide
sets, lists, and maps optimized for Windchill persistent objects. These collections
seamlessly handle Persistables represented as QueryKeys, WTReferences, and
fully-inflated Persistables. The collections also provide numerous APIs for doing
things such as refreshing and inflating, getting sub-collections based on class, and
testing membership. See the wt.fc.collections package in the Javadoc for more
information.
Multi-object event dispatch and notification allows any event (such as
PRE_STORE) to be dispatched and notified as either single- or multi-object. The
event mechanism automatically handles the case where the dispatcher and notifier
(that is, the listener) are inconsistent by converting the multi-object event into
single-object events and looping over the listener and, vice-versa, by converting
the single-object event into a multi-object event and notifying the multi-object
listener. Multi-object events will have collections-based event targets.

2. "CRUD" refers to Create (store/insert), Read (find/query/navigate/expand),


Update (modify/update), and Delete (delete/remove) operations.

36-26 Windchill Customizer’s Guide


Multi-object delegation makes it possible to request the delegates for a collection
of objects. The multi-object delegate APIs will then map the appropriate
delegates to sub-collections of the collection that would use them. It is then
possible to execute multi-object APIs on the delegate, passing these sub-
collections to the delegate's multi-object APIs. For example, when requesting the
"x.y.Z" delegate for a collection of parts and documents, the result may be that
delegate1 matches the parts and delegate2 the documents; delegate1's multi-object
API can then be called, passing the parts sub-collection. See the Javadoc entry for
wt.services.ac.DefaultServices for more information.
Multi-object exceptions are thrown by multi-object APIs and listeners. These
exceptions provide extended information about the nature of the problem(s)
associated with some of the objects in the passed-in collection. For example, if a
change identity against ten objects failed because three of the objects were
assigned non-unique identities, the resultant exception will indicate the three
individual failures. This is made possible by the addition of "additionalMessages"
to wt.util.WTException.
Multi-object CRUD persistence manager APIs interact with the database using
batch operations, reducing the total number of database interactions for a CRUD
operation to as little as one (more practically, as little as one per table). A "store"
operation passing a collection of 100 parts can employ a single bulk insert to the
database, rather than 100 individual insert operations. See the wt.fc Javadoc entry
for more information.
Batch ("UPDATE WHERE" and "DELETE FROM") statement capabilities
produce Windchill statements that, in the database, are translated as UPDATE
WHERE and DELETE FROM statements. This makes it possible, for example,
to delete all of the associations for a collection of objects in one database hit
without even requiring the links to be pre-queried (in practice, these operations
are still subject to events, so the OIDs may be returned and, if the listeners require
full persistables, inflated). See wt.fc.batch for more information.
Transaction context and listeners provide fine-grained mechanisms for adding
information to the nested and global transactions (in a manner similar to the
MethodContext) and for being notified when a transaction is about to commit, has
committed, or rolls back. See the Javadoc entries for Transaction,
TransactionListener, and TransactionCommitListener in the wt.pom package.
Referential integrity association validation during object delete employs a
declarative mechanism to specify how associations should behave during
deletion. Each role can indicate that, when the role object is being deleted, the
association should be deleted or the deletion vetoed.

Developing Server Logic 36-27


36-28 Windchill Customizer’s Guide
37
The Enterprise Layer

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.

Topic Page
Enterprise Abstractions .....................................................................................37-2
Document Abstractions ...................................................................................37-10
Part Abstractions .............................................................................................37-13
Change Abstractions........................................................................................37-21

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

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

37-2 Windchill Customizer’s Guide


folders, they tend to be more administrative in nature (that is, created by
administrators but referenced by end users).

Simple Business Class

The Enterprise Layer 37-3


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

37-4 Windchill Customizer’s 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

The Enterprise Layer 37-5


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

37-6 Windchill Customizer’s Guide


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.

The Enterprise Layer 37-7


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
cycle-managed, as is the case with RevisionControlled objects.

Iterated Folder Resident Business Class

37-8 Windchill Customizer’s Guide


Cabinet Managed Business Cclass
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

The Enterprise Layer 37-9


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. A more complete diagram can also be viewed using
Rose.

Doc Package

37-10 Windchill Customizer’s Guide


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

The Enterprise Layer 37-11


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.
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, see the section on Extending the
EnumeratedType class in the System Generation chapter on page 32-36 and the
Enumerated Types chapter on page 34-1.

37-12 Windchill Customizer’s Guide


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.

The Enterprise Layer 37-13


Attributes are on either WTPartMaster or WTPart. The WTPartMaster, as a
Mastered object, represents the part’s identity. As such, "number" and "name"
have been placed on it. The part’s 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 WTPart also contains as aggregated properties a source and a type (as shown
in the following figure).

WTPart Properties

37-14 Windchill Customizer’s Guide


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

The WTPartUsageLink is a type of IteratedUsageLink, an association defined to


be used to build structures. The WTPartUsageLink’s aggregated Quantity can be
used to indicate the amount of the component that is being consumed. The
QuantityUnit’s values can be altered by editing its resource bundle.
The WTPartUsageLink can be navigated using the PersistenceManager’s navigate
APIs, or even the StructService’s navigateUses and navigateUsedBy APIs. Be
aware that navigating the usedBy role results in the returning of all part iterations;
StructService’s navigateUsedBy API returns only versions. However, the
StructService’s APIs navigate using the IteratedUsageLink as its target; the

The Enterprise Layer 37-15


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

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 document’s
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 WTPartService’s
getReferencesWTDocumentMasters API.

37-16 Windchill Customizer’s Guide


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

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 WTPartService’s APIs listed in the following figure.

Finding and Saving the WTPartConfigSpec

The ConfigSpecs aggregated by the WTPartConfigSpec have the following


behavior:

The Enterprise Layer 37-17


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

37-18 Windchill Customizer’s Guide


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

The Enterprise Layer 37-19


The Part, PartMaster, and PartIteration classes modeled in the wt.part package
(see the following figure) are placeholders for future functionality.

Placeholders

37-20 Windchill Customizer’s Guide


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

The Enterprise Layer 37-21


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.

37-22 Windchill Customizer’s Guide


Change Item Classes
The following figure shows the model for the change classes provided by
Windchill’s change management module.

<<Abstract>>
ChangeIssue

0..n
FormalizedBy
0..1
<<Abstract>> 1 0..n <<Abstract>> 1 0.. n <<Abstrac t>>
ChangeRequest2 ChangeOrder2 ChangeActivity2
Address edBy2 IncludedIn2
1 0..1
ResearchedBy
0..n
<<Abstract>> AcceptedStrategy
ChangeAnalysis

1
<<Abstract>> <<Abstract>>
ChangeInvestigation ChangeProposal 0..1

DetailedBy
For the Windchill out of 0..n For the Windchill out of
the box change process, the box change process
there can be only one <<Abstract>> the UI does not expose
ChangeInvestigation per AnalysisActivity this relationship
ChangeRequest.

Change Management Class Model

The Enterprise Layer 37-23


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 problem’s 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.
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.

37-24 Windchill Customizer’s Guide


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.

The Enterprise Layer 37-25


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.

<<Interface>>
Changeable2

Product Master that is the_subject


of_ the change request

W TProductInstance2 <<Abstract>>
(from part) RevisionCont rolled
(from enterprise)

WTPart WTDocument EPMDocument


(from part) (from doc) (from epm)

WTProduct
(from part)

Changeable Objects

37-26 Windchill Customizer’s Guide


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.

Subject
Product

Product
Master

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

The Enterprise Layer 37-27


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:

This relationship identifies Changeable2 This relationship identifies Changeable2


revisions which were relevant for a given revisions which must be changed to
Analysis Activity. satisfy a Change Activity.

<<Abstract>>
Object ToObjectLink
(from fc)

RelevantAnalysisData AffectedActivityData

<<Abstract>>
AnalysisActivity 0..n 0..n 0.. n 0..n
<<Interface>> <<Abstract>>
0..n 0..n Changeable2 0..n 0..n ChangeActivity2
WTProductMaster <<Abstract>>
(from part) ChangeRequest2
0.. n 0..n

RelevantRequestData2 ChangeRecord2

SubjectProduct
This relationship identifies Changeable2
This relationship identifies
revisions which were created to satisfy a
Changeable2 revsions
Change Activity. These revisions are
which were relevant for a
either entirely new, or new revisions of
given Change Request.
existing objects.

<<Abstract>>
Object ToObjec tLink
(f ro m f c)

Associations Class Diagram

37-28 Windchill Customizer’s Guide


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 (see the content package in the
Windchill Services chapter on page 31-1), 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.

The Enterprise Layer 37-29


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

Change issue
The following figure shows the model for change issues:

<<Abstract>> <<Interface>> <<Interface>> <<Interface>> <<Interface>>


Managed ChangeIssueIfc ContentHolder ChangeItem ElectronicallySignable
(from electronicIdentity)
(from enterprise) (f ro m co ntent )

<<Abstract>>
ChangeIss ue
<<Abstract>>
Identificat ionObjec t
(from fc)

WTChangeIssue
<<Int erface>>
Identified number : String WTChangeIs sueIdentity
(from fc) name : String
number : String
description : String
name : String
requester : String
<<Interface>>
Typed WTChangeIssueIdentity()
WTChangeIssue()
(from type) assignToObject()
WTChangeIssue()
setToObject()
checkAttributes()
getIdentity()

0..1
IssuePriority
HIGH : IssuePriority = toIssuePriority ("HIGH")
ME DIUM : IssuePriority = t oIssuePriorit y(" MEDIUM" )
LOW : IssuePriority = t oIss uePriorit y(" LOW ")
EMERGENCY : IssuePriority = t oIssuePriorit y(" EMERGENCY" )

0..1
Category
SAFETY_ISSUE : Category = toCategory("SAFETY_ISSUE")
COST_REDUCTION : Category = toCategory("COST_REDUCTION")
DESIGN_ISSUE : Category = toCategory("DESIGN_ISSUE")
QUALITY_IMPROVEMENT : Category = toCategory("QUALITY_IMPROVEMENT")
OTHER : Category = toCategory("OTHER")

Change Issue Model

37-30 Windchill Customizer’s Guide


Change Request
The following figure shows the model for change requests:

<<Abstract>> <<Interface>> <<Interface>> <<Interface>> <<Interface>>


Managed ChangeRequestIfc ContentHolder ChangeItem ElectronicallySignable
(f rom e nte rp rise ) (from content) (f ro m el ectroni cI den ti ty)

<<Interface>>
<<Interface>> <<Abstract>>
Typed
Identified ChangeRequest2
(from type)
(from fc)

Category
SAFETY_ISSUE : Category = toCategory("SAFETY_ISSUE")
COST_REDUCTION : Category = toCategory("COST_REDUCTION")
DESIGN_ISSUE : Category = toCategory("DESIGN_ISSUE")
QUALITY_IMPROVEMENT : Category = toCategory("QUALITY_IMPROVEMENT")
WTChangeRequest2 0..1
OTHER : Category = toCategory("OTHER")
number : String
name : String
description : S tring RequestPriority
needDate : Timestamp HIGH : RequestPriority = toRequestPriority("HIGH")
MEDIUM : RequestPriority = toRequestPriority("MEDIUM")
WTChangeRequest2() 0..1 LOW : RequestPriority = toRequestPriority("LOW")
WTChangeRequest2() EMERGENCY : RequestPriority = toRequestPriority("EMERGENCY")
checkA ttributes()
Complexity
SIMPLE : Complexity = toComplexity("SIMPLE")
0..1 COMPLEX : Complexity = toComplexity("COMPLEX")

<<Abstract>>
IdentificationObject
(from fc)

WTChangeRequest2Identity
number : String
name : String

WTChangeRequest2Identity()
assignToObject()
setToObject()
getIdent ity()

Change Request Model

The Enterprise Layer 37-31


Change Investigation
The following figure shows the model for change investigations:

<<Interface>> <<Abstract>> <<Interface>> <<Interface>> <<Interface>>


ChangeAnalysisIfc Cabinet Managed Content Holder ChangeItem ElectronicallySignable
(from enterprise) (from content) (from electron icIdentity)

<<Interface>> <<Abs tract>>


ChangeInvestigationIfc ChangeAnalysis

<<Abstract>> <<Abstract>>
ChangeInvestigation Ident ificat ionObject
(from fc)
<<Interface>>
Ident ified
(from fc)
WTChangeInvestigation
WTChangeInvestigationIdentity
number : String
number : String
name : String
name : String
description : String
<<Interface>> needDate : Timestamp
Typed WTChangeInvestigationIdentity()
results : String
(from type) assignToObject()
setToObject()
WTChangeInvestigation()
getIdentity()
WTChangeInvestigation()
checkAttributes()

Change Investigation Model

37-32 Windchill Customizer’s Guide


Change Proposal
The following figure shows the model for change proposals:

<<Interface>> <<Abstract>> <<Interface>> <<Interface>> <<Interface>>


ChangeAnalysisIfc CabinetManaged ContentHolder ChangeItem ElectronicallySignable
(f rom en terprise) (f rom c ontent) (f rom el ectroni cI denti ty)

<<Interface>> <<Abstract>>
ChangeProposalIfc ChangeAnalysis

<<Int erface>> <<Abstract>> <<Abstract>>


Ident ified ChangeProposal IdentificationObject
(from fc) (from fc)

WTChangeProposal WTChangeProposalIdentity

<<Interface>> number : String number : String


Ty ped name : String name : String
(from type) description : String
WTChangeProposalIdentity()
WTChangeProposal() assignToObject ()
WTChangeProposal() setToObject()
checkAttributes() getIdentity()

Change Proposal Model

The Enterprise Layer 37-33


Analysis Activity
The following figure shows the model for analysis activities:

<<Interface>> <<Abstract>> <<Interface>> <<Interface>> <<Interface>>


AnalysisActivityIfc CabinetManaged ContentHolder ChangeItem Elect ronically Signable
(from enterprise) (from content) (f ro m el ectroni cI dent ity)

<<Interface>>
<<Abstract>> <<Abstract>>
Identified
(f rom f c)
Analys isAct ivit y IdentificationObject
(f rom f c)

WTAnalysisActivity
WTAnalysisActivityIdentity
number : String
<<Interface>> name : String name : String
Typed des cription : String number : St ring
(f rom t ype) needDate : Timest amp
results : String W TAnaly sisActivit yIdentity()
assignToObject()
W TAnalys isAct ivit y() s etToObject()
W TAnalys isAct ivit y() getIdentit y()
checkAtt ributes ()

Analysis Activity Model

37-34 Windchill Customizer’s Guide


Change Order
The following figure shows the model for change orders:

<<Abstract>> <<Interface>> <<Interface>> <<Interface>> <<Interface>>


Managed ChangeOrderIfc ContentHolder ChangeIt em ElectronicallySignable
(f rom enterprise) (from content) (from electronicIdentity)

<<Int erface>> <<Int erface>> <<Abstract>>


<<Abstract>>
Typed Identified IdentificationObjec t
ChangeOrder2 (f ro m f c)
(from type) (from fc)

WTChangeOrder2 WTChangeOrder2Identity
number : String number : String
name : String name : String
description : String
needDate : Timestamp getIdentity()
WTChangeOrder2Identity()
WTChangeOrder2() setToObject()
WTChangeOrder2() assignToObject()
checkAttributes()

Change Order Model

The Enterprise Layer 37-35


Change Activity
The following figure shows the model for change activities:

<<Abstract>> <<Interface>> <<Interface>> <<Interface>> <<Interface>>


CabinetManaged ChangeActivityIfc ContentHolder ChangeItem ElectronicallySignable
(f ro m e nterp ri se ) (from con tent) (from electronicIdentity)

<<Interface>> <<Abstrac t>> <<Interfac e>>


<<Abstract>>
Identified ChangeActivity2 Typed
Ident ificationObject
(from fc) (from type)
(f rom f c)

W TChangeAct ivity2 WTChangeActivity2Identity


number : String number : St ring
name : String name : String
description : String
needDate : Timestamp W TChangeAct ivity2Ident it y()
ass ignToObject()
WTChangeActivity2() setToObject()
checkAttributes() getIdentit y()
WTChangeActivity2()

Change Activity Model

37-36 Windchill Customizer’s Guide


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


37-38 Windchill Customizer’s Guide
38
Persistence Management

This chapter describes persistence management.

Topic Page
Overview ...........................................................................................................38-2
Persistence Manager..........................................................................................38-2
Query .................................................................................................................38-4
Transaction ........................................................................................................38-8
Paging................................................................................................................38-9
Referential Integrity ..........................................................................................38-9
Multi-object CRUD Persistence Manager APIs..............................................38-12
Batch (update where/delete from) Statement Capabilities ..............................38-13
Transaction Context and Listeners ..................................................................38-14
Referential Integrity Association Validation During Object Delete ...............38-15
Persistence Datastore Sequence Customization ..............................................38-16

38-1
Overview
The PersistenceManager is an interface for database access. To use the
PersistenceManager, a class must implement the wt.fc.Persistable interface. By
implementing Persistable, the classes have the necessary code generated to read
and write data to and from the database and display its identity. Applications
should access the PersistenceManager through a convenience class named
PersistenceHelper. The PersistenceManager operations support events associated
with the operation. Application code can listen for these events and perform some
related action in the same transaction.
Operations that fetch objects from the database perform access control checks on
each object returned in the result set. These query operations use
wt.query.QuerySpec to define the classes of objects to select from the database.
QuerySpec uses the wt.query.SearchCondition class to define search criteria. That
is, in the SELECT statement that is generated, the QuerySpec defines which
columns to select and which tables to select from, and SearchCondition defines
the WHERE clause. The fetch operations return wt.fc.QueryResult.
The operations that delete, modify, and store a Persistable object all perform
access control checks before continuing with the operation. These operations
return the Persistable object with updated persistence information.
Support for large result sets and long running queries is provided via the paging
mechanism. Much like a web search, paging allows the user to execute a query
and view results in pages via fetch requests. Result pages are defined in terms of
an offset and range. A paging session corresponding to a specify query is
available for paging fetch requests for a limited amount of time. This is due to the
limited system resources that must be used to implement the paging session.
Therefore, the user must be prepared to handle exceptions caused by a paging
session timeout.

Persistence Manager
The PersistenceManager is the base business manager that other managers use to
handle persistence. For programming convenience, a helper class has been
implemented to facilitate client (and server) usage of the PersistenceManager
methods. The name of the class is PersistenceHelper. The wt.fc package Javadoc

38-2 Windchill Customizer’s Guide


contains documentation on the various publicly supported PersistenceManager
methods.

Persistence Manager

Persistence Management 38-3


Query
The wt.query package contains the following classes for creating queries which
retrieve objects from the database.
When used with the find operation, QuerySpec can perform both single and
multiple class queries. The following sections discuss how to perform single class
queries using QuerySpec, SearchCondition, and QueryResult. The last section
describes how all three are used in multiple class queries.
The information in this section is sufficient for most database queries. If you
require more advanced SQL queries, see the Advanced Query Capabilities chapter
on page 36-1.

QuerySpec
QuerySpec is used as an argument on the find and navigate operations to define
the classes of objects to retrieve. The SearchCondition object (described later in
this section) defines the criteria on those classes.

QuerySpec in a Find Operation


You can specify a single class on the constructor for the find operation as follows:
QuerySpec(Class targetClass);

The following example retrieves all Parts from the database.


QuerySpec qs = new
QuerySpec(wt.part.WTPart.class);
QueryResult qr = PersistenceHelper.manager.find(qs);

Since this is usually not the desired result, search conditions are used to limit the
number of objects returned. For example, to add a search condition to the
QuerySpec, use the following form:
QuerySpec.appendWhere(WhereExpression where,
int[] classIndices)

The classIndices parameter is used to apply the search condition to the appropriate
classes in the QuerySpec. The classes referenced from the SearchCondition must
match the QuerySpec classes at the specified index.

QuerySpec in a Navigate Operation


For the navigate operation, you must specify both the targetClass and linkClass on
the constructor as follows:
QuerySpec(Class targetClass, Class linkClass);

The targetClass is the class of the "other side role" in the navigate.
SearchConditions can be appended based on either the target or the link.

38-4 Windchill Customizer’s Guide


Example:
QuerySpec qs = new QuerySpec( wt.part.WTPartMaster.class,
wt.part.WTPartUsageLink.class);

CompositeWhereExpression where =
new CompositeWhereExpression(LogicalOperator.AND);
where.append(new
SearchCondition(wt.part.WTPartMaster.class,

wt.part.WTPartMaster.NAME,SearchCondition.EQUAL,"XYZ"));
where.append(new
SearchCondition(wt.part.WTPartUsageLink.class,
WTAttributeNameIfc.CREATE_STAMP_NAME,true,
new AttributeRange(beginTime,endTime)));
qs.appendWhere(where, new int[] {0, 1});

SearchCondition
The number of objects retrieved by a QuerySpec is limited by criteria defined with
SearchCondition. The most common format of a SearchCondition constructor is
as follows:
SearchCondition(Class targetClass, String attributeName, String operation,
Object value)
The targetClass can be a concrete class, abstract class, or interface. When
appended to a QuerySpec, the SearchCondition is responsible for creating a
WHERE clause on the query.
The attributeName can be any attribute of the target class that maps to a column in
the table being queried. In the case of a target class that has AutoNavigate
associations to other classes, any attributes that map to columns in the base class
or associated class can be used. Not all attribute types can be used in a search
condition, for example, attributes stored in BLOB columns. To verify which
attributes can be used, inspect the InfoReport for the target class, looking at the
attribute’s PropertyDescriptor to ensure that its QUERY_NAME property is not
null.

QueryResult
The QueryResult object is the standard container returned from all Persistence
queries and navigations. QueryResult implements the standard
java.util.Enumeration plus the added abilities to determine the number of objects
in the QueryResult and reset the QueryResult to process it again.
Example: (using the QuerySpec created in the previous section):
QueryResult qr =
PersistenceHelper.manager.navigate(thePart,
wt.part.WTPartUsageLink.USES_ROLE,qs,false);

Persistence Management 38-5


The QueryResult in this example will contain WTPartUsageLinks with both the
WTPartMaster and WTPart roles populated because onlyOtherSide is false. If
onlyOtherSide had been true, QueryResult would contain WTPartMaster objects.
The SearchConditions narrow the search to only those WTPartMasters with the
name of "XYZ" who had usage links created between a specified beginTime and
endTime.

Multiple Class Queries


QuerySpec also supports multiple class queries when used with the find operation.
Any number of classes can be added to the QuerySpec and objects of those classes
will be returned from the database. The following two methods can be used for
adding classes:
addClassList(Class targetClass, boolean isSelectable)

appendClassList(Class targetClass, boolean isSelectable)

The difference between the two is that appendClassList() always adds a new class
to the QuerySpec. If the method addClassList() is used and the specified class is
already in the QuerySpec, the index of the existing class is returned. The index
returned when adding (or appending) a class is used when appending a search
condition for that class.
When using multiple class queries, all of the classes usually should be joined to
avoid redundant results. Use the following constructor for SearchCondition to join
two classes:
SearchCondition(Class targetClass, String targetAttribute,
Class linkClass, String linkAttribute)

When appending this type of SearchCondition to a QuerySpec, both class indexes


must specify classes in the QuerySpec.
When multiple classes are in the QuerySpec, the elements in the QueryResult will
no longer be Persistable objects. If the full object is selected (via the isSelectable
argument, then the QueryResult elements will be an array of wt.fc.Persistable
objects (that is, Persistable[]). The array is needed because more than one class
can be returned. The exact type of the element will be Persistable[]. If any
attributes of the class are selected, then the QueryResult elements will be an array
of java.lang.Object objects (that is Object[]).
When adding (or appending) a class, the boolean parameter isSelectable specifies
whether objects of that class will be returned in the QueryResult. The
QueryResult Persistable array will have the same order as the classes in the
QuerySpec. However, classes that are not Selectable will not appear in the
QueryResult. For example, if the QuerySpec contains the classes W, X, Y, and Z
with X and Z selectable, the QueryResult Persistable array will contain X and Z.
All of the classes in a multiple class query are subject to Access Control
regardless of whether objects of that class are returned in the QueryResult.

38-6 Windchill Customizer’s Guide


Example:
QuerySpec qs = new QuerySpec();

// Append the classes


int partIndex = qs.appendClassList(wt.part.WTPart.class,true);
int partMasterIndex =
qs.appendClassList(wt.part.WTPartMaster.class, true);

// Join the WTPart class to the View class via the View object
ID and
// the WTPart Foreign Key
SearchCondition sc = new SearchCondition(wt.part.WTPart.class,
wt.part.WTPart.MASTER_REFERENCE + "." +
WTAttributeNameIfc.REF_OBJECT_ID,
wt.part.WTPartMaster.class, WTAttributeNameIfc.ID_NAME);
qs.appendWhere(sc, new int[] { partIndex, partMasterIndex });

QueryResult result = PersistenceHelper.manager.find(qs);


while(result.hasMoreElements())
{
Persistable[] persistableArray = (Persistable[])
result.nextElement();
wt.part.WTPart part = (wt.part.WTPart)
persistableArray[partIndex];
wt.part.WTPartMaster partMaster = (wt.part.WTPartMaster)
persistableArray[partMasterIndex];
}

Persistence Management 38-7


Transaction
Transaction objects provide a mechanism that supports the standard concept of a
database transaction. It has the following methods:
start
After a transaction is started, all subsequent database inserts, deletes, and
updates are part of that transaction.
commit
Commits the pending database operations to the database.
rollback
Discards the pending database operations.
The pattern for a method that can throw WTException is as follows:
Transaction trx=new Transaction();
try {
trx.start();
<your code here>
trx.commit();
trx=null;
}
finally {
if (trx!=null)
trx.rollback();
}

If you create a transaction in which to perform some activities but never reach
your commit statement, be sure you mark the current transaction for rollback.
Someone else may accidentally ground out an exception and later try to commit
your partially completed work. The rollback call in a finally block, marks any
enclosing transaction so partial results cannot be accidentally committed later. If
code following notices a problem and calls rollback, the database is safe but, if
your code is the deepest transaction, it is your responsibility to call rollback if you
do not get to your commit call. Because you may not know for certain if your code
is the deepest transaction at the time an exception is thrown, you should always do
it.

38-8 Windchill Customizer’s Guide


Paging
The basic idea behind paging is the concept of a "snapshot" query. When a paging
session is opened, a "snapshot" is taken of the results. These results can then be
fetched in pages over multiple calls. When all desired fetches are complete, the
paging session should be closed. This cleans up any data associated with the
paging session to free system resources. These system resources are significant so
a timeout property exists. If the timeout limit is reached, then the paging session is
automatically closed. Any further fetch requests would result in an exception.
Another configurable property is the paging limit (there is a system wide value
and this value can also be overridden when opening a paging session). Because of
the system resource required, a limit can be set such that if the result set size of the
"snapshot" query is less than this value, then all of the results are returned
immediately and no paging session is established. Note also that the results of the
initial "snapshot" query are access controlled. Only data that the user can access
(i.e. data that the user has read permission for) will be stored for subsequent page
requests. In addition, the total count of the size of the result set will also be
returned when the paging session is opened.
This "snapshot" behavior is important to understand in terms of how the
underlying query results can change. Consider a paging session that is established
and a total paging size of 50 is available for fetch requests. The first 25 objects are
returned and displayed to the user. The set of data can be modified by other user
operations. For example, another user could delete an object in the second set of
25 objects. Now when a fetch request is made for objects 25 through 50, the object
that was deleted will not be available. The paging results will still contain 25
elements. However, for the object that was deleted, a null value would be returned
in the paging results. Another situation can occur for updates. Consider a paging
session that is established for a query that returns data where a numeric attribute
of an object is less than some value. Between the time that the paging session was
opened and a subsequent fetch request, an object from the results could have been
modified and the numeric attribute changed such that it no longer meets the
original query’s criteria. Yet, it would still be part of the paging session results
because it did meet the criteria at the time that the paging session was established.
This is another reason for the timeout limit on paging sessions.
The definition of the "snapshot" query uses the same query constructs as normal
queries. Both QuerySpec and CompoundQuerySpec objects can be specified. The
classes or column expressions that are selected will be returned in the fetch
requests. Criteria and sorting will be applied when executing the "snapshot"
query. The sorting (if any is specified) will be maintained on fetch requests. When
specifying a sort on a QuerySpec that will be paged, each ColumnExpression
must have a unique column alias. This should be specified using the
ColumnExpression.setColumnAlias() method. The actual fetch requests return a
PagingQueryResult, which is a sub-class of QueryResult. The PagingQueryResult
has additional paging attributes such as the paging session ID (used for
subsequent fetch requests) and the total paging size.

Persistence Management 38-9


The Paging APIs are specified as static methods in the wt.fc.PagingSessionHelper
class (see the wt.fc.PagingSessionHelper class entry in your installed Windchill
Javadoc for more information). There are several types of APIs that are available
for opening a paging session, fetching from a paging session, and closing a paging
session. The following example shows how these methods can be used to perform
an interactive paging session for an arbitrary query passed to the method as an
argument. The method consists of a while loop that prompts the user for an offset
and range for a fetch request (or to end the paging session). The first time through
the loop the paging results are null so the paging session is opened. The paging
session ID and total paging count values are then stored in local variables. The
paging session ID will be used to execute fetch requests and eventually close the
paging session. If the paging session has already been opened, then a fetch is
made using the offset and range. The paging results are then displayed along with
the offset, range, and total count. The last piece of code in the loop checks the
paging session ID to ensure that a paging session has been established. If the
query returned no results or the paging limit was not reached, then no paging
session would exist. This entire loop is enclosed in a try/finally block to ensure
that the paging session is always closed (if one has been established).
public void executePaging(QuerySpec a_querySpec)
throws WTException, WTPropertyVetoException
{
long pagingSessionId = 0;

try
{
PagingQueryResult pagingResults = null;
int offset = 0;
int range = 0;
int totalCount = 0;
boolean done = false;

while(true)
{
// Prompt user for offset and range
offset = ..;
range = ..;
done = ..;
if(done)
{
break;
}

if(pagingResults == null)
{
// Open Paging Session
pagingResults = PagingSessionHelper.openPagingSession(
offset, range, a_querySpec);
pagingSessionId = pagingResults.getSessionId();
totalCount = pagingResults.getTotalSize();

else
{
pagingResults = PagingSessionHelper.fetchPagingSession(

38-10 Windchill Customizer’s Guide


offset, range, pagingSessionId);
}

// Display QueryResult items


System.out.println("Displaying " + offset + " to " +
(offset + range) + " of " + totalCount);

if(pagingSessionId <= 0)
{
// No paging session was established
break;
}
}
}
finally
{
if(pagingSessionId > 0)
{
PagingSessionHelper.closePagingSession(pagingSessionId);
}
}
}

Persistence Management 38-11


Referential Integrity
The persistence layer supports associations between two Persistable objects via
classes extending wt.fc.BinaryLink. For these associations, the persistence layer
also supports enforcing referential integrity as specified in the associations
modeled properties. The Rose Information Modeler supports Association
Specification model properties, "Owner" and "Cascade", on the "Windchill A"
and "Windchill B" tabs for the corresponding role . Both properties will be
boolean options. The persistence layer will uses these properties when an object is
removed. If the "Owner" property is true, then the persistence layer will remove
the link object associated with the removed object. If the "Owner" property is
false, then the persistence layer does not implicitly remove the link object when
the object is removed, but it will verify that this association does not exist before
the transaction is allowed to commit. The "Cascade" property is used only when
an association link object is removed. If the "Cascade" property is true, then the
persistence layer will cascade the remove operation to the associated role object.
This occurs when the link is removed via a direct call or via the "Owner"
processing. The default value for all roles is "Owner=true" and "Cascade=false".
The role A and role B settings are independent of each other, and any combination
is valid. When extending an association, the sub-class will inherit these role
attributes from the parent, but the values can still be explicitly overridden in the
sub-class.

Multi-object CRUD Persistence Manager APIs


The “standard ” persistence manager persistence APIs now have multi-object
variants taking Windchill collections. These include store/insert, modify/update,
delete/remove, and prepareForModification as well as enhanced support for multi-
object navigation (query is already multi-object).The multi-object APIs will
dispatch multi-object events and will interact with the database using techniques
that will result in a significant performance boost over a simplistic looping
algorithm.

38-12 Windchill Customizer’s Guide


Batch (update where/delete from) Statement Capabilities
It is now possible to build the equivalent of the SQL statements “update where”
and “delete from”. Their use will generally be limited to cases where the API does
not have and does not need the objects brought back to the VM (from the
database) and no events eed dispatching. However, these APIs are extremely
efficient and when used properly represent the most efficient mechanism to
update and delete rows in the database.

When to use
The batch update/delete operations represent the most performant option for
affecting change in the database because they minimize both the data needed to
perform the operation and the data needed to affect the change – neither requires
that the objects to be changed first be retrieved from the database and only the
columns to change need to be sent (as opposed to full persistables) in the case of
an update.These APIs should be considered when:
• There is no need to bring the object back into the VM, either to perform tests
or to dispatch events
• None of the objects involved in the batch operation exist in memory prior to
the batch operation
In most cases, it is sufficient to say that their use should be limited only to cases
where there is never a need to bring the object – or its reference – back to memory
and should never be used on objects already in memory. The above guidelines are
based on the fact that the performance benefits drop when the data is actually
needed and by the fact that the changes won't be reflected in any of the in-memory
objects.
However, a gray area for batch update is in cases where the references are needed
for event dispatch, the dispatched event indicates that the change has occurred,
and the listeners need not inflate.

Persistence Management 38-13


Transaction Context and Listeners
New transaction capabilities allow for transaction contexts and listeners.
A transaction context is similar to the method context except that it is associated
to either a local or global transaction. The transaction context, like the method
context, allows for the sharing of data outside of that which is possible simply as
arguments to APIs.
A transaction listener, also associated to a local or global transaction, provides
hooks that get executed when the transaction commits, rolls back, or is about to
commit. These listeners provide a means to defer validations (until the database is
known to have no additional changes associated with the transaction), defer work
until immediately before the transaction would commit, as well as do additional
processing once it is known that the transaction has committed or rolled back.
Maintaining cache integrity is an example of when to use a TransactionListener.
// class for some Standard Service Manager
public class StandardSomeServiceManager extends StandardManager {

MyCache myCache;
// member class for service events
class MyListener extends ServiceEventListenerAdapter {
public void notifyVetoableEvent (Event e) {
KeyedEvent keyedEvent = (KeyedEvent) e;
Object targetObject = keyedEvent.getEventTarget ();
//
// check out event and object to see if we really care
what happens
//
// Set up with Transaction for commit
if (keyedEvent.getEventType ().equals
(PersistenceManagerEvent.POST_DELETE)) {
Transaction.addTransactionListener(new
Remover(targetObject));
}
}
}
// member class for transaction events
class Remover implements TransactionListener {
Object obj;
public Remover (Object obj) {
this.obj = obj;
}
public notifyCommit() {
// get my cache and remove object
getMyCache().remove(this.obj);
}
public notifyRollback() {
// ignore
}
}
public void performStartupProcess () {
myListener = new MyListener() // subclass of
ServiceEventListenerAdapter

38-14 Windchill Customizer’s Guide


// Set up to receive service events
getManagerService().addEventListener(myListener,
PersistenceManagerEvent.generateEventKey
(PersistenceManagerEvent.POST_DELETE))
}
public static MyCache getMyCache() {
if (myCache == null) {
try {
return new MyCache();
}
catch (RemoteExcepiton re) { // do something }
}
return myCache;
}
}
// class which implements the actual cache
public class MyCache extends CacheManager {
public MyCache() {
super();
}
}

Referential Integrity Association Validation During Object


Delete
The referential integrity feature promises to cleanup delete listeners that exist
simply to remove associations or to validate that objects should not be allowed to
be deleted due to the existence of associations. The replacement of these listeners
by referential integrity will improve performance because the centralized code can
more efficiently query for and delete associations than the individual listeners can.

Persistence Management 38-15


Persistence Datastore Sequence Customization

Objective
You want to create a new datastore sequence for use in Windchill.

Background
Windchill uses datastore schema objects to implement a sequence. In Oracle, this
is implemented directly as a sequence schema object. In SQLServer, this is
implemented as a table and access stored procedure.

Scope/Applicability/Assumptions
• This documentation assumes that you have access to the Windchill datastore
directory, <WindchillHome>/db, and access rights to execute DDL scripts in
the target datastore.
• For the modeled customization procedure, it is assumed that the Windchill
Information Modeler (i.e. Rose) has been successfully installed and
configured.

Intended Outcome
The end result of this solution is the creation of a datastore sequence.

Solution
Model a sequence class using Information Modeler.

Solution Elements

Element Type Description

<MySequence> Java class The class for representing a datastore


sequence in Windchill.

38-16 Windchill Customizer’s Guide


Procedure - Creating a Modeled Datastore Sequence
1. Create a class <MySequence> in <MyPackage> implementing the
wt.fc.DatastoreSequence interface.

2. Specify the sequence properties. Open the Class Specification dialog for the
class, select the "Windchill" tab, and choose the "Sequence" value from the
"Set" drop down list. Specify the initial seed and increment values if the
defaults are not sufficient.

Persistence Management 38-17


3. Generate the model elements.
4. Execute the sequence DDL. From a Windchill shell, execute:
<WindchillHome>/db/execute_sql_script.bat
<MyPackage>/create_<MySequence>_sequence.sql

5. Compile the <MySequence>.java class in <MyPackage>.

Customization Points

Procedure - Creating a Non-modeled Datastore Sequence in Oracle


When a non-modeled sequence is created, the database schema objects are not
included in the Windchill introspection information. Therefore, some tools that
rely on this information (e.g.Windu, upgrade tools) will treat these objects as
unrelated to Windchill.
1. Create the sequence DDL script "create_<MySequence>_sequence.sql" in
"<WindchillHome>/db/sql" directory. For multi-byte systems, use directory,
"<WindchillHome>/db/sql3".
2. Add the following lines to this script, substituting <MySequence>,
<MySequenceSeed>, and <MySequenceIncrement>.
exec WTPK.createSequence('<MySequence>',
<MySequenceSeed>,<MySequenceIncrement>)

3. Execute the sequence DDL. From a Windchill shell, execute


"<WindchillHome>/db/execute_sql_script.bat
create_<MySequence>_sequence.sql".

Procedure - Creating a Non-modeled Datastore Sequence in SQLServer


When a non-modeled sequence is created, the database schema objects are not
included in the Windchill introspection information. Therefore, some tools that
rely on this information (e.g.Windu, upgrade tools) will treat these objects as
unrelated to Windchill.
1. Create the sequence DDL script "create_<MySequence>_sequence.sql" in
"<WindchillHome>/db/sqlServer" directory.
2. Add the following lines to this script, substituting <MySequence>,
<MySequenceSeed>, and <MySequenceIncrement>.
CREATE TABLE wt_sequence_<MySequence> (dummy CHAR(1),
value BIGINT
IDENTITY(<MySequenceSeed>,<MySequenceIncrement>))
go
CREATE PROCEDURE wt_get_next_sequence_<MySequence>
AS
INSERT wt_sequence_<MySequence> (dummy) VALUES ('x')
RETURN SCOPE_IDENTITY()
go

38-18 Windchill Customizer’s Guide


3. Execute the sequence DDL. From a Windchill shell, execute
"<WindchillHome>/db/execute_sql_script.bat
create_<MySequence>_sequence.sql".

Procedure - Obtaining the Next Value in a Modeled Sequence


In the primary procedure above, a sequence class was created. To obtain the next
value in this sequence, use the PersistenceManager.getNextSequence(Class)
method passing <MyPackage>.<MySequence>.class.

Procedure - Obtaining the Next Value in a Non-modeled Sequence


In the non-modeled procedures above, a sequence was created directly in the
datastore. To obtain the next value in this sequence, use the
PersistenceManager.getNextSequence(String) method passing the string constant
<MySequence>.

Limitations
None.

Sample Code

Examples of Usage in Windchill Code


Sequence values are used in many areas within Windchill code. See sub-class of
wt.fc.DatastoreSequence in Where-Used Tool and/or Javadoc.

Packaged Samples
None.

Non-modeled Sample Scripts

Oracle
The following is a sample script for a partNumber sequence that begins with 1 and
has an interval of 20.
exec WTPK.createSequence('partNumber', 1, 20)

SQLServer
The following is a sample script for a partNumber sequence that begins with 1 and
has an interval of 20.
CREATE TABLE wt_sequence_partNumber (dummy CHAR(1), value BIGINT
IDENTITY(1,20))
go
CREATE PROCEDURE wt_get_next_sequence_partNumber
AS
INSERT wt_sequence_partNumber (dummy) VALUES ('x')

Persistence Management 38-19


RETURN SCOPE_IDENTITY()
go

Related Package/Class Javadoc


• Foundation module
wt.fc

38-20 Windchill Customizer’s Guide


39
Advanced Query Capabilities

This chapter describes advanced query capabilities supported in the wt.query


package. These capabilities support advanced SQL queries and you are assumed
to be familiar with the functionality and behavior of advanced SQL statements.

Note: See your installed Windchill Javadoc entries for the wt.query package for
further information, including database-specific support for SQL functions and
keywords.

Topic Page
QuerySpec .........................................................................................................39-2
SearchCondition ................................................................................................39-9

39-1
QuerySpec
The QuerySpec contains the following attributes and APIs for building complex
query expressions.

Descendant Query Attribute


By default, when a query contains a class, all concrete, persistable subclasses (that
is, all classes that have an associated table in the database) are queried. Use the
boolean descendant query attribute to control this behavior. When this attribute is
false, only the specified class in the query is queried in the database. Note that an
exception is thrown if the class is not concrete and persistable. Use this feature
only when it is necessary to perform a query against a single table.

Single Column Expression in SELECT Clause


When a class is selected in the query result set, every column of that class is
included in the SELECT clause so that a full object can be built and returned in
the QueryResult. In some cases, only single columns are needed in a result set.
When possible, single columns should be used since this is much more efficient
and offers better performance. The following API supports single column
expressions in the SELECT clause:
appendSelect(ColumnExpression a_column, int[] a_fromIndices, boolean
a_selectOnly)
The fromIndices parameter is used to associate the column expression to classes
in the query, if applicable. In general, a ColumnExpression may be associated
with zero or more classes in the From clause. See the following table to determine
the size of the a_fromIndices array based on the type of ColumnExpression. For
example, a single ClassAttribute would require one from index. A SQLFunction
with two ClassAttribute arguments and a ConstantExpression argument would
require two from indices. If no fromIndices are required, a null value can be
passed as the argument. The selectOnly parameter controls whether the column
expression should be returned as a result object. If true, the column expression is
included only in the select and is not returned as a result.
The ColumnExpression parameter specifies the query column to append to the
select clause. The following are concrete ColumnExpression implementations:

Column Expression Description Required From Indices

ClassAttribute This class represents a class attribute 1


that can be used in a SQL statement.
Introspection information is used to
determine the associated table and
column.

39-2 Windchill Customizer’s Guide


Column Expression Description Required From Indices

SQLFunction This class represents a SQL function 0 or more. This number is


within a SQL statement. based on the sum of the
required from indices of all
arguments.

ConstantExpression This class represents a constant in a 0


SQL statement.

KeywordExpression This class represents an expression that 0


evaluates to a SQL keyword that can be
used in a SQL statement.

TableColumn This class represents a table column that 0


can be used in a SQL statement. The
exact table and column name specified
are used directly in the SQL statement.

The following example builds a query for part numbers:


QuerySpec qs = new QuerySpec();
int classIndex = qs.appendClassList(wt.part.WTPart.class, false);
ClassAttribute ca = new ClassAttribute(
wt.part.WTPartclass, wt.part.WTPart.NUMBER);
qs.appendSelect(ca, new int[] { classIndex }, false);

Note that when the WTPart class is appended to the query, the selectable
parameter is false. The full object is not returned; only the number column is
returned.
Results are still returned in the QueryResult object. Each element of the
QueryResult corresponds to a row and is an Object array (that is, Object[]). In this
example, the number column is at index 0 for each element. The actual Java type
for each result is based on the table column and the JDBC SQL-to-Java type
mapping.
The behavior of queries for parent classes (that is, classes that have one or more
persistable, concrete subclasses) is to execute SQL for each table. When only
ColumnExpressions are included in the SELECT clause, all of these SQL
statements are implicitly executed as a single UNION statement instead of
multiple separate database queries.
Queries that include only column expressions still have Access Control applied.
Internally, columns are added to the query to retrieve information needed for
Access Control. When queries containing only columns are used as sub-selects as
part of an ObjectReference query (described later in this section), then the Access
Control columns are not added. This behavior is important to understand when
using aggregate SQL functions. When these are used, the SELECT clause must
contain only expressions with aggregate SQL functions (or the expression must be
included in the GROUP BY clause. If Access Control is applied to such a
statement, then it will result in invalid SQL.

Advanced Query Capabilities 39-3


Table Expression in FROM Clause
When a class is added to a query, the generated SQL includes the associated table
for the class in the FROM clause of the query. It is also possible to append a
TableExpression to the FROM clause as shown below:
appendFrom( TableExpression a_tableExpression )
The following are concrete TableExpression implementations:

ClassTableExpression This class represents a class specification of a


table that can be used in a SQL FROM clause.
Introspection information is used to determine the
associated table.

ClassViewExpression This class represents a "view" of a class table that


can be used in a SQL FROM clause. All
descendent classes are part of this view (however,
no additional sub-class columns are included).
This class is useful for queries involving outer
joins or group by because all sub-classes are
treated as a single "table".

SubSelectExpression This class represents a subselect that can be used


in a SQL statement. The subselect is specified via
a StatementSpec attribute.

ExternalTableExpression This class represents a table that can be used in a


SQL FROM clause. The exact table name
specified is used directly in the SQL statement.

The following example builds a query against a non-modeled table named dual:
QuerySpec qs = new QuerySpec();
int fromIndex = qs.appendFrom(new
ExternalTableExpression("dual"));
TableColumn dummyColumn = new TableColumn("dual", "dummy");
SQLFunction currentDate = SQLFunction.new
SQLFunction(SQLFunction.SYSDATE);
qs.appendSelect(dummyColumn, new int[] { fromIndex }, false);
qs.appendSelect(currentDate, null, false);

Expression in WHERE Clause


The most common type of WHERE clause expression is a SearchCondition.
However, other expressions can also be used. The following APIs support
expressions in the WHERE clause:
appendWhere(WhereExpression a_expression, int[] a_fromIndicies)

39-4 Windchill Customizer’s Guide


appendWhere(WhereExpression a_expression, TableExpression[]
a_tableExpressions, String[] a_aliases)
The following are concrete WhereExpression implementations:

SearchCondition This class represents a search


condition on a query. When appended
to a QuerySpec, the values will be
used in the SQL WHERE clause.

ExistsExpression This class represents an EXISTS


expression in a WHERE clause. A
StatementSpec instance is used for the
subselect.

CompositeWhereExpression This class represents a number of


WHERE expressions connected using
a logical operator (i.e. AND/OR).

NegatedExpression This class represents a negation of an


expression in a WHERE clause. This
class contains an aggregated
WhereExpression that is preceded
with a NOT when this expression is
evaluated.

The fromIndices parameter is used to associate the WHERE expression operands


with tables in the FROM clause. Similar to the appendSelect() method, the
fromIndices array is based on the types of WhereExpression and
ColumnExpressions used in those WhereExpressions. For example, a
SearchCondition with a ClassAttribute and a ConstantExpression would require a
single from index. A CompositeWhereExpression containing three
SearchConditions would require fromIndices array with size equal to the sum of
the size needed for each SearchCondition.
The following example demonstrates the proper usage of the fromIndices. This
code queries for parts and their associated alternate parts. A composite where
expression is used with several criteria: the second through fourth characters of
the associated part numbers are equivalent, the part name begins with "E", or the
alternate part name begins with "E". This first section of code sets up the classes
in the query, the select items, and the joins between the classes.
QuerySpec qs = new QuerySpec();
int partIndex = qs.appendClassList(wt.part.WTPartMaster.class, false);
int alternatePartIndex = qs.appendClassList(wt.part.WTPartMaster.class, false);
int linkIndex = qs.appendClassList(wt.part.WTPartAlternateLink.class, false);

// Define the attributes in the query


ClassAttribute partName =
new ClassAttribute(wt.part.WTPartMaster.class, wt.part.WTPartMaster.NAME);

Advanced Query Capabilities 39-5


ClassAttribute alternatePartName =
new ClassAttribute(wt.part.WTPartMaster.class, wt.part.WTPartMaster.NAME);
ClassAttribute partNumber =
new ClassAttribute(wt.part.WTPartMaster.class, wt.part.WTPartMaster.NUMBER);
ClassAttribute alternatePartNumber =
new ClassAttribute(wt.part.WTPartMaster.class, wt.part.WTPartMaster.NUMBER);

// Define constants used in the criteria


ConstantExpression subStringStart = new ConstantExpression(new Long(2));
ConstantExpression subStringEnd = new ConstantExpression(new Long(4));
ConstantExpression wildcardExpression = new ConstantExpression("E% [ ]");

// Add items to the select and join the classes


qs.appendSelect(partName, new int[] { 0 }, false);
qs.appendSelect(alternatePartName, new int[] { 1 }, false);
qs.appendJoin(linkIndex, wt.part.WTPartAlternateLink.ALTERNATES_ROLE, partIndex);
qs.appendJoin(linkIndex, wt.part.WTPartAlternateLink.ALTERNATE_FOR_ROLE,
alternatePartIndex);

In this next section, the criteria are constructed and appended to the query. Note
that the first SearchCondition uses two ClassAttribute instances. The
corresponding indices must be added to the fromIndices array that is used in the
appendWhere. Likewise, the second SearchCondition references the part class and
the third SearchCondition references the alternate part class. Therefore, four
fromIndices are required and each array element must correspond to the
appropriate SearchCondition.
CompositeWhereExpression orExpression =
new CompositeWhereExpression(LogicalOperator.OR);
orExpression.append(new SearchCondition(
SQLFunction.newSQLFunction(SQLFunction.SUB_STRING,
partNumber, subStringStart, subStringEnd),
SearchCondition.EQUAL,
SQLFunction.newSQLFunction(SQLFunction.SUB_STRING,
alternatePartNumber, subStringStart, subStringEnd)));
orExpression.append(new SearchCondition(
partName, SearchCondition.LIKE, wildcardExpression));
orExpression.append(new SearchCondition(
alternatePartName, SearchCondition.LIKE, wildcardExpression));

qs.appendWhere(orExpression, new int[] {


partIndex, alternatePartIndex, partIndex, alternatePartIndex });

The last API explicitly specifies table expressions and aliases for the WHERE
expression operands. This API is used for correlated subselects. When using
subselects, it is common to use correlated columns (that is, a join between a
column in the outer select and a column in the subselect). This is supported using
the appendWhere() API in which TableExpressions and aliases are passed
explicitly. For WhereExpressions that do not involve a subselect, the
TableExpressions and aliases are derived implicitly using the QuerySpec FROM
clause and the specified indices.
The following example builds a query using an EXISTS clause and a correlated
subselect. The query will return all PartMasters for which an alternate PartMaster

39-6 Windchill Customizer’s Guide


does not exist. An alternate is represented by the WTPartAlternateLink class,
which is a many-to-many association between PartMasters. The role A of the
WTPartAlternateLink class specifies the current PartMaster and the role B
specifies the alternate PartMaster. Following is the SQL for this query:
SELECT A0.*
FROM WTPartMaster A0
WHERE NOT (EXISTS (SELECT B0.ida2a2
FROM WTPartAlternateLink B0
WHERE (A0.ida2a2 = B0.ida3a5)))

The following code constructs the query specification. The outer select will return
PartMaster objects.
QuerySpec select = new QuerySpec();
int partIndex = select.appendClassList(wt.part.WTPartMaster.class,
true);

The following code constructs the subselect. The alias prefix is changed to avoid
conflicts with the outer select.
QuerySpec subSelect = new QuerySpec();
subSelect.getFromClause().setAliasPrefix("B");
int altIndex =
subSelect.appendClassList(wt.part.WTPartAlternateLink.class,
false);

subSelect.appendSelect(new ClassAttribute(

wt.part.WTPartAlternateLink.class, WTAttributeNameIfc.ID_NAME),

new int[] { altIndex }, true);

The following code explicitly sets up the TableExpressions and aliases, which are
passed as arrays. The join will be from the outer select to the subselect so the outer
select values are placed in the arrays at index 0 and the subselect values are placed
in the array at index 1. The arrays are then used to append the SearchCondition.
TableExpression[] tables = new TableExpression[2];
String[] aliases = new String[2];
tables[0] = select.getFromClause().getTableExpressionAt(partIndex);
aliases[0] = select.getFromClause().getAliasAt(partIndex);
tables[1] = subSelect.getFromClause().getTableExpressionAt(altIndex);
aliases[1] = subSelect.getFromClause().getAliasAt(altIndex);

SearchCondition correlatedJoin = new SearchCondition(


wt.part.WTPartMaster.class, WTAttributeNameIfc.ID_NAME,
wt.part.WTPartAlternateLink.class,WTAttributeNameIfc.ROLEA_OBJECT_ID);
subSelect.appendWhere(correlatedJoin, tables, aliases);

Finally, the negated EXISTS clause is appended to the outer select.


select.appendWhere(new NegatedExpression(new
ExistsExpression(subSelect)), null);

Advanced Query Capabilities 39-7


Bind Parameters
Bind parameters are a database/JDBC feature to take advantage of database
statement preparsing and optimization. Bind parameters are a mechanism for
replacing constants in a SQL statement with replacement parameters at execution
time. For example, the following WHERE clause expression uses the constant
’Engine’:
WTPartMaster.name = ’Engine’
This expression can be replaced with the following in the static SQL:
WTPartMaster.name = ?
and the value ’Engine’ can be bound to the parameter ? at execution time.
On a subsequent execution, a new value, such as Cylinder, can be bound to that
same parameter. If these two statements had used the constant value directly in the
static SQL, each statement would have been parsed, optimized, and precompiled
separately. When bind parameters are used, a single static SQL statement can be
reused multiple times.
This bind parameter feature is implicitly supported when using the QuerySpec,
SearchCondition, and other query classes. However, the bind parameters can also
be explicitly accessed using the following APIs:
getBindParameterCount()
getBindParameterAt(int a_index)
setBindParameterAt(Object a_value, int a_index)

Query Limit
A QuerySpec attribute, "queryLimit", can be used to limit the results returned
from a query. As the database results are processed, a count is kept for each item
in the result set. This count includes items filtered out due to Access Control. If
the limit is reached, then a PartialResultException will be thrown. This exception
will contain a QueryResult with the items that have been processed. This could be
used in a situation where a client may choose to display these results after issuing
a message that a query limit was reached.

39-8 Windchill Customizer’s Guide


SearchCondition
A SearchCondition represents a SQL WHERE clause expression of the following
form:
<left side operand> <operator> <right side operand>
The following are examples:
MyTable.Column1 = 5
MyTable.Column2 LIKE "E%"
MyTable.Column3 = JoinTable.Column1

Operands can also be more complex, such as SQL functions or subselects.


SearchCondition can use arbitrary RelationalExpression operands. The operands
can be specified using the SearchCondition constructor or setter methods. The
following are concrete ColumnExpression implementations:

ClassAttribute This class represents a class attribute that can be


used in a SQL statement. Introspection
information is used to determine the associated
table and column.

SQLFunction This class represents a SQL function within a


SQL statement.

SubSelectExpression This class represents a subselect that can be used


in a SQL statement. The subselect is specified via
a StatementSpec attribute.

ConstantExpression This class represents a constant in a SQL


statement.

KeywordExpression This class represents an expression that evaluates


to a SQL keyword that can be used in a SQL
statement.

RangeExpression This class represents a range in a SQL WHERE


clause.

DateExpression This class represents a date constant in a SQL


statement. This subclass of ConstantExpression is
necessary to provide the special handling for date
values.

ArrayExpression This class represents an array of constants in a


SQL IN clause.

TableColumn This class represents a table column that can be


used in a SQL statement. The exact table and
column name specified are used directly in the
SQL statement.

Advanced Query Capabilities 39-9


The following example builds a complex query to determine the WTPartMaster
object with the oldest modify timestamp after a specified date cutoff. Following is
the SQL for this query:
SELECT A0.*
FROM WTPartMaster A0
WHERE (A0.modifyStampA2 IN (SELECT MIN(B0.modifyStampA2)
FROM WTPartMaster B0
WHERE B0.modifyStampA2 > ’cutoff’) )

The following code constructs the query specification:


Class targetClass = wt.part.WTPartMaster.class;
QuerySpec subSelect = new QuerySpec();
subSelect.getFromClause().setAliasPrefix("B");
int subIndex = subSelect.appendClassList(targetClass, false);
int[] fromIndicies = { subIndex };
ClassAttribute subModifyStamp =
new ClassAttribute(targetClass,WTAttributeNameIfc.MODIFY_STAMP_NAME);
SQLFunction minFunction = SQLFunction.new SQLFunction(SQLFunction.
MINIMUM, subModifyStamp);
subSelect.appendSelect(minFunction, fromIndicies, false);
subSelect.appendWhere(new SearchCondition(subModifyStamp,
SearchCondition.GREATER_THAN, DateExpression.newExpression(cutoff)),
fromIndicies);

QuerySpec select = new QuerySpec();


int index = select.appendClassList(targetClass, true);
select.appendWhere(new SearchCondition(modifyStamp,SearchCondition.IN,
new SubSelectExpression(subSelect)), new int[] { index });

Compound Query
A compound query is a SQL statement that combines more than one component
query into a single SQL statement via a set operator. Set operators include
UNION, UNION ALL, INTERSECT, and MINUS. A compound query is
composed by specifying a set operator and adding component queries. The
component queries are StatementSpec objects so nesting of compound queries is
also supported.

Note: The current version of the Oracle JDBC driver contains a bug that prohibits
using parentheses around component statements in a nested compound query. The
setting of the wt.pom.allowCompoundParentheses property in the db.properties
file controls whether parentheses are used. By default, this setting is false to avoid
the Oracle JDBC driver bug. This workaround could lead to unexpected results if
the set operator precedence is significant.

The following example builds a compound query to return a specific PartMaster


number and the numbers of all of its alternates. Note that only numbers are
selected, not full objects. This is necessary because, if all subclasses are
considered, the compound query statement must include all subclass tables. These
subclass tables may contain additional columns that would make the select list for

39-10 Windchill Customizer’s Guide


each statement incompatible with other component statements. SQL requires that
each component query in a compound statement must have the same number and
corresponding type in the select list. Following is the SQL for this query:
SELECT A0.number
FROM WTPartMaster A0
WHERE (A0.name = ‘ENGINE')
UNION
SELECT A2.number
FROM WTPartMaster A0,WTPartAlternateLink A1,WTPartMaster A2
WHERE (A0.name = ‘ENGINE') AND
(A0.idA2A2 = A1.idA3A5) AND (A2.idA2A2 = A1.idA3B5)

The following code constructs the query specification. The first select constructed
is for PartMasters with the name ENGINE.
QuerySpec partSelect = new QuerySpec();
int partIndex = partSelect.appendClassList(wt.part.WTPartMaster.class, false);
partSelect.appendWhere(new SearchCondition(wt.part.WTPartMaster.class,
WTPartMaster.NAME, SearchCondition.EQUAL, "ENGINE"), new int[]
{ partIndex });

The next select is constructed for returning PartMaster alternates. An alternate is


represented by the WTPartAlternateLink class, which is a many-to-many
association between PartMasters. A join must be specified across this association
from the original part to its alternates.
QuerySpec altSelect = new QuerySpec();
partIndex = altSelect.appendClassList(wt.part.WTPartMaster.class,
false);
int altIndex = altSelect.appendClassList(W
wt.part.WTPartAlternateLink.class,
false);
int altPartIndex =
altSelect.appendClassList(wt.part.WTPartMaster.class,
false);

altSelect.appendSelect(new ClassAttribute(
wt.part.WTPartMaster.class, wt.part.WTPartMaster.NUMBER),
new int[] { altPartIndex }, false);

altSelect.appendWhere(new
SearchCondition(wt.part.WTPartMaster.class,
WTPartMaster.NAME, SearchCondition.EQUAL, "ENGINE"), new int[]
{ partIndex });

altSelect.appendJoin(altIndex,
wt.part.WTPartAlternateLink.ALTERNATES_ROLE,
partIndex);
altSelect.appendJoin(altIndex,
wt.part.WTPartAlternateLink.ALTERNATE_FOR_ROLE,
altPartIndex);

Finally, the compound statement is constructed using the two previous queries
and the UNION set operator.

Advanced Query Capabilities 39-11


CompoundQuerySpec compound = new CompoundQuerySpec();
compound.setSetOperator(SetOperator.UNION);
compound.addComponent(partSelect);
compound.addComponent(altSelect);

Access Control Consideration


The use of some advanced SQL APIs can bypass Access Control. These situations
are detected and an AdvancedQueryAccessException will be thrown. The
following advanced query uses will cause this exception:
• Sub-selects (wt.query.SubSelectExpression)
• MINUS or INTERSECT Compound Statements
(wt.query.CompoundQuerySpec)
• External Tables (wt.query.ExternalTableExpression)
• Aggregate Functions (wt.query.SQLFunction)
AVERAGE
MAXIMUM
MINIMUM
SUM
COUNT
• ROWNUM keyword (wt.query.KeywordExpression)
This is done to ensure that Access Control is not bypassed unknowingly. In some
cases, the use of these advanced SQL features that bypass Access Control is
legitimate. For these cases, the advanced checking can be disabled at runtime.
Query specification classes support an "advancedQueryEnabled" attribute that can
only be set from server side code. If applicable, the attribute should be set to true
on the query instance that is passed to the PersistenceManager query/find API to
allow these queries to be executed without throwing an exception.
// Use advanced APIs to build query.
// Disable checking of advance features
statement.setAdvancedQueryEnabled(true);
// Execute query with access control
PersistenceHelper.manager.find(statement);
The find() method executes the statement with access control. Therefore, Access
Control related columns may be implicitly added to the select. For some
advanced features, such as aggregate functions, INTERSECT, and MINUS, the
addition of these columns can affect the expected results or cause a SQL
exception. In these cases, to successfully execute the query, the server side, non-
access controlled query() method should be used.

39-12 Windchill Customizer’s Guide


PersistenceServerHelper.manager.query(statement);

Sorting
Queries can be used to sort the result data at the database level. However, in
general, database sorting should only be applied to paging queries and queries that
involve only ColumnExpressions. Other types of queries may be implemented as
several separate SQL statements so the sorting is only applied to the individual
statements and not the complete query. Any ColumnExpression can be used as a
sort column. The OrderBy item is used to pass the ColumnExpression to the
StatementSpec. The OrderBy also indicates the sort order (ascending or
descending) and optionally a Locale. If a Locale is specified, then any character
based attributes are sorted with respect to that Locale using the database language
support. For Oracle, this is the National Language Support (NLS) (see Oracle
documentation for more information). Java Locale values are mapped to Oracle
NLS linguistic sort names via dbservice.properties entries.
Sorting is supported for standard and compound queries via QuerySpec and
CompoundQuerySpec methods.
QuerySpec.appendOrderBy(OrderBy a_orderBy, int[] a_fromIndicies)

CompoundQuerySpec.appendOrderBy(OrderBy a_orderBy)

The QuerySpec method validates the ColumnExpression contained in the


OrderBy against the QuerySpec’s FROM clause. The CompoundQuerySpec
method does not validate. Note that neither method handles appending the
ColumnExpression to the SELECT clause of the statement. This still must be
done via the appendSelect() method. In both cases, it is recommended that a
column alias be set for each ColumnExpression that is contained in an OrderBy.
Depending on the type of query and the number of subclasses involved, the actual
SQL statements may not be valid if a column alias is not used. Note that the
column alias must not be a SQL reserved word (e.g., "number").
The following example builds a compound query using sorting. The names of
parts and documents are returned sorted by name. Following is the SQL for this
query:
SELECT A0.bname sortName
FROM WTPart A0
UNION
SELECT A0.bname sortName
FROM WTDocument A0
ORDER BY sortName DESC

The following code constructs the query specification. The first component query
is for Parts. Note the setting of the column alias.
String sortName = "sortName";

QuerySpec partQuery = new QuerySpec();


int classIndex = partQuery.appendClassList(wt.part.WTPart.class,
false);
ClassAttribute partName = new ClassAttribute(wt.part.WTPart.class,

Advanced Query Capabilities 39-13


wt.part.WTPart.NAME);
partName.setColumnAlias(sortName);
partQuery.appendSelect(partName, new int[] { classIndex }, false);

This next section constructs the Document portion of the query. The same column
alias is used.

QuerySpec docQuery = new QuerySpec();


classIndex = docQuery.appendClassList(wt.doc.WTDocument.class,
false);
ClassAttribute docName =
new ClassAttribute(wt.doc.WTDocument.class,
wt.doc.WTDocument.NAME);
docName.setColumnAlias(sortName);
docQuery.appendSelect(docName, new int[] { classIndex }, false);

Finally, the compound query is constructed using these two component queries.
The OrderBy is appended to the overall query. The default locale is used to sort
the names with respect to the user’s language.
CompoundQuerySpec query = new CompoundQuerySpec();
query.setSetOperator(SetOperator.UNION);
query.addComponent(partQuery);
query.addComponent(docQuery);
query.appendOrderBy(new OrderBy(partName, true

));

Join Support
Query joins are used for associating data contained in separate tables. Joins can be
accomplished by using the PersistenceManager navigate methods or through
adhoc WhereExpressions. The QuerySpec class also provides explicit support for
appending a join to a query using link classes and roles defined in the Rose model.
This offers the flexibility of the QuerySpec along with the simplicity of specifying
query joins using model information. The following QuerySpec methods can be
used.
appendJoin(int a_linkIndex, String a_role, Persistable a_source)
appendJoin(int a_linkIndex, String a_role, int a_targetIndex)

The following example builds a query that joins together the SubFolder and Part
classes via the FolderMembership link. The query returns all folders and all of the
associated parts that are contained in the folder. The following code constructs the
query specification. The first section adds the classes and the attributes that should
be returned. The final two lines of code join together the classes using the
modeled roles for the FolderMembership link class.
QuerySpec query = new QuerySpec();

int folderIndex = query.appendClassList(wt.folder.SubFolder.class, false);


int linkIndex = query.appendClassList(wt.folder.FolderMembership.class, false);
int partIndex = query.appendClassList(wt.part.WTPart.class, false);

39-14 Windchill Customizer’s Guide


query.appendSelect(new ClassAttribute(wt.folder.SubFolder.class,
wt.folder.SubFolder.NAME),
new int[] { folderIndex } , false);
query.appendSelect(new ClassAttribute(wt.part.WTPart.class, wt.part.WTPart.NAME),
new int[] { partIndex }, false);
query.appendJoin(linkIndex, wt.folder.FolderMembership.FOLDER_ROLE, folderIndex);
query.appendJoin(linkIndex, wt.folder.FolderMembership.MEMBER_ROLE, partIndex);

Advanced Query Capabilities 39-15


39-16 Windchill Customizer’s Guide
40
Internationalization and
Localization

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.

Topic Page
Background .......................................................................................................40-2
The Windchill Approach ...................................................................................40-3
Localizing Text Visible to the User ..................................................................40-5
Resource Info (.rbInfo) Files .............................................................................40-8

40-1
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
user-
You 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 locale-
Consider the use of decimals within numbers, currency symbols, date formats,
address styles, and system of measurement.
• How should data be formatted-
Consider 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 color-
When 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.

40-2 Windchill Customizer’s 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 application’s 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
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.

Internationalization and Localization 40-3


• 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 locale-


dependent way.

40-4 Windchill Customizer’s 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 user-
specified 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;

Internationalization and Localization 40-5


public void addNotify() {
//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
{
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"},

40-6 Windchill Customizer’s Guide


{"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","<

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.

Internationalization and Localization 40-7


Resource Info (.rbInfo) Files

wt.L10N.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 Source File Run-Time File

Message Text *RB.rbInfo *RB.class


*Resource.rbInfo *Resource.class

40-8 Windchill Customizer’s Guide


Modeled Metadata <package>ModelRB.rbInfo <package>ModelRB.RB.ser
(Display Names)

EnumeratedType Options <EnumType>RB.rbInfo <EnumType>RB.RB.ser


Definition

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

<key>.value The localizable text that will be Required


displayed.

<key>.constant A string that will be used to generate Message text: Optional


a constant field into the runtime
Metadata: Unused
resource bundle, which can be used
by code that does resource lookups. EnumeratedType: Unused

<key>.comment A comment describing the entry. Optional

<key>.argComment<n> A comment for each substitution Optional


argument of the value string.

<key>.customizable Indicates whether the resource entry Optional


is customizable.

<key>.deprecated Indicates (to the developer) whether Optional


the resource entry is deprecated.

<key>.abbreviatedDisplay Reserved for future use. Unused

<key>.fullDisplay Reserved for future use. Unused

Internationalization and Localization 40-9


Key Description Usage

<key>.shortDescription Reserved for future use. Unused

<key>.longDescription Reserved for future use. Unused

<key>.order Explicit sort order for the value, Message text: Unused
unused for alpha ordering.
Metadata: Unused
EnumeratedType: Optional

<key>.defaultValue Specifies the value is the default Message text: Unused


value for the Enumerated Type.
Metadata: Unused
EnumeratedType: Optional

<key>.selectable Specifies if the value should be Message text: Unused


allowed to be selected.
Metadata: Unused
EnumeratedType: Optional

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.

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.

40-10 Windchill Customizer’s Guide


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. See How Rose UML Maps to Localizable Resource Info Files in
the System Generation chapter on page 32-47.

EnumeratedType Options Definition


Resource Info files for enumerated types are described in the Enumerated Types
chapter on page 34-1.

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. For more information, see the
Command Line Utilities section the System Generation chapter on page 32-55.

Internationalization and Localization 40-11


40-12 Windchill Customizer’s Guide
41
Customizing Archive, Purge,
and Restore

Archive and Purge allow you to remove data from your Windchill system while
preserving a reasonable working set of data for end users. You have the ability to
couple archive functionality with purge so that while data is removed from the
production system, an archive of that data still exists to be retrieved as required.

Note: In order to access the archive functionality, you must install Windchill
Archive.

Topic Page
Archiving Related Classes.................................................................................41-2
Enabling Archive/Purge/Restore for Custom Classes.......................................41-4
Customizing Archive Upgrade..........................................................................41-8

41-1
Archiving Related Classes
Note: All objects that need to be archived must implement the
wt.fc.archive.Archiveable interface.

When creating an archive, Windchill gives you the ability to specify which
versions and iterations and which dependencies should be included with the item
selected for archival. The choices for each of these two options are as follows:
• CAD Dependencies: Required dependencies or All dependencies. This
choice pertains to CAD dependencies the same way it does elsewhere in the
product.
• Version and Iterations: Latest iteration of latest version or Latest iteration
of each version: This logic (in some cases) recursively collects objects based
on a list of link objects that connect archive-supported objects in Windchill.
This enables Windchill to recreate the object with enough contextual information
to use it meaningfully after restore, even if all such information has been deleted
from active use from the Windchill instance at the point of restore.
Out of the box, Windchill takes a "safety first" approach and collects all the
supported contextual objects (barring exceptions) for the Versions and Iterations
category of related items.
The list of supported objects is as follows:
wt.epm.structure.EPMMemberLink
wt.epm.structure.EPMVariantLink
wt.epm.structure.EPMReferenceLink
wt.epm.build.EPMBuildHistory
wt.epm.structure.EPMContainedIn
wt.part.WTPartUsageLink
wt.part.WTPartReferenceLink
wt.part.WTPartDescribeLink
wt.epm.build.EPMBuildLinksRule

For your business objectives, a subset of the above list may make more sense
and/or you may need to add customized links to the list. The following
information describes the way related objects are collected by Windchill; this
needs to be understood to customize this behavior:
• Windchill uses wt.dataops.objectcol.RelationshipMapDef objects and
wt.dataops.objectcol.RelationshipMap objects to control the collection of
related objects.
• Windchill loads one wt.dataops.objectcol.RelationshipMapDef object, that
holds the traversal map for related objects based on
<Windchill>/loadFiles/content/RelationshipMap.xml file, as part of the base
data loading.
• Windchill loads four wt.dataops.objectcol.RelationshipMap objects that use
the above loaded wt.dataops.objectcol.RelationshipMapDef object and

41-2 Windchill Customizer’s Guide


correspond to each of the four options offered by Windchill (given the
combination of two options with two choices each as described above), as part
of the base data loading.
To change/extend the related object collection behavior, you need to delete and
recreate the five objects above. This can only be done before any one of them has
been used in active Windchill use, that is, by creating a archive.
Follow the steps below for this customization:
1. Delete the five objects referred to above, making sure they have not been used
earlier (and thus ensuring referential integrity is not violated). For example,
use the PersistenceManager API to delete the objects (see the Persistence
Management chapter on page 38-1).
2. Make a copy of <Windchill>/loadFiles/content/RelationshipMap.xml and
suitably alter the related object definition in it. The DTD is located in
<Windchill>/codebase/registry/objectcol/dtds/Criterion-def.dtd.
3. Make a copy of <Windchill>/loadFiles/BaseCriterionDefs.xml, removing all
sections except for those that relate to the creation of RelationshipMapDef
and RelationshipMap objects. Change the reference of the XML to refer to the
new, altered copy of RelationshipMap.xml from the previous step.
4. Reload the objects deleted in step 1 by loading the new
BaseCriterionDefs.xml copy from the step above, using the LoadFromFile
mechanism. For example,
windchill wt.load.LoadFromFile
-d <Windchill>/loadFile/BaseCriterionDefs.xml

For more information on data loading, see:


• Windchill Installation and Configuration Guide - Windchill
• Windchill Data Loading Reference and Best Practices Guide

Customizing Archive, Purge, and Restore 41-3


Enabling Archive/Purge/Restore for Custom Classes

Introduction
This section describes the procedure for enabling the archive, purge, and restore
of custom classes. Specifically it discusses the creation of Import Export (IX)
handlers for those classes and steps for configuring the IX and
Archive/Purge/Restore Framework.
The following steps need to be performed in order to achieve this.
• Write IX handlers for all custom classes, including relationship classes.
• Make appropriate entries for the new classes in coreobjects.dtd ,
coreX05.xml.
• Make appropriate entries in RelationshipMap.xml

Note: All objects that need to be archived must implement the


wt.fc.archive.Archiveable interface.

Writing Handlers
You will need to create IX handlers for all your custom classes including your link
classes.
Refer to the How to Write Exp/Imp Handlers section in the Import Export
Framework chapter on page 42-17. In addition you can refer to the
implementation of handlers for WTPart and WTDocument. Alternatively you can
derive your handlers from existing handlers and reuse the code.
Apart from importing normal attributes, you need to export and import certain
additional attributes.
To do this use the wt.ixb.archive.ArchiveHndHelper class. This class provides
helper methods that IX handlers need to support Archive and Restore
functionality. In your IX handler you should check to see whether archive/restore
is being done. In this case you must also perform certain operations on the
archive-specific attribute. To export/import Archive-related attributes use the
ExpImpForFlexibleVersioningAttr, ExpImpForArchiveAttr,
ExpImpForMarkUpAttr classes.
You can refer to the IX Handler for WTPart for details.
The following examples show sample code that is added to various methods to
enable archive/restore.
• protected void exportAttributes (Object object, IxbDocument fileXML,
Exporter exporter)
if (ArchiveHelper.isArchiveRestoreContext(exporter)) {
IxbHndHelper.exportAttribute(ExpImpForFlexibleVersioningAttr.class, ob, fileXML,
exporter);

41-4 Windchill Customizer’s Guide


IxbHndHelper.exportAttribute(ExpImpForArchiveAttr.class, ob, fileXML, exporter);
IxbHndHelper.exportAttribute(ExpImpForMarkUpAttr.class, ob, fileXML, exporter);
}

The above code will ensure that Archive and Flexible Versioning attribute
information is also stored in the archive.
• public void checkConflicts (IxbElement fileXML, Importer importer)
If you are implementing this method you should also include the code below.
if (ArchiveHelper.isArchiveRestoreContext(importer)) {
IxbHndHelper.checkConflictForAttribute(ExpImpForFlexibleVersioningAttr.class,
existingOb, fileXML, importer);
IxbHndHelper.checkConflictForAttribute(ExpImpForArchiveAttr.class, existingOb,
fileXML, importer);
}

• public Object importObjectAttributes (Object ob, IxbElement fileXML,


Importer importer)
if (ArchiveHelper.isArchiveRestoreContext(importer)) {
ob = IxbHndHelper.importAttribute(ExpImpForFlexibleVersioningAttr.class, ob,
fileXML, importer);
ob = IxbHndHelper.importAttribute(ExpImpForArchiveAttr.class, ob, fileXML,
importer);
}
· public Object importObjectAttributesAfterStore(Object object,IxbElement fileXML,
Importer importer)
if (ArchiveHelper.isArchiveRestoreContext(importer)) {
ob = (WTPart)IxbHndHelper.importAttribute(ExpImpForMarkUpAttr.class, ob,
fileXML, importer);
}

• If your handler classes do not extend from existing handler and your classes
are not derived from an out-of-the-box class you will also need to override the
storeObject method to ensure that your objects are created with the same
OIDs they had before archive/purge.
public Object storeObject( Object object, IxbElement fileXML, Importer importer )

For example,
ObjectIdentifier oid = ((Persistable)
object).getPersistInfo().getObjectIdentifier();
ArchiveHndHelper.addOidForReuse(Transaction.getCurrentTransaction(), oid);
PersistenceHelper.manager.save(object) ;

Make entries in coreobjects.dtd , coreX05.xml


Refer to the Import Export Framework chapter on page 42-1.

Customizing Archive, Purge, and Restore 41-5


Make entries in RelationshipMap.xml
• Make entries for your link class in <Windchill>/
loadFiles/content/Relationshipmap.xml . You need to create entries in
Relationshipmap.xml only if you have custom links between your classes.
• The link class is identified by the link tag and the classname is the fully
qualified class name of your link class. The field attribute of the derived tag
allows the collection service to fetch the dependent object.
• The seeds are the classes to be collected. These are specified using the seed
tag. You can ensure that descendants of your class are selected by setting the
allow-subtypes attribute to true.
• The output-type element is the other end of the relationship. The collection
service will collect all objects of output-type that are related to the seed. You
can set the allow-subtypes attribute to true to ensure that descendants are also
considered for collection.
<!-- CustomOtoOLink -->
<related>
<by-relationship collect-related-by='true' collect-other-end='true'
other-end-dependant='true'>
<output-types>
<output-type classname='auto.Custom.CustomDoc' allow-subtypes='true'/>
</output-types>
<relationship>
<seeds>
<seed classname="auto.Custom.CustomPart" allow-subtypes="true"/>
</seeds>
<link classname="auto.Custom.CustomOtoOLink"/>
<role>
<name>
<derived>
<derive classname="auto.Custom.CustomOtoOLink"
field="CUSTOM_DOC_ROLE" />
</derived>
</name>
</role>
<recurse>
<input type="string" name="recurse-part-reference" required="false"
default-value="false">
<match>
<pattern resource="true value">true</pattern>
<pattern resource="false value">false</pattern>
</match>
</input>
</recurse>
</relationship>
</by-relationship>
</related>

Recreate the schema for the Dataops module and load the XML file into the
database using the LoadFromFile mechanism. For example,
windchill wt.load.LoadFromFile

41-6 Windchill Customizer’s Guide


-d <Windchill>/loadFile/BaseCriterionDefs.xml

Limitations
• For archive information to be stored objects need to implement at least the
Iterated and Ownable interfaces.
• For storing Archive attribute information your classes need to be Iterated and
Ownable.
• For storing Flexible attribute information your classes need to be Iterated and
Federatable.
• If your classes are not Iterated and Ownable you will not be able to store
Archive information, however you can import/export your custom attributes,
and restore the OIDs as this only requires your classes to be Persistable.

Customizing Archive, Purge, and Restore 41-7


Customizing Archive Upgrade
Since Customized objects can be exported and archived and also undergo schema
changes, it is necessary to provide support for upgrade of jars that contain these
objects.
Archive upgrade also applies to customized objects. This needs to be done if all of
the following conditions are true.
• Customers have customized (modeled) classes that are Archiveable.
• Such objects have been Archived
The dtd of objects have changed in the current version. The kinds of changes that
may occur are listed in the Schema Changes section.
All the facilities listed above can be used by customizes as well. Developers
making these changes should not change any out-of-the-box artifacts. This may
cause failures during Upgrade.
To start customizing Archive Upgrade the customizer must decide on a location to
store the Customized Archive Upgrade Artifacts. This will be referred to as the
customization_dir. The com.ptc.windchill.ixupgrade.customization_dir property
must be added to site.xconf and propagated to ixupgrade.properties. The artifacts
to be created and the syntax is exactly the same as the out-of-the-box procedure.
Please refer to the other sections for details. The most important difference is the
location for the customized artifacts.
• Create all the required artifacts as described in the document.
• Run the IXUpgrade utility.
• The rules and XSLs will be generated under the customization_dir directory.

How customized archive upgrade works?


In a customized environment Archives created might contain out-of-the-box
objects as well as well as customized objects. out-of-the-box objects are handled
automatically. Rules for out-of-the-box objects cannot be customized or changed;
they can only be changed as result of a MOR update. If the customization_dir is
specified then the Archive Upgrade framework assumes that customization has
been done. The Archive Upgrade framework distinguishes between customized
artifacts and out-of-the-box artifacts. There are two sets of rules and two sets of
generated and hand-written XSL. At the time of upgrade the two sets of rules are
combined to form a single consolidated set of rules. Since there cannot be any
overlap in the objects available out-of-the-box and objects that are Customized the
right rules are automatically applied. It is very important to test all these changes
and restore on a test system to make sure there are no problems in you upgrade
code or artifacts.

41-8 Windchill Customizer’s Guide


Writing upgrades

Preparation for Archive Upgrade Development


Create a directory structure similar to the following. The only variable is the
cust_archive_upgrade directory that can be given a suitable name and stored in a
convenient location.

CAPTION

Determine Schema Changes


Determine the types of changes that have occurred between releases. For the kind
of changes that are possible please refer to Schema Changes.

Deciding what artifacts need to be created


Decide a phase / phases for which you would have to create Artifacts. Refer to the
various phases in Archive Upgrade for details of the phase.
• JarPreUpgrade
• XMLUpgrade
Refer to common uses cases and how to write upgrades from them in the Common
Use Cases section.

Create the Upgrade descriptor


Create an upgrade descriptor in the right directory having a meaningful name.

Create Artifacts as required


Create custom XSLs , write java code etc for the phases you have chosen and put
them into the appropriate directory. Make sure that your complied java code is
available in the Methodserver's classpath.

Customizing Archive, Purge, and Restore 41-9


Run the IXUpgradeUtility
Running the IXUpgradeUtility will cause generation of all artifacts viz. rules,
Generated XSLs.

Testing Restore
The generated artifacts should be tested on a test system by restoring old archives
containing customized objects prior to deploying on a production system.

41-10 Windchill Customizer’s Guide


42
Import Export Framework

This chapter describes the Import Export (IX) Framework and explains how to
customize and use it for various solutions.

Topic Page
Overview ...........................................................................................................42-2
How to Write an IX Application .......................................................................42-3
How to Write Exp/Imp Handlers.....................................................................42-17
Navigating Through an Object’s Structure with ObjectSet Application.........42-26
Product Design eXchange (PDX) Support for Export ....................................42-46

42-1
Overview
The basic unit of job for the framework is importing or exporting a single object.
The framework understands the transactional nature of import and encapsulates a
session of individual imports into one database transaction.

42-2 Windchill Customizer’s Guide


How to Write an IX Application
The export starts with Export application. The code of the application that invokes
export should look as follows:
ExportHandler appHandler = new ExportHandler ();
Exporter exporter = IxbHelper.newExporter(handle,
IxbHelper.STANDARD_DTD,
clientSettingsElement,
policyFile==null?(File)null:policyFile.getFile());

Iterator iter = objectSet.iterator();


while (iter.hasNext()) {
Persistable ob = (Persistable)iter.next();
exporter.doExport(ob);
}
exporter.finalizeExport();
appHandler.cleanUp ();

Create an Application Export Handler 'appHandler'. This is an instance of a class


either implementing ApplicationExportHandler interface or extending the abstract
class ApplicationExportHandlerTemplate. In the export application in
StandardIXBService, the appHandler extends ApplicationExportHandlerForJar, a
subclass of ApplicationExportHandlerTemplate

The job of the 'appHandler' is:


• To create a file to store exported objects (e.g. a JAR file).
• To store logs to be sent back to the client (optional).
• To clean up temporary files and do other clean-up jobs (advised, but
optional).
To create, the following methods must be implemented in 'appHandler':
• storeLogMessage(...) methods are used to send logs back to clients.
It is up to the developer how to implement the mechanism to send the logs
back. If you do not want to send any log messages, make your Export Handler
extend ApplicationExportHandlerTemplate. This class has the
default storeLogMessage() (empty method).
• It is optional to have clean up and other concluding tasks here, and these jobs
must be called explicitly after exporter.finalizeExport().
The Application Export Handler may also contain methods to perform tasks of
transforming the output if the application needs to modify the exported XML. For
example, PDXExportHandler has methods for XSL transformation to PDX
format. These methods must be called explicitly after
exporter.finalizeExport().
The existing implementations of the Application Export Handler are:

Import Export Framework 42-3


• WCXMLExportHandler extends ApplicationExportHandlerTemplate.
This is a public class designed for creating export jar file on server. (It is
mostly a copy of the inner class ExportHandler in StandardIXBService.). This
handler will be removed in 7.0, since now we have
ApplicationExportHandlerForJar.
• PDXExportHandler extends ApplicationExportHandlerTemplate. This
class performs specific tasks connected with export to PDX format. This
includes creating additional XML attributes/elements and XSL transformation
to PDX format.
Create an instance of the Exporter class, and use it to export objects by calling
exporter.doExport(obj), where obj runs through all WT objects
collected for export.
After this, call exporter.finalizeExport(), perform any additional tasks
(for example, transformation to another format), call methods of appHandler to
clean up after the export process, send log messages to client.
The methods doExport(…), doExportImpl(…) and the inner class ExportHandler
in StandardIXBService are examples of one export application. Please see the
details in the section, "Example of an Export Application" later in this chapter.
Prerequisite
In order to create the export jar at a client specific location, the following
prerequisite needs to be satisfied before calling the doExport api of
StandardIXBService:
• The context key IXBStreamer.CLIENT_SAVE_AS_FILE needs to be set
with the complete client side file path:
WTContext.getContext().put(IXBStreamer.CLIENT_SAVE_AS_FILE,CLIE
NT_JAR);

Where CLIENT_JAR is the complete client side file path, e.g. c:\\
mydocuments\\impex.jar

Exporter Class
The details of the exporter class are as follows:
Definition:
public class Exporter extends ExpImporter{…};

Constructor:
Exporter (ApplicationExportHandler _applicationExportHandler,
String targetDTD,
IxbElement localMappingRules,
File policyRuleFile) throws WTException {
super ("export", localMappingRules);

42-4 Windchill Customizer’s Guide


// -- init expActionTuner --
applicationExportHandler = _applicationExportHandler;
dtd = targetDTD;
// -- init expActionTuner --
expActionTuner = new ExportActionTuner (policyRuleFile);
}

An explanation of the arguments follows:


_applicationExportHandler - an instance of any class that either
implements the interface ApplicationExportHandler,extends the
abstract class ApplicationExportHandlerTemplate or extends the
abstract class ApplicationExportHandlerForJar.
The class ApplicationExportHandlerForJar extends the class
ApplicationExportHandlerTemplate. The class
ApplicationExportHandlerForJar provides methods for storing XML
and content files in export jar file. It handles both ApplicationData content and
content residing in local file system.
_applicationExportHandler has a job of creating a Jar file (or any other
way of storing) of the resulting collection of XML pieces (exported objects). It
must implement two methods:
storeContent (ApplicationDataob);

storeDocument (IxbElement elem);

targetDTD: string that specifies what DTD must be used for export process.
The IX framework will find appropriate handlers for objects and Document Type
Definition for objects based on this DTD string. The DTD string used in
Windchill 9.0 is standardX10.dtd.
Generally the intent was to be able to export objects in any DTD. As you will see
below the class export handlers are resolved using the DTD identifier.
The string targetDTD is also written to the XML file of exported objects, so the
import process could know what DTD should be used to import objects.

localMapppingRules: XML file or XSL file that is used to override,


change or exclude certain attributes objects when the export process takes
place.

The following XML rule file overrides the Team Template attribute, and no matter
what team an object belonged to when it was exported, its team template attribute
will be “Change Team” in the “/System” domain.

<?xml version="1.0" encoding="UTF-8"?>


<userSettings>
<mappingRules>
<COPY_AS>

Import Export Framework 42-5


<tag>teamIdentity</tag>
<value>*</value>
<newValue>Change Team (/System)</newValue>
</COPY_AS>
</mappingRules>
</userSettings>

The XSL rule file tests if the exported object has the name of “part_c”, it will
override the Team Template attribute and version information, and tests if the
exported object has the name of “PART_B”, it will override the Team Template
attribute.
If you don’t want to override anything, just pass “null” for the argument
localMapppingRules.
policyRuleFile: XSL file that is used to override, change or exclude certain
attributes objects when the export process takes place.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="@* | node()" priority="-9">
</xsl:template>
<xsl:template match="WTPart">
<xsl:choose>
<xsl:when test="name='part_c'">
<newInfo>
<teamIdentity>Default (/System)</teamIdentity>
<folderPath>/Design</folderPath>
<versionInfo>
<versionId>B</versionId>
<iterationId>2</iterationId>
<versionLevel>1</versionLevel>
</versionInfo>
</newInfo>
</xsl:when>
<xsl:when test="number='PART_B'">
<newInfo>
<teamIdentity>Default (/System)</teamIdentity>
<folderPath>/Design</folderPath>
</newInfo>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

For example the policy rule file specifies that check out exported WTPart objects
in the database after exporting them. If an exported WTDocument object has the
number of “TESTDOC-1”, check it out after exporting it. With all other exported
WTDocuments, lock them in the database after exporting them.

42-6 Windchill Customizer’s Guide


<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" indent="no" encoding="UTF-8"/>

<!--
The syntax of Export Policy is standard XSL syntax. The output of
XSLT using the XSL policy file
must only have at most one element of the form:

<actionInfo>
<action>...</action>
</actionInfo>
-->

<!--

The following is a sample of a well-formed xsl. In the cases, where


there are no specific actions to be performed, nothing needs to be
done, which is the default action that would transpire as shown in
the uncommented section below.
-->

<!--

<xsl:template match="@* | node()" priority="-9">


</xsl:template>

<xsl:template match='WTPart'>
<actionInfo>
<action>Checkout</action>
</actionInfo>
</xsl:template>

<xsl:template match='WTDocument'>
<actionInfo>
<xsl:choose>
<xsl:when test="number='TESTDOC-1'">
<action>Checkout</action>
</xsl:when>
<xsl:otherwise>
<action>Lock</action>
</xsl:otherwise>
</xsl:choose>
</actionInfo>
</xsl:template>

-->

<!-- Do nothing by default -->


<xsl:template match="@* | node()" priority="-9">
</xsl:template>

</xsl:stylesheet>

Import Export Framework 42-7


If you don’t want to override anything, just pass “null” for the argument
policyRuleFile.

An instance of the Exporter must be created via the factory method


newExporter() of the class IxbHelper. For example:
Exporter exporter = IxbHelper.newExporter (
appHandler,
IxbHelper.STANDARD_DTD,
localMappingRules,
policyRuleFile);

Using the Exporter to Export Objects


After you create an instance of the class Exporter, for example exporter, you
can use it to export top-level objects. The call to export the object ‘obj’ would be
exporter.doExport(obj);
This is actually making a call to the method doExport (Object obj,
String targetDTD, String targetElem) in the class Exporter.
In this method, the real Export handler for the object obj will be created.

Note: A list of available export handlers is created based on XML files in the
folder <WC_home>\registry\ixb\handlers. If you pass a wrong DTD in the
constructor of Exporter (a DTD that is not available in the system), you will not
get the handler, so you cannot export the object.Please refer to the part “How to
write Export Handler” for information how to add entry for an Export handler to
XML files.

If you have more than one object, you have to pass them to the exporter one by
one. Let’s assume that those objects are in a set called res, then you can export
them like this:
Iterator iter = res.iterator();
while (iter.hasNext()) {
Persistable obj = (Persistable)iter.next();
exporter.doExport(obj);
}

After you export all objects, you must call exporter.finalizeExport();


You can call clean-up methods of appHandler (if there are any). Now the export is
finished.

Note: A sample file with comments is distributed along with installation


information.

42-8 Windchill Customizer’s Guide


How Import Works
To import objects from XML files in a jar file, import application must do the
following:
1. Create a tool to read the imported jar file and extract the list of XML files that
are contained in the jar file. Please see the doImportImp(…) method in the
StandardIXBService and the class IXBJarReader for an implementation
example.
2. Prepare the String ruleFileName to be passed into an instance of the class
Importer. The String ruleFileName can be obtained from an IxbStreamer,
from the user, assigned the value null or obtained from somewhere else,
depending on the structure of the import application.
3. Process policyFile (if it is not null) to create an XSL StreamSource that
contains the import policy.
4. Create an Application Import Handler appHandler. This is an instance of
any class that either implements the interface
ApplicationImportHandler or extends the abstract class
ApplicationImportHandlerTemplate

5. Create an instance of the class Importer (importer).


6. Get the list of XML files in the jar file.
7. Create IxbDocuments from those XML files.
8. With each IxbDocument, do the following:
– If there is an action name passed to the application and the policyFile is
null, apply the action name into the IxbDocument. If the policyFile is not
null, apply action name and action information in the policyFile into the
IxbDocument.
– Feed them to the importer one by one by calling the import process:
• importer.doImport(IxbDocument Doc);
• importer.finalizeImport();
9. Clean up (if needed).
10. Send log messages to client.
The methods doImport(...), doImportImpl(...) and the inner class
ImportHandler in the StandardIXBService are an example of one import
application. Please see the details in the part “Example of an Import Application”.

Import Export Framework 42-9


Versioned objects can be imported in any of 10 different manners decided by
action name and action information that are written to the IxbDocument fileXML
of each importing object. Developers who write import applications must know
about action names and their meanings to apply them correctly, but object
handlers don’t have to worry about the Actor classes. A list of all available action
names can be found in the file Windchill\src\wt\ixb\registry\ixb\handlers\
actor.xml.
All of the actions are different from each other in 3 crucial methods:
previewObject, createObject and storeObject. In the class
ExpImpForVersionedObject, based on action name and action information
that are passed into the IxbDocument fileXML, appropriate actor will be created
and this actor’s methods will be called to serve the purpose of previewing,
creating and storing versioned objects.
Here is the list by actor names for information.
1. PickExistingObject: Find if an object with the same ufid or same (name,
number, version, iteration) with the object in XML file exists in database. If
such an object exists, do nothing. Otherwise, import the object in XML file.
2. NewIteration: Import object in XML file as the next available iteration in
the database.
– For example: If there is no version/iteration in the database for the object
which is in the XML file, the imported object will get the version /
iteration specified in the XML file. If the latest version / iteration of the
object in the database is B.2, the imported object will be B.3.
3. NewVersion:Import objects from the XML file as the next available version
in the database.
– For example: If there is no version / iteration in the database for the object
which is in the XML file, the imported object will get the version /
iteration specified in the XML file. If the latest version / iteration of the
object in the database is B.2, the imported object will be C.1.
4. CheckOut: Find any version/iteration of the object in the XML file (Check the
existence of the master object in the database). If there is no version of the
object in the XML file, throw an error. Otherwise, find an instance of the
object in the database that has the same version (iteration can be different) as
the object in the XML file. If such an object exists, check out the latest
iteration of the object in the database, update it with information from the
XML file. I agree Otherwise, throw an error. No, we don’t check it in
5. ImportNonVersionedAttr: Find an object with the same ufid or same (name,
number, version, iteration) with the object in the XML file. If such an object
exists, update it with information from the XML file. Otherwise, throw an
error.
6. UpdateInPlace: Find an object with the same ufid or same (name,
number, version, iteration) with the object in XML file exists in database. If

42-10 Windchill Customizer’s Guide


such an object exists AND it is checked out, update it with information from
the XML file. Otherwise, throw an error.
7. UnlockAndIterate: Find an object in the database with the same ufid or
same (name, number, version, iteration) as the object in the XML file. If such
an object exists AND it is locked, unlock and iterate it, then update it with
information from the XML file. Otherwise, throw an error.
8. CreateNewObject: Create a brand new object with new name, new number,
new version, new iteration provided in Import Policy file. Other information
will be extracted from the XML file. This functionality cannot be used alone,

Note: This option cannot work without a policy file to specify the new object
identities.

The format of new information that must be provided in ImportPolicy file is:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">

<!--
The syntax of Import Policy is standard XSL syntax. The output of
XSLT using the XSL policy file
must only have at most one element of the form:

<actionInfo>
<action>...</action>
</actionInfo>

The following is a sample of a well-formed xsl. In the cases, where


there are no specific actions to be performed, nothing needs to be
done, which is achieved by the following:

<xsl:template match="@* | node()" priority="-9">


</xsl:template>

-->

<xsl:template match="@* | node()" priority="-9">


</xsl:template>

<xsl:template match='WTPart'>
<actionInfo>
<action>PickExistingObject</action>
</actionInfo>
</xsl:template>

<xsl:template match='WTDocument'>
<actionInfo>
<action>PickExistingObject</action>
</actionInfo>
</xsl:template>

<xsl:template match='EPMDocument'>

Import Export Framework 42-11


<actionInfo>
<action>PickExistingObject</action>
</actionInfo>
</xsl:template>

</xsl:stylesheet>

Note:

• <actionInfo> must always exist.


• Criteria can be any valid attribute of the object in XML file.
• Between <xsl:choose>, there can be many <xsl: when test ....> with different
criteria and different action names.
• Only CreateNewObject and SubstituteObject can have action params,
and there are only four action params <newName>, <newNumber>,
<newVersion>, <newIteration>, all of them must be provided.

• SubstituteObject: Substitute the object in the XML file for an object in


the database that has the name, number, version, and iteration provided in the
ImportPolicy file. If such an object doesn't exist, throw an exception. Format
of tag and params for this case is exactly the same with CreateNewObject,
but the <action> is SubstituteObject.
• Ignore: Do not import the object in the XML file. This action doesn't require
any actor.

Importer class
Definition: public class Importer extends ExpImporter
Constructor:
Importer (ApplicationImportHandler _applicationImportHandler,
String _dtd,

String _ruleFileName,

Boolean _overrideConflicts,

Boolean _validate

) throws WTException

Parameters explanation:
• applicationImportHandler: an instance of a class that either
implements the interface ApplicationImportHandler or extends the
abstract class ApplicationImportHandlerTemplate
• applicationImportHandler has a job of extracting from the Jar file
that stores XML, and its class must implement 2 methods:

42-12 Windchill Customizer’s Guide


getContentAsInputStream (String contentId);
getContentAsApplicationData (String contentId);
The later method may always return null to indicate that the file does not
exist in Windchill DB.

Note: Please see the inner class ImportHandler of the class


StandardIXBService for an example of implementation of an
application import handler.

• targetDTD: string that specifies what DTD must be used for import
process. The IX framework will find appropriate handlers for objects and
Document Type Definition for objects based on this DTD string if the
imported file does not specify any. The DTD string used in Windchill 9.0 is
standardX10.dtd.

• ruleFileName: Mapping rule file can be XML file (like in previous


versions) or XSL file, so this parameter is String. The constructor that uses
IxbElement _localMappingRules is deprecated. In the case you do not have
mapping rule file and want to put it to null, please do not put the “null” value
directly in the constructor, because it will cause one ambiguous reference
error. Instead of doing that, you should use a string, assign null value to it, and
pass it as ruleFileName. Mapping rule file is used to change, override or
exclude certain attributes objects when the import process takes place.
For example, the rule file overrides the Team Template attribute, and no matter
what team an object belonged to when it was exported, its team template attribute
is replaced by “Change” in the “/System” Domain on import.
<?xml version="1.0" encoding="UTF-8"?>
<userSettings>
<mappingRules>
<COPY_AS>
<tag>teamIdentity</tag>
<value>*</value>
<newValue>Change Team (/System)</newValue>
</COPY_AS>
</mappingRules>
</userSettings>

An example for XSL mapping rule file:


<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="WTPart">
<xsl:choose>
<xsl:when test="name='part_c'">
<newInfo>
<teamIdentity>Default (/System)</teamIdentity>
<folderPath>/Design</folderPath>
<versionInfo>
<versionId>B</versionId>
<iterationId>2</iterationId>
<versionLevel>1</versionLevel>

Import Export Framework 42-13


</versionInfo>
</newInfo>
</xsl:when>
<xsl:when test="number='PART_B'">
<newInfo>
<teamIdentity>Default (/System)</teamIdentity>
<folderPath>/Design</folderPath>
</newInfo>
</xsl:when>
<xsl:otherwise>

</xsl:otherwise>
</xsl:choose>

</xsl:template>
</xsl:stylesheet>

This XSL file says that whenever the import process meet a WTPart named
part_c, then change its team identity template to Default (/System), change its
folder part to /Design, and change its version to B.2, whenever the import process
meet a WTPart with the number PART_B, then change its team identity template
to Default (/System), change its folder part to /Design
If you don’t want to override anything, just pass “null” for the argument
localMapppingRules.

• _overrideConflicts: boolean value specifies whether the import process


should override “overridable” conflicts.
• _validate: boolean value specifies whether the import process should
validate the XML file of the imported object against the DTD.
An instance of the class Importer must be created via the method
newImporter() of the class IxbHelper. For example:
Importer importer = IxbHelper.newImporter(
handler,
IxbHelper.STANDARD_DTD,
ruleFileName,
overrideConflicts,
null);

Use Importer to import object from XML files


After you create an instance of the class Importer (importer) you can use it to
import objects from XML files. If you have more than one XML files to import,
you have to give IxbDocument-s that created from XML files to the importer one
by one.
As mentioned above, the Import Application server must call two methods to do
the import:
importer.doImport(IxbDocument doc);

importer.finalizeImport();

42-14 Windchill Customizer’s Guide


doImport (doc)
This method doesn’t really import the object, but inserts the XML document that
represents the object in to a list to be imported later. After all XML documents
representing all the imported objects are inserted in the import list, the real import
process starts with the call to finalizeImport().
• finalizeImport(): The import process is actually performed in this
method. It will call to:
doImport_CheckConflicts() - check conflicts for imported objects.

doImport_doRealImport () - do the real import for the list of objects


by calling importElement (IxbElement doc) for each XML
document representing each object in the list.
In the method importElement(…) the import handler for a particular type of the
object is created by calling getImportHandler(tag, dtdFromXML).
The method getImportHandler(…) finds the appropriate handler for the
imported object as follows.
1. Try to get an import handler by using the DTD string in the <dtd> tag of the
XML file of the imported object.
2. If the handler is null, try again using current DTD in the importer. This
current DTD is calculated using version of the current Windchill. For
Windchill R9.0 it is standardX10.dtd.
After getting the handler for the element, the importElement(…) calls the
following methods:
handler.importElement(…) to do the import task.

handler.outputLog(…) to send log to user.

All handlers for non-versioned objects (for example links, ReportTemplate ... )
extend the class ClassExporterImporterTemplate, and all handlers for
versioned objects (for example Parts, Documents, EPMDocuments ...) extend the
class ExpImpForVersionedObject.

Note: Handlers for non-versioned objects act like the previous versions.

If the real handler doesn’t implement the method importElement(…), then the
call invokes the default method importElement(…) of the class
ClassExporterImporterTemplate. In this class, the importElement(…)
method calls to
findAmongExistingObjects (fileXML, importer);
If it finds that the object in the XML file currently exists in the database, it will not
import the object. Otherwise, it will call the following methods:

Import Export Framework 42-15


createObject (fileXML, importer);

importObjectAttributes (ob, fileXML, importer);

storeObject (ob, fileXML, importer);

importObjectAttributesAfterStore (ob, fileXML, importer);

Some of these methods should be implemented in the handler, and it is how and
when the real handler comes to do its job.

Note: Handlers for versioned objects act different.

If the real handler doesn’t implement the method importElement(…), then


the call invokes the default method importElement(…) of the class
ExpImpForVersionedObject. In this class, despite the object in the XML
file exists in the database or not, the importElement(…) method always calls
to:
createObject (fileXML, importer);
importObjectAttributes (ob, fileXML, importer);
storeObject (ob, fileXML, importer);
importObjectAttributesAfterStore (ob, fileXML, importer);

Then, the Import Application can do a clean-up, and send messages to the client.
The import process is finished.

42-16 Windchill Customizer’s Guide


How to Write Exp/Imp Handlers

Writing Export Handlers for the Export Process


To create an export handler for a class, one needs to know three things:
1. How to use XML files that contain handlers information.
2. How to update DTD files that contain information about objects that will be
exported/imported.
3. How to write a handler.

XML files that contain handlers information


These XML files reside in the folder Windchill\codebase\registry\ixb\handlers.
The whole folder is processed as the root element of XML tags, and the contents
of XML files in this folder are processed as child elements. So, the XML files in
this folder are not well formed, and they have contents similar to the following:
<classExporter>
<class>
[class name of the object that will be exported with full path
name]
</class>
<dtd>
[String DTD, specifies where DTD for the class is stored]
</dtd>
<targetTag>default</targetTag>
<handler>
[class name of the handler that is used to export the object]
</handler>
</classExporter>

For example:
<classExporter>
<class>wt.part.WTPart</class>
<dtd>standardX10.dtd</dtd>
<targetTag>default</targetTag>
<handler>wt.ixb.handlers.forclasses.ExpImpForWTPart</handler>
</classExporter>

Import Export Framework 42-17


All handlers with the <dtd> tag “standardX10.dtd” are handlers for export object
in R9.0.
For example, for R9.0 we have tags:
<classExporter>
<class>wt.part.WTPart</class>
<dtd>standardX10.dtd</dtd>
<targetTag>default</targetTag>
<handler>wt.ixb.handlers.forclasses.ExpImpForWTPart</handler>
</classExporter>

So we know that the class


wt.ixb.handlers.forclasses.ExpImpForWTPart is a handler for
exporting the class wt.part.WTPart in R9.0 format.
The class IxbHandlersManager contains all necessary methods to manipulate
handlers.

DTD Files
In the folder Windchill\src\wt\ixb\registry\ixb\dtds\standardX10.dtd there is a file
named coreobjects.dtd that is the DTD file for all objects that will be
exported/imported.

How to Write a Class Export Handler


1. Create a Class that extends ClassExporterImporterTemplate
2. Implement exportAttributes(Object obj, Exporter exp) method,
which retrieves the data from the object and adds it to the XML DOM
Document. The following is an example of this method for the object of
“MyClass”:
public void exportAttributes (Object object, IxbDocument fileXML,
Exporter exporter) throws WTException {
try {

MyClass ob = (MyClass)object;
// export the local id
IxbHndHelper.exportAttribute(
ExpImpForLocalIdAttr.class, ob, fileXML, exporter);
// export other attributes that are specific to
// MyObject; e.g. name, number
IxbHndHelper.exportAttribute(
ExpImpForMyObjectAttr.class, ob, fileXML, exporter);
// export version information
IxbHndHelper.exportAttribute(
ExpImpForVersionAttr.class, ob, fileXML, exporter);
// export content
IxbHndHelper.exportAttribute(
ExpImpForContentAttr.class, ob, fileXML, exporter);

}
catch (Exception e) {
LogHelper.devExc ( e,

42-18 Windchill Customizer’s Guide


"exportAttributes: could not export
object=<"+object+">");
}
}

3. Override getRootTag() method, which returns the desired root tag for the
object type to be exported. The following is an example of this method for the
object of "MyClass":
protected String getRootTag() {
return "MyClass";
}

4. Add an entry in the handlers XML file (<WC_home>\registry\ixb\


handlers\coreX10.xml) that specifies the class being exported
(com.mycompany.MyObject), the XML DTD for core Windchill objects
(standardX10.dtd), and the handler for the class
(wt.ixb.handlers.forclasses.ExpImpForMyObject). An example
entry follows:
<classExporter>
<class>com.mycompany.MyObject</class>
<dtd>standardX10.dtd</dtd>
<targetTag>default</targetTag>
<handler>wt.ixb.handlers.forclasses.ExpImpForMyObject</handler>
</classExporter>

How to Write an Attribute Export Handler


If there is an attribute that is required to be exported the same way for different
classes or if you simply decide to handle it is a separate handler, you can create an
attribute handler. The steps to follow are:
1. Create a Java class extending AttributeExporterImporterTemplate.
2. Implement exportAttribute(Object ob,IxbElement fileXML,
Exporter exporter) method, which retrieves the attribute data from the
object and adds it to the XML DOM Document. The following is an example
of this method for the object “MyObject”. This method gets the part type and
the part source of the object.
3. public void exportAttribute (
Object obj,
IxbElement fileXML,
Exporter exporter) throws WTException{
try {
MyClass ob = (MyClass) obj;
LocalizableMessage localMessage1 = ob.getDisplayType();
Locale locale1 = new Locale("English", "US");
String dispType = localMessage1.getLocalizedMessage(locale1);
fileXML.addValue(IxbHndHelper.XML_ATTR_PARTTYPE, dispType);
fileXML.addValue(
IxbHndHelper.XML_ATTR_SOURCE,ob.getSource ().toString() );

Import Export Framework 42-19


}
catch (Exception e){
LogHelper.devExc (e,
"Exception in ExpImpForLTPartAttr, ob=<"+obj+">");
}
}

After adding this, the export handler for class may call this method to have the
part attribute exported.

How to Write Handlers for the Import Process


To create import handlers for a class, there are two things to know:
1. XML files that contain handlers information.
2. How to write a handler.

XML files that contain handlers information


These XML files are in the folder Windchill\codebase\registry\ixb\
handlers.
The whole folder is processed as the root element of XML tags, and the contents
of XML files in this folder are processed as child elements. So the XML files in
this folder are not well formed, and their contents are similar to the following:

<elementImporter>
<tag>
[class name of the object that will be imported without full
path name ]
</tag>
<dtd>
[String DTD, specifies where DTD for the class is stored]
</dtd>
<handler>
[class name of the handler that is used to import the object]
</handler>
</elementImporter>

For example:
<elementImporter>
<tag>WTPart</tag>
<dtd>standardX10.dtd</dtd>
<handler>wt.ixb.handlers.forclasses.ExpImpForWTPart</handler>
</elementImporter>

All handlers with the <dtd> tag “standardX10.dtd” are handlers for import
object in R9.0.

For R9.0 format we have tags:

42-20 Windchill Customizer’s Guide


<elementImporter>
<tag>WTPart</tag>
<dtd>standardX10.dtd</dtd>
<handler>wt.ixb.handlers.forclasses.ExpImpForWTPart</handler>
</elementImporter>

So we know that the class


wt.ixb.handlers.forclasses.ExpImpForWTPart is handler for import of
the class wt.part.WTPart in R9.0.
The class IxbHandlersManager contains all methods to manipulate handlers.

How to Write a Class (Element) Import Handler


Import handlers for classes can be divided in to two types:
• Import handlers for versioned objects.
• Import handlers for non-versioned objects.

Handler for Non-Versioned Object


1. Create a Java class that extends ClassExporterImporterTemplate
2. Implement method:
public Object createObject (IxbElement fileXML, Importer
importer)

3. Override the following methods if necessary:


public Object importObjectAttributes (Object ob,
IxbElement fileXML,
Importer importer);

public Object storeObject (Object object,


IxbElement fileXML,
Importer importer);

public Object importObjectAttributesAfterStore(Object object,


IxbElement fileXML,
Importer importer);

public Object findAmongExistingObjects (IxbElement fileXML,


Importer importer);

Import handlers for non-versioned objects are quite straightforward, and any of
the following classes can be referred as example:
ExpImpForWTPartDescribeLink
ExpImpForWTPartReferenceLink
ExpImpForWTPartUsageLink

Import Export Framework 42-21


Note: An object is imported by the following sequence: createObject(),
importObjectAttributes(), storeObject(),
importObjectAttributesAfterStore().

createObject(): if the object doesn’t exist in database (is not found by


findAmongExistingObjects), it will be created, and all the Ufid attribute of the
object is imported.
importObjectAttributes(): import all attributes of the object
storeObject(): the method storeObject() will call to
PersistenceHelper.manager.store().

importObjectAttributesAfterStore() iimports all attributes that must be


imported after the object is stored.
4. Add an entry to the handlers registry file (<WC_home>\registry\ixb\
handlers\coreX10.xml). The entry specifies the class being imported
(MyObject), XML DTD for core Windchill objects (standardX10.dtd),
and the handler for the class com.ptc.mypackage.ExpImpForMyObject.
An example entry follows:

<elementImporter>
<tag>MyObject</tag>
<dtd>standardX10.dtd</dtd>
<handler>com.ptc.mypackage.ExpImpForMyObject</handler>
</ elementImporter >

Handler for Versioned Object


1. Create a Java class that extends ExpImpForVersionedObject
2. Implement the following methods:
• public Mastered getMaster (IxbElement fileXML):
returns the Object Master if there is any version of the importing
object in the database, otherwise returns null.
• public Versioned createNewObject (IxbElement
fileXML,Importer importer): create a new object with
information from the XML file.
3. Override the following methods if necessary:
public Object importObjectAttributes (Object ob,
IxbElement fileXML,
Importer importer);

public Object importObjectAttributesAfterStore(Object object,


IxbElement fileXML,
Importer importer);

public Object findAmongExistingObjects (IxbElement fileXML,

42-22 Windchill Customizer’s Guide


Importer importer);

Note: An object is imported by the following sequence: createObject(),


importObjectAttributes(), storeObject(),
importObjectAttributesAfterStore().

createObject(): This method is implemented in the class


ExpImpForVersionedObject. The creation of objects will be delegated to
Actor classes, depends on the actor name in the XML file (The actor name is
writen into the XML file by import application). Particular object handlers don’t
have to worry about createObject() and Actor.
importObjectAttributes(): import all attributes of the object that can be
imported before the object is stored.
storeObject(): This method is implemented in the class
ExpImpForVersionedObject. The store of objects will be delegated to Actor
classes, depends on the actor name in the XML file (The actor name is writen into
the XML file by import application). Particular object handlers don’t have to
worry about storeObject() and Actor.
importObjectAttributesAfterStore():import all attributes of the object
that must be imported after the object is stored.
ExpImpForWTPart, ExpImpForDocument, ExpImpForEPMDocument are
examples of import handlers for versioned objects.

4. Add an entry to the handlers registry file (<WC_home>\registry\ixb\


handlers\coreX10.xml). The entry specifies the class being imported
(MyObject), XML DTD for core Windchill objects (standardX10.dtd),
and the handler for the class com.ptc.mypackage.ExpImpForMyObject.
An example entry follows:
<elementImporter>
<tag>MyObject</tag>
<dtd>standardX10.dtd</dtd>
<handler>com.ptc.mypackage.ExpImpForMyObject</handler>
</ elementImporter >

How to Write an Attribute Import Handler


If there is an attribute that is required to be imported the same way for different
classes or if you simply decide to handle it is a separate handler, you can create an
attribute handler. The steps to follow are:
1. Create a Java class that extends AttrExporterImporterTemplate.
2. Override the following methods if needed:

Import Export Framework 42-23


prepareForCheckConflicts(Importer importer): prepares for conflict
checking. It is likely never be implemented by a particular handler.
checkConflictForAttribute(Object existingOb,
IxbElement fileXML,
Importer importer) :
This method does the conflict checking for particular attribute, so if the imported
attribute can potentially have conflicts with an attribute that exists in the database,
this method must be overridden.
importAttribute (Object object,

IxbElement fileXML,

Importer importer):

Retrieves the attribute data from the XML DOM Document and set it to the
imported object. This method must be overridden to suit particular attribute.

42-24 Windchill Customizer’s Guide


Here is an example for importAttribute() for the attribute MyAttr to the
object MyObject:
public Object importAttribute (Object object,
IxbElement fileXML,
Importer importer)
throws WTException{
String myAttr;
try{
myAttr = fileXML.getValue(IxbHndHelper.XML_ATTR_MYATTR);
// XML_ATTR_MYATTR tag must be defined in IxbHndHelper
}
catch (Exception exc){
// The paragraph bellows allows the import process continue,
// even when the import of MyAttr fails. If the programmer
// wants the import process to stop when the import of
// MyAttr fails, please assign ob=null and throw exception
System.out.println(
"Exception when getting MyAttr in importAttribute");
System.out.println("MyAttr attribute is not imported");
return object;
}

MyObject ob = (MyObject) object;


try {
MyObjectHelper.service.setMyAttr(ob, myAttr);
}
catch (Exception e) {
if (! importer.
attributeExporterImporterManager.
overrideConflicts) {
ob = null;
throw e;
}
else{
// override the conflict by doing something here…
}
}
finally{
return ob;
}

Import Export Framework 42-25


Navigating Through an Object’s Structure with ObjectSet
Application
In import/export, a new optional <loadCondition> element under navigation
<rule> element has been added. These rules reside in XML files under
<WT_HOME>\codebase\registry\ixb\object_set_handlers.
The <loadCondition> element will have a fully qualified <className> and
<methodName>. Object Navigation framework will call the specified method
using reflection. The method must be static and must return boolean and must not
have arguments. If the specified method returns a true only then the rule will be
loaded. In case <loadCondition> is not present, the rule will be loaded by default.
If the <loadCondition> element is present, the framework first calls the specified
method to decide if the rule should be loaded or not.
The element looks like :
<loadCondition>

<className>xxxx</className>

<methodName>yyy</methodName>

</loadCondition>

Example:
<loadCondition>

<className>wt.ixb.objectset.ObjectSetHelper</className>

<methodName>isPDMLinkInstalled</methodName>

</loadCondition>

Object Collection
When an object is given to the export process, the ObjectSet application does the
job of navigating through the object's structure and collecting all of its related
objects.
The definition of the navigation is taken from a set of XML files known as
navigation?rule files. Additionally, the ObjectSet application uses Java classes
known as generators and filters to collect a set of objects that will be exported
when simple navigation is not enough and some programming logic needs to be
applied.
The navigation rule files reside in the folder Windchill\codebase\
registry\ixb\object_set_handlers.

Navigating Rules
There are two types of navigating rules: Generator and Filter.

42-26 Windchill Customizer’s Guide


• Generators are rules that are used by the application to traverse through the
object’s structure and get all of its objects to be exported, such as “uses”,
“described by”, “reference”, etc.
• Filters are rules that are applied to objects to be exported to exclude certain
objects from the export process. For example, with “Filter By Time”, we can
choose to export objects that were modified during a specified period. This is
the only out-of-the-box filter currently available.
Available GeneratorIds are defined in XML files in the folder Windchill\
codebase\registry\ixb\object_set_handlers with the tag
<setGenerator>. A list of these Generator Ids can be obtained by calling to
IXBHelper.service.getAllAvaiableGenerators(). The call returns all
available Generators in the system.
IXBHelper.service.getGeneratorList() returns a list of Generators that
will be displayed to the GUI for end-user selection. This helps to hide Generators
that you don’t want the end-user to see. To hide these Generators, the XML files
for these Generators, should have the <display> tag set to false.

Import Export Framework 42-27


For example: a paragraph of XML file for WTPart:
(From “<Windchill>\codebase\registry\ixb\object_set_handlers\
product_struct.xml”)
<setGenerator>
<id>productStructureNavigator</id>
<handler>
wt.ixb.objectset.handlers.navigator.ProductStructureNavigator
</handler>
<dialogClassName>
wt.clients.ixb.exp.NavigatorSearchDialog
</dialogClassName>
<localizedName>
<localizedString>
<class>wt.ixb.objectset.objectSetResource</class>
<key>PRODUCT_STRUCTURE_NAME</key>
</localizedString>
</localizedName>

Tags
<id>: Generator Id

<handler>: Navigator – Java class that helps navigating through the object
structure. In the example, to navigate through WTPart structure.
<dialogClassName> : Java class of the dialog that must be called from the GUI
to search the top-level object of this class in database (in this example, to search
WTPart).

<localizedName> and its sub tags are for internationalization purpose. The
string resource for displaying the Generator to the GUI will be defined in the
.rbInfo file specified by localizedName/localizedString/class and its
key in the .rbInfo file is localizedName/localizedString/key.
If you don’t want this GeneratorId to be displayed to the GUI, but only to be used
programmatically in your application, add the tag <display> like this:

<setGenerator>
<id>productStructureNavigator</id>
<display>false</display>
<handler>
wt.ixb.objectset.handlers.navigator.ProductStructureNavigator
</handler>
<dialogClassName>
wt.clients.ixb.exp.NavigatorSearchDialog
</dialogClassName>
<localizedName>
<localizedString>
<class>wt.ixb.objectset.objectSetResource</class>
<key>PRODUCT_STRUCTURE_NAME</key>
</localizedString>
</localizedName>

42-28 Windchill Customizer’s Guide


Available Filter Id-s are defined in XML files in the folder Windchill\
codebase\registry\ixb\object_set_handlers with the tag
<setFilter>. A list of these Filter Ids can be obtained by calling to
IXBHelper.service.getAllAvaiableFilters(). It returns all
available Filters in the system.
IXBHelper.service.getFilterList() returns a list of Filters that will
be displayed to the GUI for user selection. This function help to hide filters which
you don’t want the end user to see. To hide such Filters, set the value of the
<display> tag to false in the XML files of these Filters.

Note: If the tag <display> is not specified, or set to true, the Generator will be
included in the result of the method
ObjectSetHelper.getListOfObjectSetGenerators() and it will
be displayed in the GUI. If the tag <display> is false, the Generator will not be
included in the result of the method
ObjectSetHelper.getListOfObjectSetGenerators(), and it will
not be displayed to the GUI. To get all Generators in the system, use the method
ObjectSetHelper.getAllAvaiableGenerators().

All the methods get…Generators and get…Filters return Vectors that


contain an element list of the type IXBHandlerDescription. Use getId()
of those elements to get lists of Generators or Filters that are passed as arguments
generatorIds and filterIds for the method doExport() in the
StandardIXBService.

Object Navigation
The mechanism is an XML-rule-driven “navigator” of Windchill objects. Given a
seed (top level) object the mechanism uses specified rules to navigate from object
to object. The navigation can be performed through a DB link, a foreign key, or a
specified method. Here is an example of rule definition of WTPart. The seed is a
Folder object.
(From “<Windchill>\codebase\registry\ixb\object_set_handlers\
product_struct.xml”)
<handler>
wt.ixb.objectset.handlers.navigator.ProductStructureNavigator
</handler>

<schema>

<rule>
<for>wt.part.WTPart</for>
<go>
<byMethod>
<method>navigateFromWTPartToDescribeByDoc</method>
</byMethod>
</go>
</rule>

Import Export Framework 42-29


<rule>
<for>wt.part.WTPartDescribeLink</for>
<go>
<fromForeignKey>
<targetClass>wt.doc.WTDocument</targetClass>
<getMethodName>getDescribedBy</getMethodName>
</fromForeignKey>
</go>
</rule>

</schema>

The example above shows both possible types of navigation: From WTPart it
navigates to wt.part.WTPartDescribeLink by a navigate method and from
there using the method getDescribedBy to get the WTDocument that the
WTPart is described by. Then, non-trivial semantic steps can be made.

After collecting, the objects can be filtered out by a set of defined filters. The filter
definition is stored in the same object set registry. The following is an example of
a date/time filter:
(File: “<Windchill>\codebase\registry\ixb\object_set_handlers\
filter_by_time.xml”)

<setFilter>
<id>filterByTime</id>
<handler>wt.ixb.objectset.handlers.FilterByTime</handler>
<dialogClassName>
wt.clients.ixb.exp.FilterByTimeDialog
</dialogClassName>
<localizedName>
<localizedString>
<class>wt.ixb.objectset.objectSetResource</class>
<key>FILTER_BY_TIME_NAME</key>
</localizedString>
</localizedName>
<parameters>
</parameters>
</setFilter>

The filtering mechanism, as well as the object collection are coupled with the
export application at the level of StandardIXBService. They can be separated.

42-30 Windchill Customizer’s Guide


Adding New Navigators
To implement new Navigator, in most cases you will have to do the following
steps:
1. Implement the XML rule file describing the logic of the navigation. See
<Windchill>\codebase\registry\ixb\object_set_handlers\
product_struct.xml for an example.
2. Implement a subclass of
wt.ixb.objectset.handlers.navigator.GeneralNavigator. You may need to
implement the following methods:
a. public boolean canBeUsedAsTopLevelObject(Persistable obj)
b. public String getTopLevelObjectLocalizedImage(Persistable obj)

Note: You must implement all methods that are specified in the rule files.

Such navigation methods take the object to navigate from as a parameter, and
return Enumeration, which will be added to the export set. For example, if you
specify the following rule:
<byMethod>
<method>navigateFromObject1ToObject2</method>
</byMethod>

Then, you must implement the following Java method:


public Enumeration navigateFromObject1ToObject2 (Persistable ob)
throws WTException

List of Existing Generators and Filters

This appendix provides help for the GUI developer who will be using the IX
Object Collection mechanism by calling:
ObjectSetHelper.computeObjectSetForGivenGeneratorsAndFilters(generatorIds,
generatorParams, filterIds, filterParams);

Import Export Framework 42-31


Examples

Part With all Children

genId[0] = “productStructureNavigator”;
genParams[ 0] = “wt.part.WTPart:6789”;
WTHashSet objects = (WTHashSet) ObjectSetHelper.
computeObjectSetForGivenGeneratorsAndFilters(genIds,
genParams,
new String [0 ],
new String [0 ]);

All Objects in the Cabinet and Folder (Including Subfolders)

genId[0] = genId[ 1] = “folderContent”;


genParams[ 0] = “wt.folder.Cabinet:1865”;
genParams[ 1] = “wt.folder.Subfolder:5674”;
WTHashSet objects = (WTHashSet) ObjectSetHelper.
computeObjectSetForGivenGeneratorsAndFilters(genIds,
genParams,
new String [0 ],
new String [0 ]);

Note: Warning, if there are no filters, you can pass new String[0] for
filterIds and filterParams (Don’t pass null, an exception is thrown)

To get String constants for GUI, see Windchill\codebase\wt\ixb\


objectset\ObjectSetResource.rbInfo.

42-32 Windchill Customizer’s Guide


Generators list
Localized name –
String id Description En (for GUI) Parameters as String

folderContent Collects all objects in Cabinet and Folder <class name: oid>, like:
a given
wt.folder.Subfolder:1234
Cabinet/Folder
or
(including
subfolders) wt.folder.Cabinet: 1234

productStructureNavi Collects all children Product Structure <class name: oid>, like:
gator of a given Part (built with active
wt.part.WTPart:1234 for
Config Spec)
(e.g. Parts, which it the top-level object. This
uses and Documents object must be instance of
which describe it) WTPart
productStructureNavi Collects all children CAD Document <class name: oid>, like:
gatorEPM of a given CAD Structure (built with
wt.epm.EPMDocument:12
Document active config spec)
34 for the top-level object.
This object must be
instance of EPMDocument
productStructureNavi Collects all children Product Structure <class name:oid>, like:
gatorWithEPM of a given Part with CAD
wt.part.WTPart:1234 for
including related documents (built
the top-level object. This
CAD Documents with active Config
object must be instance of
Spec)
WTPart

singleDocument Takes only given Document <class name: oid>, like:


document
wt.doc.WTDocument:1234

Note: actually <class_name:oid> is object local id

Filters list
Localized name – En (for
String id Description GUI) Parameters as String

filterByTime Filters out objects Filter based on modification <timeFrom#timeTo>,


with modification time where timeFrom and
time before/after the timeTo = “null” or
given interval Timestamp.toString()

Import Export Framework 42-33


Examples about Exp/Imp Application:

Export Application
The current Windchill Export out-of-the-box GUI and the
StandardIXBService is an Export Application.

The out-of-the-box Windchill Export GUI is Export Application (client) that calls
export process in StandardIXBService (Export Application (server)) via
IXBHelper.

There are two ways to use it:


With GUI:
IXBExpImpStatus status = IXBHelper.service.doExport(
boolean previewOnly,
String[ ] generatorIds,
String[ ] generatorParams,
String[ ] filterIds,
String[ ] filterParams,
IXBStreamer ruleFile,
String guiId,
boolean detailedLog);

Without GUI:
IXBExpImpStatus status = IXBHelper.service.doExport(
boolean previewOnly,
String[ ] generatorIds,
String[ ] generatorParams,
String[ ] filterIds,
String[ ] filterParams,
IXBStreamer ruleFile,
boolean detailedLog,
String stDtd);

IXBHelper is a class in wt.ixb.clientAccess.

It calls methods doExport(…) of the class StandardIXBService to do export


process.
IXBExpImpStatus is a class in wt.ixb.clientsAccess containing
information about the Exp/Imp process and is used to pass Exp/Imp status
between the server and client.
generatorIds – see definition above.

generatorParams is an array of Object Ids of top-level objects that will be


exported. From the current Exp GUI, those objects will be chosen by using
NavigatorSearchDialog. After the selection is done, this dialog will return a
list of IXBSelectedNavInfo with Navigator Id and Generator Id, and seed
object as an objectId. Given an object obj, we can get the Object Id by using
IXBHelper.service.getObjectId(obj).

42-34 Windchill Customizer’s Guide


filterIds - see definition above

filterParams is an array of objects attributes to set the objects to be excluded


from export process, or to be included in export process, depends on the type of
filters.
ruleFile is the rule file for export process. This file is provided to Exporter to
create a tuner for export process.
guiId is the id of the GUI from which the export process is called. See the
method recordGuiIdInContext() of the class
wt.clients.ixb.util.ExpImpServerRequest for an example how to
create the GUIid.
detailLog indicates whether the status message should be in details or not.

stDtd specifies which version of the Exp/Imp handlers will be used. This is
used to support backward compatible. If stDtd is null or empty (“”), the
STRING_DTD will be calculated based on the current Windchill.
When the method IXBHelper.service.doExport(…) is called, it will call to
the method doExportImpl(…) in the StandardIXBService.

This method:
• Creates a general export handler ExportHandler handler. This is an inner
class of StandardIXBService.
• Gets a list of objects that will be exported by calling:
ObjectSetHelper.computeObjectSetForGivenGeneratorsAndFilters
(
generatorIds,
generatorParams,
filterIds,
filterParams);

• Creates an instance of Exporter, the class that does the export.


• Depending on isPreview (true/false) the exporter will do a preview or
real export by calling methods of Exporter class mention in the section
Exporter class of this document.

• Calls clean-up methods of the ExportHandler handler.

Import Application
The current Windchill Import GUI and StandardIXBService are the Import
Application. The current Windchill Import out-of-the-box GUI is Import
Application client that calls import process in StandardIXBService (Import
Application server) via IXBHelper.

Import Export Framework 42-35


There are two ways to use it:
With GUI:
IXBExpImpStatus status = IXBHelper.service.doImport(
IXBStreamer ruleFile,
IXBStreamer dataFile,
boolean overrideConflicts,
String guiId,
boolean isPreview,
boolean detailedLog,
String creatorName);

Without GUI:
IXBExpImpStatus status = IXBHelper.service.doImport(
IXBStreamer ruleFile,
IXBStreamer dataFile,
boolean overrideConflicts,
boolean isPreview,
boolean detailedLog,
String creatorName,
String stDtd);

IXBHelper is a class in wt.ixb.clientAccess.

It calls methods doImport(…) of the class StandardIXBService to do the


import process.
IXBExpImpStatus is a class in wt.ixb.clientsAccess containing
information about Exp/Imp process and used to pass Exp/Imp status between
server and client.
ruleFile is the rule file for export process. This file is provided to Importer to
create a tuner for import process.
dataFile is the jar file that contains XML files of objects that will be imported.

overrideConflicts specifies whether overridable conflicts must be


overridden or not.
isPreview specifies whether the process should do real import, or check
conflicts and display what objects will be imported.
guiId is the id of the GUI from which the export process is called. See the
method recordGuiIdInContext() of the class
wt.clients.ixb.util.ExpImpServerRequest for an example how to
create the GUIid.
detailLog indicates whether the status message should be in details or not.

42-36 Windchill Customizer’s Guide


creatorName specifies how top-level imported objects (for example
EPMDocument, WTDocument, WTPart) are created.

stDtd specifies which version of Exp/Imp handlers will be used. This is used to
support backward compatible. If stDtd is null or empty (“”), the STRING_DTD
will be calculated based on version of current Windchill system.
When the method IXBHelper.service.doImport(…) is called, it will call to
the method doImportImpl(…) in StandardIXBService.
This method:
• Puts creator name in WTContext to be used by import handler.
• Creates a general import handler ImportHandler handler.
• Gets a list of XML files from the Jar file to be imported by calling
jar.getFileNamesByExtension ("xml");

• Creates an instance of Importer, the class that does the import job.
• Depending on isPreview (true/false), the method doImportImpl(…)
calls the appropriate methods of Importer to do a preview or the real import:
– importer.doImport(stream);
– importer.doPreview(stream);
• The others (importer.doImport(fn, tag) and
importer.doPreview(fn,tag)) are for optimization, and they depend on
how XML files are named. This feature is just for a particular Exp/Imp
Application (wt.clients.ixb and StandardIXBService).
• Sends log messages back to client.

Import Export Framework 42-37


Simple Export Handler Code:
import java.io.File;
import java.io.PrintStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;

import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;

import wt.pom.Transaction;
import wt.content.ApplicationData;
import wt.content.ContentItem;
import wt.content.Streamed;

import wt.ixb.publicforapps.ApplicationExportHandlerTemplate;

import wt.ixb.publicforhandlers.IxbElement;
import wt.ixb.publicforapps.Exporter;
import wt.ixb.publicforapps.IxbHelper;

import wt.ixb.objectset.ObjectSetHelper;

import wt.util.WTException;
import wt.util.WTMessage;

import wt.ixb.clientAccess.IXBJarWriter;

import wt.fc.Persistable;

public class SimpleApplicationExportHandler extends


ApplicationExportHandlerTemplate{

private File targetDir = null;


private PrintStream log = null;

private IXBJarWriter jw = null;


private File resJar = null;
private int fileNum = 0; //counter for exported content files
private HashSet contentFileNames = new HashSet(); //to handle content files with
the same name

public static final String NAME_IS_TAG = "TAG";


public final static String CONTENT_SUBDIR = "CONTENTS";

public SimpleApplicationExportHandler(File tmp_storeDir, PrintStream a_log)


throws WTException{
if (!tmp_storeDir.exists()){
tmp_storeDir.mkdirs();
}
targetDir = tmp_storeDir;

42-38 Windchill Customizer’s Guide


log = a_log;
}

public String storeContent (Object ob) throws WTException


{
String storeName = null;
if(ob instanceof ApplicationData)
{
ApplicationData obj = (ApplicationData)ob;
String fileName = obj.getFileName();

try
{
storeName = this.computeUniqueFileName(fileName);
Streamed sd = (Streamed)obj.getStreamData().getObject();
InputStream is = sd.retrieveStream();
jw.addEntry(is, storeName);

}
catch (IOException ioe)
{

throw new WTException(ioe);


}
}
return storeName;
}

public String storeDocument(IxbElement elem, String dtd)throws WTException


{
try {
String tag = elem.getTag();
String fn = NAME_IS_TAG+"-"+tag+"-"+(fileNum++)+".xml";
File file = new File(targetDir,fn);
FileOutputStream stream= new FileOutputStream (file);
elem.store(stream, dtd); stream.close();

jw.addEntry(file);
file.delete();
}
catch (IOException ioe){
throw new WTException(ioe);
}
}

public void storeLogMessage(String resourceBundle, String messageKey, Object[]


textInserts)
throws WTException{
WTMessage m = new WTMessage(resourceBundle, messageKey, textInserts);
String s = m.getLocalizedMessage();
log.println(s);
}
public void storeLogMessage(String resourceBundle, String messageKey, Object[]
textInserts, int importanceLevel)
throws WTException{
storeLogMessage (resourceBundle, messageKey, textInserts);

Import Export Framework 42-39


}

public void exportObjectContent (Object obj, Exporter exporter, ContentItem item,


String exportFileName)
throws WTException {
if (item instanceof ApplicationData) {
ApplicationData ad = (ApplicationData) item;
Streamed streamedIntfc = (Streamed) ad.getStreamData().getObject();
try{
InputStream is = streamedIntfc.retrieveStream();
jw.addEntry(is, exportFileName);
}
catch (IOException ioe){
throw new WTException(ioe);
}
}
}
private String computeUniqueFileName (String fn) throws IOException {
//compute file name in jar (should be unique)
if (contentFileNames.contains(fn)) {
// if simple content's name already has been used then look for
// name in form name-123.ext
// As a result will have names like: design.doc, design-23.doc, design-
57.doc, ...
int i = fn.lastIndexOf('.');
String fn_n = ( i>0 ? fn.substring(0, i) : fn);
String fn_t = ( i>0 ? fn.substring(i+1) : "" );
while (true) {
fn = (i>0 ?
fn_n + '-' + (fileNum++) + '.' + fn_t :
fn_n + '-' + (fileNum++)
);
if (!contentFileNames.contains(fn)) break;
}
}
contentFileNames.add(fn);
String fnInJar = CONTENT_SUBDIR + "/" + fn;
return fnInJar;
}

public File doExport( WTContainerRef container,


String[] generatorIds,
String[] generatorParams,
String[] filterIds,
String[] filterParams,
File ruleFile,
File policyFile,
String actionName,
String stDtd,
File resultingJar)
throws WTException{

//init jar file


resJar = resultingJar;
try{
jw = new IXBJarWriter(resultingJar);
}

42-40 Windchill Customizer’s Guide


catch (IOException ioe){
throw new WTException(ioe);
}

//adopt incoming rule file


IxbElement clientSettingsElement = null;
if (ruleFile!=null) {
try{
InputStream clientSettingsStream = new FileInputStream(ruleFile);
clientSettingsElement = IxbHelper.newIxbDocument(clientSettingsStream,
false);
}
catch(IOException ioe){
throw new WTException(ioe);
}
}

//create exporter
Exporter exporter = null;
if ( policyFile==null ) { // policy rule is null; export action is expected
...
exporter = IxbHelper.newExporter(this, container, IxbHelper.STANDARD_DTD,
clientSettingsElement, null, actionName);
}
else{
exporter = IxbHelper.newExporter (this, container,
IxbHelper.STANDARD_DTD, clientSettingsElement, policyFile, null );
}

//gen set of items to export


Set res = ObjectSetHelper.computeObjectSetForGivenGeneratorsAndFilters
(generatorIds, generatorParams, filterIds, filterParams);

Iterator iter = res.iterator();

Transaction trx = new Transaction();


try {
if ( !(actionName != null &&
actionName.equals(wt.ixb.tuner.ExportActionHelper.NO_ACTION_CMD) )){
trx.start();
}
while (iter.hasNext()) {
Persistable ob = (Persistable)iter.next();
exporter.doExport(ob);

}
exporter.finalizeExport();
if ( !(actionName != null &&
actionName.equals(wt.ixb.tuner.ExportActionHelper.NO_ACTION_CMD) )){
trx.commit();
}
trx = null;
}
finally {
if (trx != null) {

Import Export Framework 42-41


if ( !(actionName != null &&
actionName.equals(wt.ixb.tuner.ExportActionHelper.NO_ACTION_CMD) )){
trx.rollback();
}
trx = null;
}
}
try{
jw.finalizeJar();
}
catch(IOException ioe){
throw new WTException (ioe);
}

return resJar;

}
}

42-42 Windchill Customizer’s Guide


Simple Import Handler Code:

import java.io.File;
import java.io.PrintStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;

import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;

import wt.pom.Transaction;

import wt.content.ApplicationData;
import wt.content.ContentItem;
import wt.content.Streamed;

import wt.ixb.publicforapps.ApplicationImportHandlerTemplate;

import wt.ixb.publicforhandlers.IxbElement;
import wt.ixb.publicforhandlers.IxbHndHelper;
import wt.ixb.publicforapps.IxbDocument;
import wt.ixb.publicforapps.Importer;
import wt.ixb.publicforapps.IxbHelper;

import wt.ixb.objectset.ObjectSetHelper;

import wt.ixb.actor.actions.IxbActionsHelper;

import wt.util.WTException;
import wt.util.WTMessage;

import wt.ixb.clientAccess.IXBJarReader;

import wt.fc.Persistable;

import javax.xml.transform.stream.StreamSource;

public class SimpleApplicationImportHandler extends


ApplicationImportHandlerTemplate{

private IXBJarReader jr = null;


private PrintStream log = null;

public SimpleApplicationImportHandler(PrintStream a_log){


log = a_log;

}
public InputStream getContentAsInputStream (String contentId)
throws WTException {
try{
return jr.getStreamByName (contentId);

Import Export Framework 42-43


}
catch(IOException ioe){
throw new WTException(ioe);
}
}
public void storeLogMessage(String resourceBundle, String messageKey, Object[]
textInserts)
throws WTException{
WTMessage m = new WTMessage(resourceBundle, messageKey, textInserts);
log.println(m.getLocalizedMessage());
}
public void doImport(WTContainerRef container,
File ruleFile,
File dataFile,
boolean _overrideConflicts,
String actorName,
File policyFile,
File containerMappingFile)
throws WTException{

try{
jr = new IXBJarReader(dataFile);
}
catch(IOException ioe){
throw new WTException (ioe);
}
//prepare rule file
String ruleFileName = (ruleFile!=null)? ruleFile.getAbsolutePath(): null;

//prepare container mapping file


String containerMappingFileName =
(containerMappingFile!=null)?containerMappingFile.getAbsolutePath(): null;

//prepare policy file


String policyFileName = (policyFile!=null)?policyFile.getAbsolutePath():
null;

StreamSource xslPolicyFile = null;


if (policyFile!=null) {
xslPolicyFile = new StreamSource(policyFile.getAbsolutePath());
}
Boolean overrideConflicts = new Boolean (_overrideConflicts);
Importer importer = IxbHelper.newImporter(this,
container,
IxbHelper.STANDARD_DTD,
ruleFileName,
policyFileName,
containerMappingFileName,
actorName,
overrideConflicts,
null /*validate*/);

String [] fns = jr.getNonContentFileNamesByExtension ("xml");

boolean validate = IxbHndHelper.getIxbProperty("import.parser.validate",


false);

42-44 Windchill Customizer’s Guide


for (int i=0; i<fns.length; i++) {

String fn = fns[i];
InputStream stream = null;
try{
stream = jr.getStreamByName (fns[i]);
}
catch (IOException ioe){
throw new WTException (ioe);
}
IxbDocument doc = IxbHelper.newIxbDocument(stream, validate);

//if policyFile == null, apply actorName to XML Document before pass it to


importer
if (policyFile == null){
IxbElement rootElem = doc.getRootElement();
//XML_ACTION_KEY = "actionInfo/action"
IxbElement actionElement =
doc.getElement(IxbActionsHelper.XML_ACTION_KEY);
if (actionElement == null){
rootElem.addValue(IxbActionsHelper.XML_ACTION_KEY, actorName);
}
else {
rootElem.removeChildElement( actionElement);
rootElem.addValue(IxbActionsHelper.XML_ACTION_KEY, actorName);
}
}
else { //apply policy file
doc =
IxbActionsHelper.writeActionAndParametersToFileXML(doc,xslPolicyFile);
}
//set elem ready for import
importer.doImport(doc);
}

//perform actual import


importer.finalizeImport();
}

Import Export Framework 42-45


Product Design eXchange (PDX) Support for Export
Product Design eXchange (PDX) is a file format used for sharing of product
design data between business partners. This allows you to share information about
Documents, Parts, Product Structure and Bill of Materials (BOM).
You can export data from Windchill to PDX format including Agile. You can
customize to export of BOM data to PDX format.
The OOTB PDX export allows you to export:
• Documents
• Parts
• EPM Documents

Sample prodcut structure in Windchill system

Corresponding PDX output as seen in PDXplorer

42-46 Windchill Customizer’s Guide


Customization Points
Required artifacts
• Class files: wt.ixb.pdx.*
• XSL path used for transformation : <WT_HOME>codebase\registry\ixb\pdx
• DTD path: <WT_HOME>codebase\registry\ixb\pdx\dtds
Default behavior
• By default it would be Agile compatible.
• By default:
– “Agile_07.dtd“ and “wcxml2pdx_agile.xsl” would be the respective dtd
and xsl corresponding to Agile format.
– “IPC_2571.dtd” and “wcxml2pdx.xsl” would be the respective dtd and
xsl corresponding to PDX format.
Overridable properties for wt.properties
• pdx.export.dtdFilePath=$(wt.home)$(dir.sep)codebase$(dir.sep)registry$(dir.sep
)ixb$(dir.sep)pdx$(dir.sep)dtds$(dir.sep) Agile_07.dtd
• pdx.export.xslFilePath=$(wt.home)$(dir.sep)codebase$(dir.sep)registry$(dir.sep
)ixb$(dir.sep)pdx$(dir.sep) wcxml2pdx_agile.xsl
• pdx.AgileCompatible=true
• pdx.debug.enable=false
The xsl may also be modified as per requirement or to support PDX export of
other exportable windchill objects.

Supported APIs
• ExportPackage exportPackage =
ExportPackageForPDX.createExportPackageForPDX(…)
• PDXExportHelper.doExportToPDX(…)

createExportPackageForPDX
There are four static public APIs (createExportPackageForPDX) in
ExportPackageForPDX to support this functionality.

public static wt.ixb.objectset.ExportPackage createExportPackageForPDX(

java.lang.String name, java.lang.String description,


java.lang.String exporter, java.lang.String[] generIds,
java.lang.String[] generParams, java.lang.String[] filterIds,
java.lang.String[] filterParams) throws wt.util.WTException

Import Export Framework 42-47


Purpose: Creates ExportPackage holding all information necessary for export in
PDX format. The objects are collected using standard ixb collection mechanism
(generators and filters).
Parameters:
• name – Name of the export package
• description - Description of the export package
• exporter - Name of the user who makes export
• generIds - Array of String id for object set generator types, e.g.
{"singleDocument", "productStructureNavigatorWithEPM"}
• generParams - Array of local id for the corresponding seed objects
• filterIds - Array of String id for object set filters
• filterParams - Array of Strings representing parameters for filtering
Throws:
• wt.util.WTException

public static wt.ixb.objectset.ExportPackage createExportPackageForPDX(

wt.inf.container.WTContainerRef container, java.lang.String name,


java.lang.String description, java.lang.String exporter,
java.lang.String[] generIds, java.lang.String[] generParams,
java.lang.String[] filterIds, java.lang.String[] filterParams)
throws wt.util.WTException

Purpose: Creates ExportPackage holding all information necessary for export in


PDX format. The objects are collected within a container using standard ixb
collection mechanism (generators and filters).
Parameters:
• container - Object reference of container holding objects to export
• name – Name of the export package
• description - Description of the export package
• exporter - Name of the user who makes export
• generIds - Array of String id for object set generator types, e.g.
{"singleDocument", "productStructureNavigatorWithEPM"}
• generParams - Array of local id for the corresponding seed objects
• filterIds - Array of String id for object set filters
• filterParams - Array of Strings representing parameters for filtering

42-48 Windchill Customizer’s Guide


Throws:
• wt.util.WTException

public static wt.ixb.objectset.ExportPackage createExportPackageForPDX(

java.lang.String name, java.lang.String description,


java.lang.String exporter, java.lang.String[] generIds,
java.lang.String[] generParams) throws wt.util.WTException

Purpose: Convenience method for the common case when objects are collected
without filtering
Parameters:
• name – Name of the export package
• description - Description of the export package
• exporter - Name of the user who makes export
• generIds - Array of String id for object set generator types, e.g.
{"singleDocument", "productStructureNavigatorWithEPM"}
• generParams - Array of local id for the corresponding seed objects
Throws:
• wt.util.WTException

public static wt.ixb.objectset.ExportPackage createExportPackageForPDX(

wt.inf.container.WTContainerRef container, java.lang.String name,


java.lang.String description, java.lang.String exporter,
java.lang.String[] generIds, java.lang.String[] generParams)
throws wt.util.WTException

Purpose: Convenience method for the common case when objects are collected
within a container without filtering
Parameters:
• container - Object reference of container
• name – Name of the export package
• description - Description of the export package
• exporter - Name of the user who makes export
• generIds - Array of String id for object set generator types, e.g.
{"singleDocument", "productStructureNavigatorWithEPM"}

Import Export Framework 42-49


• generParams - Array of local id for the corresponding seed objects
Throws:
• wt.util.WTException

doExportToPDX

public static void doExportToPDX(

ExportPackageForPDX expPackage, String attachmentOption,


File dirToSave, String zipName)
throws wt.util.WTException

Purpose: Creates pdx file on server.


Parameters:
• container - Source container
• expPackage - Export package
• attachmentOption - Attachments option. Possible values are:
– PDXExportHandler.XML_VALUE_ATTACHMENTS - content files are
included into pdx package (default option)
– PDXExportHandler.XML_VALUE_NO_ATTACHMENTS - content
files are ignored (not mentioned in pdx.xml)
– PDXExportHandler.XML_VALUE_ATTACHMENTS_AS_FILE_NAME
S - content files are mentioned in pdx.xml but are not included into zip
• dirToSave - directory on server where the resulting pdx file will be stored
• zipName - name for the resulting pdx file (pass name without extension since
extension '.pdx' is added)
Throws:
• wt.util.WTException

42-50 Windchill Customizer’s Guide


public static void doExportToPDX(

ExportPackageForPDX expPackage, java.lang.String


java.io.File dirToSave, attachmentOption,
throws wt.util.WTException java.lang.String zipName)

Purpose: Creates pdx file on server.


Parameters:
• expPackage - Export package
• attachmentOption - Attachments option. Possible values are:
– PDXExportHandler.XML_VALUE_ATTACHMENTS - content files are
included into pdx package (default option)
– PDXExportHandler.XML_VALUE_NO_ATTACHMENTS - content
files are ignored (not mentioned in pdx.xml)
– PDXExportHandler.XML_VALUE_ATTACHMENTS_AS_FILE_NAME
S - content files are mentioned in pdx.xml but are not included into zip
• dirToSave - directory on server where the resulting pdx file will be stored
• zipName - name for the resulting pdx file (pass name without extension since
extension '.pdx' is added)
Throws:
• wt.util.WTException

Sample Program

Preparing Data to Export


File dir = new File(dirToSave);
WTCollection seedParts = // Get List of Parts as seed
if(!seedParts.isEmpty()) {
String [] genIds = new String[seedParts.size()];
String [] genParams = new String[seedParts.size()];
Iterator<WTReference> it = seedParts.referenceIterator();
int i = 0;
while(it.hasNext()) {
genIds[i] = "productStructureNavigator";
genParams[i] = it.next().toString();
i++;
}
WTContainerRef sourceContainer = WTContainerRef.newWTContainerRef(container);

Import Export Framework 42-51


Export to PDX Format
ExportPackage exportPackage =
ExportPackageForPDX.createExportPackageForPDX(“name_of_exp_package", “description",
“author", genIds, genParams);

PDXExportHelper.doExportToPDX(sourceContainer,(ExportPackageForPDX)exportPackage,
PDXExportHandler.XML_ATTR_ATTACHMENTS_OPTION, dir, "zipName");

42-52 Windchill Customizer’s Guide


43
Evolvable Classes

This chapter describes evolvable classes.

Topic Page
Background Information ...................................................................................43-3
General Externalization Guidelines...................................................................43-4
Hand-coded Externalization Guidelines............................................................43-4
Migration Guidelines for Classes with Hand-coded Externalization................43-5
Examples of Generated Externalization Code for Evolvable Classes...............43-6

43-1
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.
During the migration period (that is, at Windchill Release 4.0), all Externalizable
classes have the methods necessary to manage class compatibility but, in the
future, only Evolvable classes will have these features. 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. This
property is on the Windchill tab of the class specification in Rose.

43-2 Windchill Customizer’s Guide


Background Information
As of Release 4.0, 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.

Evolvable Classes 43-3


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

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 non-
transient, persistent fields of the class. (This occurrence should be rare.)
• Do not model a serialVersionUID attribute with a value other than 1 as this
disallows the ability to read old versions of the class.

43-4 Windchill Customizer’s Guide


Migration Guidelines for Classes with 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 on the Windchill tab of the class specification in
Rose 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().

Evolvable Classes 43-5


Examples of Generated Externalization Code for Evolvable
Classes
This section contains examples of generated externalization code for evolvable
classes.

Example of 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 uid

X-10 = 6676079877272797361L

*/

//##end version.uid

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

//##end writeExternal%writeExternal.body

43-6 Windchill Customizer’s Guide


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

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

Evolvable Classes 43-7


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 ) // if not doing backward compatibility

super.readExternal( input ); // handle super class

a1 = (String)input.readObject();

a2 = (Date)input.readObject();

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

43-8 Windchill Customizer’s Guide


Example of a readOldVersion Method
This method is generated virtually the same as readVersion
<EXTERBALIZATION_VERSION_UID> to support backward compatibility
with the pre-R4 stream format. 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();
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 stream-

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

Evolvable Classes 43-9


" + readSerialVersionUID
+ " local class externalizationVersionUID=
" + EXTERNALIZATION_VERSION_UID );

return success;

//##end readOldVersion%readOldVersion.body

43-10 Windchill Customizer’s Guide


44
Creating Large Objects (LOBs)

This chapter describes how to create large objects (LOBs).

Topic Page
Creating Large Objects (LOBs) ........................................................................44-2

44-1
Creating Large Objects (LOBs)

Modeling Large Objects


You can model an attribute to be a binary large object (BLOB) in one of the
following four ways:
• By default when the attribute type is a class that does not map to any of the
other java.sql.Types.
• Explicitly set the attribute’s class to LobLocator. Use this technique for large
objects that you access infrequently.
• Model the attribute to map to a SMALLBLOB by changing the ColumnType
property under the Windchill tab of the attribute specification. Use this
technique for objects that can expand and contract, but are never more than a
certain size.
• Model the attribute to map to an INLINEBLOB by changing the ColumnType
property under the Windchill tab of the attribute specification. Use this
technique for objects that can expand and contract, and are typically small in
size, but occasionally require large storage size (such as, adhoc ACLs).

DDL Generation
The DDL generated by Windchill defines the BLOB columns to be stored in their
own tablespace. This can be controlled for each attribute by changing the
tablespace property under the Windchill tab while modeling. The tablespace must
be defined before the DDL is executed. The name of the default tablespace to
contain BLOBs can be modified using a property in the user.properties file. See
the properties.html file for details on the specific property.

Note: Both Oracle and SQLServer support this tablespace feature. SQLServer
terminolgy refers to this concept as FileGroups.

Reading and Writing LOBs


BLOBs are either read or written as byte arrays or as Serialized objects each time
the object containing the BLOB is read, created, or updated. If the BLOB is
modeled using LobLocator, then only the LOB locator is retrieved with each
read/write and a second step is required to retrieve or store the LOB. The
StandardPersistenceManager provides getLob() and updateLob() to perform these
operations.
Be careful about the types of objects that you serialize into the database. Using
default Java serialization is especially prone to breaking if the Java class files are
recompiled with possible changes, or sometimes just with different compilers.
Programming to allow upward compatibility of serialized representations is
difficult. One technique is as follows:

44-2 Windchill Customizer’s Guide


1. Make the class Externalizable, which aids performance as well.
2. Specify a fixed serialVersionUID value.
3. Put an internal version number on the object stream and handle version
changes in code.
See the code-generated Externalizable business classes for an example of this
technique. The disadvantage is that all subclasses are now Externalizable and
require readExternal and writeExternal methods. You can use the same type of
technique with Serializable (fix serialVersionUID and implement
read/writeObject) if independence from the class hierarchy is important.

Small BLOBs
SMALLBLOBs are encoded into Strings before being stored and are mapped to
VARCHAR2(4000) rather than BLOB. Because of the size limitation of 4,000
characters, this option is inflexible and should be used with caution. Your code
should be prepared to handle the possible exception that is thrown if the size of the
attribute grows beyond what can be encoded into 4,000 characters.

Inline BLOBs
INLINEBLOBs combine the features of SMALLBLOB and BLOB to provide
better performance when data is small, but still allow for large data storage
capability. An attribute that is stored as an INLINEBLOB uses two columns:
• A VARCHAR2(4000) column
• A BLOB column
Each object is examined at runtime and, when the data is small enough, it is stored
in the VARCHAR(4000) column; otherwise, it is stored in the BLOB column.
When the data is stored in the VARCHAR(4000) column, no additional datastore
calls are required to read the BLOB data.
Using an INLINEBLOB introduces a fixed cost in terms of storage (two columns
are used instead of one) and additional processing at runtime. However, when the
majority of data is stored “inline” with the table, this cost is negligible in
comparison to the performance benefits. If most of the data exceeds the 4000-byte
limit, BLOB storage is probably more appropriate. However, if it is known that all
data will never exceed the 4000-byte limit, SMALLBLOB should be used.

Creating Large Objects (LOBs) 44-3


Example
An example follows, which uses the classes shown in the following figure.

/*
*
* Lobber is an example of storing BLOBs. BlobClass has three BLOBs:
* imablob which is LobLocator, and imasmallblob, and imanothersmallblob
* which are
*
*/

public class Lobber {

private static final int size = 1000;


private static BlobClass atr = null;
private static Enumeration lob_files;

public static void goLobs( String lob_dir ) {

try {

// create a BlobClass object

lob_files = getLobFiles( lob_dir );

// loop thru the files in this directory


if ( lob_files != null ) {
if ( lob_files.hasMoreElements() ) {
try {
String lobIt = (String)lob_files.nextElement();
File lobFile = new File(lobIt);

long len = lobFile.length();


System.out.println( "file length "+len );
InputStream aIs = new FileInputStream(lobFile);

44-4 Windchill Customizer’s Guide


System.out.println( "bytes available on this
InputStream "+aIs.available());

atr = createBlobClassRec(lobIt);

Transaction trx = new Transaction();


trx.start();
// save the class containing the LOB
atr = (BlobClass)
PersistenceHelper.manager.save(atr);

// Save a LOB of unknown length. Note that


// PersistenceServerHelper is used
// rather than PersistenceHelper. This
// is server side only code.

long theLength =
(long)PersistenceServerHelper.manager.updateLob(
(Persistable)atr,
atr.getImablob(),
aIs,
false );
// save a LOB of known length
len = lobFile.length();
System.out.println( "file length "+len );
aIs = new FileInputStream(lobFile);
System.out.println( "bytes available on
this InputStream "+aIs.available());

PersistenceServerHelper.manager.updateLob(
(Persistable)atr,
atr.getImablob(),
aIs,
len,
false );
trx.commit();
trx = null;
aIs.close();

}
catch ( FileNotFoundException fnf )
{ fnf.printStackTrace();}
catch ( IOException ioe )
{ioe.printStackTrace();}
finally {
if ( trx != null ) {
trx.rollback();
throw new RuntimeException("Error
processing lobs");
}
}
}
}

}
catch (WTException WTe) {
WTe.printStackTrace();

Creating Large Objects (LOBs) 44-5


}
}

private static Enumeration getLobFiles( String ldir ) {

String[] s_files = null;


Vector aVec = new Vector();
File lob_dir = new File( ldir );

if ( !lob_dir.isDirectory() )
return null;

s_files = lob_dir.list();
for ( int i=0; i
for ( int i=0; i

44-6 Windchill Customizer’s Guide


45
Customizing Data Formats

This chapter explains how to customize data formats.

Topic Page
Adding and Updating Data Formats for Content Holders.................................45-2

45-1
Adding and Updating Data Formats for Content Holders
When content files are added to a content holder object, the format of the file
(based on the file name extension) is set automatically upon upload. The available
formats are stored as DataFormat objects in the system.
In some cases, you may need to augment or change the existing data formats to
accommodate additional MIME types associated with your enterprise data.

Note: Any changes made to existing data formats should be treated as


customizations to your code. Be sure to follow the coding practices introduced in
the Managing Customizations chapter on page 5-1.

A data format:
• Sets the MIME type when a file is downloaded.
• Supplies the icon that will represent the object in browser displays.
• Informs the user of the file format.
You can use a command-line utility, provided by Solution Name, to maintain data
format objects.

Adding Data Formats


Use the following command to add a data format to the system:
java wt.content.DataFormatUtil -add

You are then prompted to provide values for the following attributes:

Attribute Description

Format name (required) Displays this name (for example, Microsoft Word) in the client to
identify the file format. The value specified must be unique.

MIME type (required) The MIME type (for example, application/msword) to be used in
downloading a file of this type. You must specify a space-separated
list of valid extensions for the MIME type (for example, .txt, .text, or
.t). This is the way in which the format of these objects will be set
when a file is uploaded.

Description (optional) Describes this data format object.

Indexable (required) Indicates whether or not this data format type can be indexed. Most
MIME types supported are defined in the system when it is installed.
However, any simple text format is indexable.

45-2 Windchill Customizer’s Guide


Attribute Description

Icon (required) Defines the path to a subdirectory of the codebase that contains the
icon for this format type. When you add a data format type, you have
the option to reference an icon other than one of those found in the
Solution Name codebase. However, you must ensure that the pixel
size for your icon is 16 x 16 to avoid an error when viewing icons.

Extensions (required) Defines the extensions that are associated with this particular mime
type (for example, .doc or .rtf for Microsoft Word).

After adding a new format for a MIME type using DataFormatUtil, you must add
a new line for that format to the wt\content\FormatNameRB.rbinfo file and then
run the ResourceBuild utility to generate resource classes from
FormatNameRB.rbinfo file. Enter the new line using the following format:
<Mime_Type>.value=<Display_Value>

For example, if the MIME type is Java Archive and display value desired is Java
Archive File, then new entry is as follows:
Java Archive.value=Java Archive File

For details on using the ResourceBuild utility, see the System Generation chapter
on page 32-1.

Updating Data Formats


Enter the following command to update an existing data format:
java wt.content.DataFormatUtil -update

The tool prompts you for the format name of an existing data format object. After
you have identified the data format, you can update its attributes.
If you make a change to the MIME type name or display value, you must also
update the corresponding line in the wt\content\FormatNameRB.rbinfo file.

Note: If you change the MIME type of a data format object, you must stop and
restart the method server to implement the change.

Listing Available Data Formats


Enter the following command to display a list of existing data format objects and
their attributes:
java wt.content.DataFormatUtil -list

Renaming a Data Format


Enter the following command to rename a data format:
java wt.content.DataFormatUtil -rename

Customizing Data Formats 45-3


The tool prompts for the format name of an existing data format object. After the
data format is identified, the tool will prompt for a new name for the data format.

Deleting a Data Format


Enter the following command to delete a data format:
java wt.content.DataFormatUtil -delete

The tool prompts for the format name of an existing data format object. After the
data format is identified, it gets deleted. If any object currently refers to this data
format, then data format is not deleted and error is shown.

45-4 Windchill Customizer’s Guide


V
Customization Appendices
Section

Chapter Page
Extendable Classes in the Windchill Supported API............................ A-1
Multi-Object Conversion Guidelines .................................................... B-1
Creating Non-Modeled Services for Listening ..................................... C-1
Windchill Profiler ................................................................................. D-1
Additional Topics - Client Customization .............................................E-1
A
Extendable Classes in the
Windchill Supported API

This appendix lists many of the extendable classes and implementable interfaces
in the Windchill supported API. It serves as a roadmap to help guide developers
when initiating modeling activities. Further information about these classes can be
found throughout this manual, and in the Windchill Javadoc.
Many Windchill objects and features can be tailored without programmatic
customization. For more information on these options, see the Customization
Overview on page 1-1. Additional information can also be found in the Windchill
System Administrator's Guide, and the Windchill Business Administrator's Guide.

Topic Page
PDM Business Information Classes ...................................................................A-2
Enterprise Business Information Classes ...........................................................A-2
Windchill Services .............................................................................................A-2
Foundation Classes.............................................................................................A-3
PDM Auxiliary Business Information Classes...................................................A-3
Business Logic Classes ......................................................................................A-3
Server Development Classes ..............................................................................A-4
Client Development Classes...............................................................................A-5

A-1
PDM Business Information Classes
Following are the starting points for extending PDM objects (part, document, and
change objects). If you want to extend the behavior of the Windchill out-of-the-
box PDM objects, start by extending these classes. For an overview of these
classes, see the The Enterprise Layer chapter on page 37-1.
wt.change2.WTAnalysisActivity
wt.change2.WTChangeActivity2
wt.change2.WTChangeInvestigation
wt.change2.WTChangeIssue
wt.change2.WTChangeProposal
wt.change2.WTChangeRequest2
wt.doc.WTDocument
wt.doc.WTDocumentMaster
wt.part.WTPart
wt.part.WTPartMaster

Enterprise Business Information Classes


To create new business classes (other than the PDM classes described above), the
following enterprise classes provide a good base from which to start:
wt.enterprise.FolderResident
wt.enterprise.IteratedFolderResident
wt.enterprise.Managed
wt.enterprise.RevisionControlled
wt.enterprise.Simple

Windchill Services
The following extendable classes represent the Windchill plug-and-play
interfaces. For more information, see the Windchill Services chapter on page
31-1.
wt.change2.Changeable2
wt.content.ContentHolder
wt.content.FormatContentHolder
wt.folder.Foldered
wt.folder.IteratedFoldered
wt.index.Indexable
wt.locks.Lockable
wt.ownership.Ownable
wt.vc.baseline.Baselineable
wt.vc.Iterated
wt.vc.Mastered
wt.vc.Versioned
wt.vc.views.ViewManageable
wt.vc.wip.Workable

A-2 Windchill Customizer’s Guide


Foundation Classes
For an overview, see the Modeling Business Objects chapter on page 4-1,
specifically the Windchill Foundation Abstractions section on page 4-8.
wt.fc.BinaryLink
wt.fc.IdentificationObject
wt.fc.Identified
wt.fc.Item
wt.fc.Link
wt.fc.NetFactor
wt.fc.ObjectMappable
wt.fc.ObjectReference
wt.fc.ObjectToObjectLink
wt.fc.Persistable
wt.fc.QueryKey
wt.fc.SemanticKey
wt.fc.UniquelyIdentified
wt.fc.WTObject
wt.fc.WTReference

PDM Auxiliary Business Information Classes


The following extendable classes provide some of the basic functionality of the
PDM business information classes.
wt.vc.ObjectToVersionLink
wt.vc.struct.IteratedDescribeLink
wt.vc.struct.IteratedReferenceLink
wt.vc.struct.IteratedUsageLink
wt.VersionToVersionLink

Business Logic Classes


Following are extendable business logic classes:
wt.eff.DateEff
wt.eff.DisplayIdentificationEffConfigurationItemDelegate
wt.eff.Eff
wt.eff.EffConfigurationItem
wt.eff.EffContext
wt.eff.EffGroupRangeDelegate
wt.eff.EffManagedVersion
wt.eff.EffRange
wt.eff.IncorporationDate
wt.eff.LeftFilledStringEff
wt.eff.StringEff
wt.eff.ValidEffsDelegate
wt.effectivity.DatedEffectivity
wt.effectivity.Effectivity
wt.effectivity.UnitEffectivity
wt.part.BOMHierarchyVisitor
wt.part.BOMPartsListVisitor
wt.part.HtmlHeadingHierarchyVisitor
wt.part.HtmlNumberedHierarchyVisitor
wt.part.HtmlPreformattedHierarchyVisitor

Extendable Classes in the Windchill Supported API A-3


wt.part.HtmlPreformattedPartsListVisitor
wt.series.HarvardSeries
wt.series.IntegerSeries
wt.series.MulticharacterSeries
wt.series.MultilevelSeries
wt.series.Series
wt.vc.baseline.Baseline
wt.vc.baseline.BaselineVisitor
wt.vc.baseline.ManagedBaseline
wt.vc.config.ConfigSpec
wt.visitor.BasicNodeExpander
wt.visitor.CompositeVisitor
wt.visitor.ConfigSpecNodeExpander
wt.visitor.Expander
wt.visitor.NodeExpander
wt.visitor.NodeExpandInfo
wt.visitor.RoleExpandInfo
wt.visitor.TextOutputVisitor
wt.visitor.Visitor
wt.visitor.VisitorAdapter
wt.visitor.Walker

Server Development Classes


Following are extendable server development classes:
wt.cache.CacheManager
wt.doc.DocumentContentProcessing
wt.doc.DocumentDelegate
wt.doc.WTDocumentDelegate
wt.events.KeyedEvent
wt.events.KeyedEventBranch
wt.events.KeyedEventListener
wt.events.KeyedEventListenerAdapter
wt.feedback.ProgressCountFeedback
wt.feedback.StatusFeedback
wt.feedback.WTContextUpdate
wt.httpgw.HTTPAuthentication
wt.pom.TransactionListener
wt.util.CollationKeyFactory
wt.util.WTThread

A-4 Windchill Customizer’s Guide


Client Development Classes
Following are extendable client development classes:
wt.clients.beans.AssociationsLogic
wt.clients.beans.EffectivityTaskLogic
wt.clients.beans.explorer.WTBusinessObject
wt.clients.beans.selectors.ComponentDelegate
wt.clients.change2.WTChangeIssueTaskDelegate
wt.clients.change2.WTChangeOrder2TaskDelegate
wt.clients.change2.WTChangeRequest2TaskDelegate
wt.clients.doc.WTDocumentTaskDelegate
wt.clients.effectivity.ConfigurationItemTaskDelegate
wt.clients.folder.SubFolderTaskDelegate
wt.clients.homepage.WindchillHome
wt.clients.prodmgmt.HelperPanel
wt.clients.prodmgmt.PartItem
wt.clients.prodmgmt.PartMasterItem
wt.clients.util.ReferenceHolder
wt.clients.util.TaskDelegateException
wt.clients.vc.AlreadyCheckedOutException
wt.clients.vc.CheckedOutByOtherException
wt.clients.vc.CheckInOutException
wt.clients.vc.NotCheckedOutException
wt.identity.DisplayIdentification
wt.identity.DisplayIdentificationDelegate
wt.identity.DisplayIdentificationPersistableDelegate
wt.identity.DisplayIdentificationStandardDelegate
wt.identity.DisplayIdentificationStandardVersionedDelegate
wt.identity.DisplayIdentificationVersionedDelegate
wt.identity.DisplayIdentity
wt.identity.StandardDisplayIdentity
wt.identity.VersionedDisplayIdentity
wt.util.LocalizableMessage

Extendable Classes in the Windchill Supported API A-5


A-6 Windchill Customizer’s Guide
B
Multi-Object Conversion
Guidelines

Topic Page
Conversion Overview......................................................................................... B-2
API Guidelines ................................................................................................... B-3
Collections Guidelines ....................................................................................... B-7
Event Dispatch Guidelines ................................................................................. B-9
Multi-Object Delegation Guidelines ................................................................ B-10
Multi-Object Exceptions Guidelines ................................................................ B-11
Multi-Object CRUD API Guidelines ............................................................... B-13
Batch Update/Delete Guidelines ...................................................................... B-13
Transaction Context/Listener Guidelines......................................................... B-14
Neat Tips and Tricks ........................................................................................ B-15

B-1
Conversion Overview

Objectives
Windchill performance is largely a function of database access: how often you go
to the database, what you send it, what you ask it to do, and what you ask it to
send back to you.The primary goal of converting single-object APIs to multi-
object is to replace the CRUD operations driven by single objects with multi-
object CRUD operations.
A single-object operation that does a query and then updates, individually, the
objects returned by that query will execute n queries and as many updates as the
number of objects those queries produce. Ideally, the multi-object conversion of
that operation will execute one query and one update. While what is being sent to
the database, asked of the database, and sent back from the database is about the
same, the number of trips has been significantly reduced. Since the “connection”
cost is significant (and, furthermore, since the CRUD operations take advantage
of more performant batch SQL operations), the multi-object will significantly
outperform the looped-over single-object operation. This is true even before the
VM cost of the looping is factored in.

Considerations
The following factors weigh in to increase the complexity of multi-object
operations over their single-object counterparts:
• What should the multi-object operation's signature look like?
• Exceptions?
• Related data changing?
• Data coming at you for different reasons?
• Complex query building?

B-2 Windchill Customizer’s Guide


API Guidelines

Multi-Object vs. Multi-Multi-Object APIs


The changeFolder example is a good, illustrative example of how far to go when
converting to multi-object. The single object changeFolder API is defined as
follows:
public Foldered changeFolder(Foldered member,Folder newFolder)throws WTException

Two obvious multi-object variants are:


public Foldered changeFolder(WTSet folderedSet,Folder newFolder)throws WTException

public Foldered changeFolder(WTValuedHashMap folderedToNewFolderMap)throws


WTException

The first API requires that all of the objects in the set go to the new folder and
represents a simple multi-object API that would require the caller to call the API
multiple times if changes to multiple folders are required.
The second API simply maps the foldered object to the new folder to change to; it
(the multi-multi-object API) is more complex – there's a lot more to manage in the
API and the caller is required to build the map even if all of the objects are going
to a single location. If the second implementation requires an internal breakup by
folder, it'll likely not be appreciably more performant than the former. Then again,
if it doesn't need to break up the data and can dispatch a single event for all the
moved objects, it will likely be more performant, although the added complexity
will then be passed onto the multi-object listeners.
If performance is the only measurement, the multi-multi-object API wins.
However, there are other factors to consider:
• When weighing the performance benefits, is it really the case that in the API
(and in any of the listeners for the events the API might dispatch) the code
won't simply end up breaking up the work in such a way that it's really
looping over the work as though it were multi-object and not multi-multi-
object?
• Is there a real need to provide that flexibility?
• Is the additional flexibility worth the additional complexity?
• If more than a map is needed, multiple, ordered arguments grouped by index
is probably the only way to pass the data, but this is somewhat ugly. For
example, checkout takes a Workable to check out, a folder to check out to,
and a note representing the check out comment; making all three arguments
multi-object most likely implies two lists and an array, or three lists.

Note: The changeFolder APIs in the Folder Service are not intended to be used
when moving Foldered objects between containers; the moveAllVersions API in
the Container Move Service should be used instead.

Multi-Object Conversion Guidelines B-3


Converting Boolean Operations
The conversion of operations that test conditions and return booleans will result in
a collection-based operation that returns either true if all the objects pass the test,
or a sub-collection of all the objects that pass the test. In some cases, two
operations, one returning a boolean and the other a sub-collection. The decision to
produce one, the other, or both should be based simply on need.
It should be noted that the boolean operation will generally always be faster than
the sub-collection operation because the boolean operation can terminate on the
first failure. For this reason, if both are logically needed and the performance
differences are non-negligible, it is preferable to produce both (rather than have
the caller check that the size of the returned collection is either 0 or equal to the
size of the passed-in collection). The boolean-based operation should then share
the check and not simply be a wrapper. Whether this is actually done should be
weighed against the cost and benefits of actually coding both operations. If both
are needed, but time is not available to adequately produce both, the boolean
implementation may simply wrap the sub-collection operation.
It should be clear in the return type of the operation that the test applies to “all ” or
that the test will “get ” those meeting the criteria.

Retaining Single-Object Operations


The creation of a multi-object variant of a single-object operation begs the
question: What should you do with the single-object operation?
• If the operation is no longer used, remove it.
• If there are reasonable justifications for keeping it around, consider making
the single-object operation a simple wrapper to the multi-object variant, as
this will reduce maintenance over time.
• There may, in rare cases, be legitimate reasons to keep the implementations
separate (for example, there may be cases where the single-object operation is
much more performant than the multi-object counterpart).

WTCollection vs. WTSet/WTList and WTHashSet/WTArrayList


Operations that take collections as arguments will need to decide what type of
collection to take. The highest level interface is WTCollection, which is
implemented by both the list and set collections (maps do not extend collection in
either Windchill or Java). The following high level considerations provide a good
start for determining what to take:
• Your operations should always take interfaces and not the concrete classes;
for example, instead of forcing WTHashSet, take WTSet.
• WTCollection provides the greatest flexibility.
• WTSet guarantees uniqueness, which is useful if the operation shouldn't
logically operate on the same object twice.

B-4 Windchill Customizer’s Guide


• WTList is ordered, which may be needed by some “multi-multi-object”
operations.
• WTSets provide the most efficient lookup (good for when contains(...) is
needed), WTLists have smaller and more efficient memory footprints
• It is easy to convert between container types.
So, what arguments should your operation take? Firstly (and to reiterate), it
should take the interfaces (WTCollection, WTList, WTSet) rather than the
concrete classes (WTArrayList, WTHashSet) because the synchronized and
unmodifiable variants of these collections do not descend from
WTArrayList/WTHashMap. Beyond that, an operations should take what it
contractually requires (which may require internal conversions for
implementation efficiency):
• Take a WTList if order matters because other arguments to the operation must
be “paired ” with collection (also consider WTKeyMap and WTValuedMap,
covered later).
• Take a WTSet if duplicates should not exist.
• Take a WTList if both order and duplicates matter (the operation should then
internally validate uniqueness).
• Take a WTCollection if neither duplicates nor order matters.
And, similarly, what should an operation return?
• Most operations should return WTCollection, providing them the ability to
change the underlying implementation without impacting callers
• In cases where the returned collection is the same object as an argument-
passed collection, return the same type as that argument

Empty collections
Windchill does not have a prescribed standard for the validation of arguments to a
method. Some methods exhaustively validate each argument, others leave invalid
arguments to fail later in the method (via NullPointerExceptions and the like).
The issue of argument validation comes up in collections not because they might
be null, but because “transformation ” operations (sub-collections, conditional
copying of collection elements, etc.) may result in a collection being empty. That
empty collection, then, may be passed to another multi-object API. What would it
mean to call “store ” with an empty collection? What should the store method do?
There are a few options relative to this:
• The method checks if the collection argument is empty; if it is empty, it
throws an IllegalArgumentException

Multi-Object Conversion Guidelines B-5


• The method checks if the collection argument is empty; if it is empty, it
returns (which may necessitate the creation of a potentially ambiguous return
value)
• The method follows the predominant practice for other arguments today; that
is, it assumes arguments are passed “correctly ” and attempts to go about its
business, potentially failing in odd ways somewhere along the line.
This document recommends the last option. It is the caller's responsibility to
recognize when its collections' manipulations may result in empty collections and
the caller should not call other multi-object operations with an empty collection.
The behavior, unless explicitly documented otherwise, of any multi-object
operation is considered to be “undefined ” when empty collections are passed.
The justifications for this approach are as follows:
• There is no established precedent that suggests arguments should be
exhaustively validated in Windchill methods, public or not, supported or not.
• The prevailing practice is that arguments are not checked at all.
• Operations that manipulate collections in such a way that empty collections
may result are presumably a minority, while there can be lots of multi-object
operations; it makes sense to localize the handling of empty collections by
making it the responsibility of the method that could produce them to handle
the end-case.
• Experience with methods that can produce empty collections has shown that
the methods themselves will generally fail even if the multi-object methods
they call do not, so it's generally necessary for these methods to be aware of
and handle the empty collections they may produce.

Memory considerations
A multi-object operation has a much higher footprint than the corresponding
single object operation. This is true in both the VM, where multi-object operations
take significantly more memory, and in the database, where transaction sizes
increase dramatically.
There are some things that can be done to the reduce memory footprint, such as
querying only what is needed to make decisions. Both the VM and Oracle can be
tuned to handle the expected increased footprints.

B-6 Windchill Customizer’s Guide


Collections Guidelines

Inflating
The WTCollection interface transparently masks the fact that a persistable can be
represented as a QueryKey, WTReference, or full-blown Persistable. It also has
iterator APIs (queryKeyIterator(), referenceIterator(), and persistableIterator()) to
get the objects based on the representation desired. The persistableIterator() will
inflate the query keys and references if they are ot already inflated, but it is
important to note that referenceIterator will not. This means that one should be
extremely careful using the following code:
for (Iterator i =col.referenceIterator();i.hasNext();){
...
Persistable p =((WTReference)i.next()).getObject();
...
}

The problem with the above code is that the getObject() may result in sequential
inflates. Unless you're absolutely sure the collection has bee inflated, this is a bad
idea. Even if you are, it's a bad idea. Instead, use the persistableIterator()API.

Using connect()
WTCollection's inflate and refresh implementation does not replace persistables
in-place. This means that two collections with the same data may become out-of-
sync when an inflate or refresh is done on one of the collections.
When creating new collections from the objects in existing collections, use the
connect() APIs to ensure that the changes made to objects in one collection affect
all the collections which contain the same objects.

WTKeyedMap vs.WTValuedMap
The WTKeyedMap is a map in which the keySet is essentially a WTCollection,
providing all of the benefits of the WTCollection to the keys. The values,
however, are just a regular collection. Many APIs will wish to map Persistables as
keys to Persistables as values, which is exactly what the WTValuedMap provides;
the WTValuedMap's values are a WTCollection.
Where both the keys and the values are Persistables, the WTValuedMap should be
used.

OBJECT_IDENTIFIER vs.VERSION_FOREIGN_KEY collections


Elements in a collection can be “keyed ” by either their
ObjectIdentifier/ObjectReference or their VersionForeignKey/VersionReference.
The constants OBJECT_IDENTIFIER and VERSION_FOREIGN_KEY, defined
in CollectionsHelper, determine which keying mechanism to use (where an
Iterated object is added to the collection). Iterated objects in collections keyed

Multi-Object Conversion Guidelines B-7


differently cannot be connected, because the toIdArray() API will return different
IDs for the same objects (one will return OIDs and the other branch Ids), and the
get/contains(QueryKey/WTReference) APIs will return false if the reference/key
is different than the one in the collection even if the persistable is logically
equivalent.
Multi-object operations acting on Iterated data, presumably, would need to handle
collections keyed either as OBJECT_IDENTIFIER or as
VERSION_FOREIGN_KEY. This can get quite complicated, even if the
operation simply throws in the towel, inflates the collection, and creates a new
collection that is “keyed properly ”.
Rather than force all operations to deal with this, the guideline should be that all
multi-object operations will assume the collection passed in is keyed as
OBJECT_IDENTIFIER unless specifically documented otherwise. This is for the
following reasons:
• The added complexity of handling multiple keyings could, and most likely
would, dwarf the true logic on the method.
• Collections keyed differently cannot be connected.
• The collection must be inflated to “convert ” their contents to another
collection that is keyed differently.
Callers should not call multi-object APIs with collections keyed as
VERSION_FOREIGN_KEY unless the APIs are explicitly documented to take
them. The APIs being called are not required to verify the passed-in collections'
key type, and will most likely fail in odd ways if invalid collections are passed.

Modifying collections
Generally, the contents of collections passed to an operation as argument should
not be altered (by removing or adding members); doing so alters the caller's
collection. Be especially careful using collections' APIs that produced
“backed”collections, such as the “subCollection(...)” APIs, as modifying the
contents of a backed collection also change the contents of the source collection.

B-8 Windchill Customizer’s Guide


Event Dispatch Guidelines

Cleanup
Many of the single-object events could benefit from cleanup work. For exampole,
a lot of them include the service, which is of dubious utility. Many have odd
datatypes, such as paired vectors. When converting these events to multi-object,
how much of this should be cleaned up? Should the multi-object variant, for
example, include the service? Should the service be removed from the single
object event? Should more of the single object be cleaned up? When considering
how much to do, consider also the following:
• The ultimate goal is to totally replace the single-object variant by converting
all the listeners to multi-object, so it may not make much sense to spend
significant time cleaning up the single-object events
• Cleanup of the single-object events beyond that of removing the service will
likely require reworking existing listeners, taking time from the more
interesting tasks of making those listeners multi-object
In general, little should be done to the single-object events save superficial clean
up (such as removing the service). An exception to this is when the changes to the
event to make it multi-object necessitate a re-evaluation of the single-object event.

Use of collections
The multi-object events, like other multi-object operations, should pass
collections of objects. These collections should be unmodifiable to ensure that
listeners and the APIs they call do not alter the contents of the collection.This
deviates slightly from the relaxed stance taken above, however there is never
justification for a listener to alter an event's contents, so it should be ensured that
this does not happen.

Single-and multi-object listeners?


Remember that if a listener listens for both single- and multi-object events (via
notifyVetoableEvent and notifyVetoableMultiObjectEvent), it will be dispatched
to twice. It is not the case that the dispatch mechanism will determine that it
should only notify the single-object variant if the event was dispatched as single-
object, for example.
There is only one known case where listening to both is appropriate, and that case
is where the listener can't fully handle multi-object but could benefit by doing
some of the work upfront,especially to pre-query data.The multi-object listener
will be dispatched to first, followed immediately by the single-object listener (in a
loop). So, it is possible to listen as multi-object, put the results of a query, for
example, on the context, and then use that contextual data in the single-object
listener.

Multi-Object Conversion Guidelines B-9


KeyedEvent's getEventTarget()API
The single-object events all upheld an unspoken, implicit contract when
implementing getEventTarget(). The API always returned the target Persistable of
the event. This made it possible for listeners to listen generically to multiple
events, casting the result of getEventTarget() to a Persistable. The notification
functionality, for example, relies on the ability to generically listen to arbitrary
events.
Multi-object variants of the single-object events must adhere to this policy by
ensuring that the result of calling getEventTarget() on a multi-object event is a
WTCollection of some form. This will allow generic listeners to cast
getEventTarget() to a collection without requiring further knowledge of the event.
Note that this does not preclude using the eventTarget field to store more
complicated data, such as WTValuedMaps in the WorkInProgressServiceEvent,
so long as getEventTarget() is overridden in the event to return an appropriate
collection.

Multi-Object Delegation Guidelines

Converting to wt.services.ac.DefaultServices
There are numerous patterns for delegation in place today. Wherever possible and
practical, these patterns should be replaced by the use of
wt.services.ac.DefaultServices. This single class and its static APIs eliminate the
need to do things like implement interfaces such as ApplicationContextChild. As
with other "cleanup work" associated with converting to multi-object, actually
cleaning up delegation in code should be weighed against the cost of cleanup.

B-10 Windchill Customizer’s Guide


Multi-Object Exceptions Guidelines

Basic expectations
Multi-object operations can detect multiple failures.The simplest example of this
is the query that, if results are found, indicates an error condition. The conversion
to multi-object implies that multiple rows may be returned by such a query.
Should a single-object exception be thrown against the first result or a multi-
object exception against the entire result? More generally, how far should one go
in reporting exception conditions to the user?
The first, absolute rule is that if a exception is thrown to you, you are done. You
should not be continuing after an exception has been thrown because an exception
corresponds to a non-local exit, which means that the operation did not finish its
normal processing and work was not completed. Not to mention that, oftentimes,
the operation, as part of a finally block, will rollback the transaction.
This document suggests a “throw what you know ” approach to exceptions. Use
the additionalMessages capabilities of the multi-object exceptions when you
have additional knowledge. With the example above, it would make sense to build
a multi-object exception out of all of the results.
Another common example is that of validation in a loop. Say that code is
processing the collection in a loop and would throw an exception if the value of a
field is invalid. Should this code collect all the failures and throw a multi-object
exception at the end of the loop, or should it throw a single-object exception
immediately? In most cases, the code should collect the messages for the failures
and throw a multi-object exception at the end of the loop.

Pre-flight checks
The single-object APIs all “fail fast” -- once an error condition is discovered,
processing stops and an exception is thrown. For example, if it is determined that
the object a user wants to check out is already checked out, the code doesn't
continue determining if the user does or does not have modify access; it bails out
and throws an exception.
Many single-object APIs, and by extension their multi-object counterparts,
perform what are called “pre-flight checks ”. These are the validations that occur
before the real work is done to the object(s). The single-object APIs bail when the
first validation fails.
With multi-object operations, however, it is possible to take the another approach.
Upon encountering an error, they may continue to collect additional problems so
as to later report a more informative exception message. Thus, the multi-object
check out operation could check access (provided it uses the non-exception
throwing “hasAccess ”), validate that the objects aren't already checked out, and
do a number of other things, recording the problems along the way, and eventually
throw a single exception with messages for each of the failures. The motivation to
do this is the belief that it will aid the users, as they will get as much information

Multi-Object Conversion Guidelines B-11


up front as opposed to needling them incrementally (assuming they can and
actually do fix the problems reported to them). This document recommends
against this approach in favor of the continued practice of “failing fast ” for the
following reasons:
• Exceptions are expected to be infrequent; you should not put significant work
into them.
• This approach requires the use of non-exception-throwing APIs; the
exception-throwing variants would “prematurely ” terminate the pre-flight
checks. These exception-throwing variants throw their own exceptions, which
may be strongly-typed exceptions (such as NotAuthorizedException),and
provide their own messages. Calling the non-exception-throwing variants
drops the strong typing and makes the message building the caller's
responsibility.
• The additional information gathered is not necessarily correct nor complete.
You may either mask errors or produce unreliable ones by either
dropping/retaining the objects in the collection that logically failed a pre-
flight check. Similarly, addressing all the issues uncovered during the pre-
flight checks does not guarantee success; there will always be at least some
needling.
Focus instead on getting the “positive ” case working.

Multi-object Exceptions and Single-Object APIs


A concern related to multi-object exceptions is that as single-object APIs wrap the
multi-object counterparts, they'll suddenly receive multi-object messages. A poor
but illustrative example of this is that operation that may have failed with a “A
message ” may now get something like “The operation failed due to the following
errors: A message ”. If the collection is of size 1 and the multi-object exception
would not make sense or would otherwise seem awkward to the existing single-
object clients, preserve the original exception.

B-12 Windchill Customizer’s Guide


Multi-Object CRUD API Guidelines

Internal Dependency Issues


The multi-object persistence APIs will not unravel dependencies in a collection. If
two objects are added to a collection to be persisted and one has a reference to the
other, the multi-object store API will do nothing to ensure that the one object gets
persisted ahead of the other such that the database will have an appropriate
reference value. Worse, because of the manner in which the persistence manager
handles persistence, the in-memory objects will appear to contain valid references
even if the database does not.
Be careful to understand the dependencies in the data. Split up the data where
dependencies exist that would yield problems.

Batch Update/Delete Guidelines

When to Use?
The batch update/delete operations represent the most performant option for
affecting change in the database because they minimize both the data needed to
perform the operation and the data eeded to affect the change – neither requires
that the objects to be changed first be retrieved from the database and only the
columns to change need to be sent (as opposed to full persistables) in the case of a
update. These APIs should be considered when:
• There is no need to bring the object back into the VM, either to perform tests
or to dispatch events
• None of the objects involved in the batch operation exist in memory prior to
the batch operation
In most cases, it is sufficient to say that their use should be limited only to cases
where there is never a need to bring the object (or its reference) back to memory
and should never be used on objects already in memory. The above guidelines are
based on the fact that the performance benefits drop when the data is actually
needed and by the fact that the changes will not be reflected in any of the in-
memory objects. However, a gray area for batch update is in cases where the
references are needed for event dispatch, the dispatched event indicates that the
change has occurred, and the listeners need not inflate.

Multi-Object Conversion Guidelines B-13


Transaction Context/Listener Guidelines

Transaction Context vs.Method Context


The method context is a global map that remains in scope for the duration of a
server-side call; the transaction context is a map that can be associated with the
“global ” (outer-most transaction) or the local transaction and remains in scope so
long as the transaction is alive (the context is dropped as immediately prior to
committing/rolling back). Nearly all of the usages of the method context should
be replaced by the transaction context.

Single-object contexts
Existing single-object code that puts objects on the method context for
downstream processing will need to be evaluated. Both the code that puts the
object on the context and the code that processes it will likely need to change. In
fact, only when the downstream consumer of the context data is guaranteed to still
be flat-lined (from the point that the flat-lined code added the context) will the
single-object context be OK.
The issue, especially in the case of contexts added by listeners, is that the
downstream code may be dealing with the entire collection while only a single
object is on the context. Keep in mind that the dispatch order is multi0-ab,
single0-a, single0-b, multi1ab, single1-a, single1-b, NOT multi0-ab, multi1-ab,
single0-a, single1-a, single0-b, single1-b, so if one listener, in single-object mode,
adds an object to the context for another listener to consume, the other listener
will always only get the last object in the collection on the context because event
dispatch will loop over the first listener (single0-a, single0-b) before getting to the
second one (single1).

Deferred validation/work with transaction listeners


One of the biggest architecture shifts associated with multi-object operations is
the fact that multiple, highly-related, objects are changing in a single transaction.
In the single-object model, only one part was being revised or checked out, for
example, and code could either assume all the related data was not changing or
would explicitly lock the related objects to prevent change; the essential view of
the database is that everything outside of the work being done to support the
single-object operation is static and unchanging. Multi-object operations break
this assumption and force the code to consider what it would mean for related
objects in the same transaction to change, either as part of the operation itself or
possibly either prior to or post the operation.
There will be cases where it is either impractical or impossible to deal with the
system while it is in flux; it will be impossible for the operation, when invoked, to
validate that the resultant state of the database would be valid or even that
everything that would need to be done has been done. This is where transaction
listeners come into play. They allow the operation to defer work until the
transaction is about to commit.

B-14 Windchill Customizer’s Guide


The “classic ” use case for deferred validation is when changes to related objects
in the same transaction impact the logic of the listener and its APIs. Because of
flat-lining and the splitting of collections, if the listener/API cannot handle any of
the following, it should move its work into a transaction listener:
• A related object having already undergone change prior to this
object's/collection's changes that are being handled now.
• The changes occurring to related objects in the same collection.
• A related object changing after this listener/API processes it.
Remember that the other objects that are changing will likely have their own
events associated with them, returning to the same listener/API. You should
consider, based on the above points, what happens when related data changes and
is processed by the same code both before and after this collection is processed
and what it means for data in the same collection to be changing.

Neat Tips and Tricks

Inflating references
If you have a collection of objects with references you wish to inflate, simply add
the references to a new collection and inflate it. Since the inflated objects are set
in the existing references, this will result in the original object's references getting
inflated.

Persisting interdependent data


It is necessary to break up the persistence of objects that have references to other
objects being persisted. For example, if code is persisting the master and its first
iteration in the same transaction, the store of both objects cannot occur by putting
both objects in the collection and persisting them with one API call.
However, the nature of the store API operation relieves the caller of the necessity
of reconnecting the references, provided the operation is done server-side. The
following code is fine:
partMasterCollection = PersistenceHelper.manager.store(partMasterCollection);
partCollection = PersistenceHelper.manager.store(partCollection);

The master references in the parts will automatically reflect the persisted changes
of the partMasterCollection (most notably, the OIDs will now be in the references.

Multi-Object Conversion Guidelines B-15


B-16 Windchill Customizer’s Guide
C
Creating Non-Modeled Services
for Listening

Topic Page
Overview ............................................................................................................ C-2
Create a Service Interface................................................................................... C-2
Create a Standard Service Class......................................................................... C-3
Compile .............................................................................................................. C-5
Register the New Service ................................................................................... C-6
Restart the Method Server.................................................................................. C-6

C-1
Overview
Customers that do not have Windchill InfoModeler may create services for
listening to events generated by other services (customers that have Windchill
InfoModeler should create listeners by following the instructions in the Creating a
Listener Service section of this Guide).
Here are the steps necessary to create a non-modeled service for listening:
1. Create a service interface
2. Create a standard service class to implement your service interface and extend
the StandardManager class
3. Compile your interface and class into your Windchill codebase
4. Register your new service in the codebase with xconfmanager
Below is an example to create a service that listens for pre- and post-checkin
events. When it "hears" one of these events, it prints a simple message to standard
output.
The example assumes the service is in a package called com.acme.listen, and that
the service is called the "Listen" service. If you copy this example, be sure to
change these names to something more appropriate.
The example assumes that you are familiar with the information in the Developing
Server Logic chapter on page 36-1.That chapter explains how to write code to
register listeners for particular events.

Create a Service Interface


Save the nearly-empty service interface to:
<Windchill>/src/com/acme/listen/ListenService.java

Here is the source code:


package com.acme.listen;
public interface ListenService {
/*
* The interface for the ListenService is empty, but to be
compatible
* with more complex services, it must exist.
*/
}

C-2 Windchill Customizer’s Guide


Create a Standard Service Class
Save the standard service class to:
<Windchill>/src/com/acme/listen/StandardListenService.java

The example below has comments that indicate "standard" pieces of code that
should not be changed as they are necessary to interact with the standard service
manager and other services. There are other comments that indicate pieces of
code that should be changed, for example, to reflect your choice of package and
class names and to listen to the particular events you are interested in.
Here is the source code:
/* Change to your package name */
package com.acme.listen;

/* javac -classpath z:/Windchill/codebase -d z:/Windchill/codebase *.java */


/* xconfmanager -t codebase/wt.properties -s
wt.services.service.4160=com.acme.listen.ListenService/com.acme.listen.StandardList
enService -p */

/* Change to import you Service Interface */


import com.acme.listen.ListenService;

import java.lang.String;

/* Standard imports for services */


import wt.services.ManagerException;
import wt.services.ServiceEventListenerAdapter;
import wt.services.StandardManager;
import wt.session.SessionContext;
import wt.session.SessionHelper;
import wt.session.SessionServerHelper;
import wt.session.SessionMgr;
import wt.util.DebugFlag;
import wt.util.DebugProperties;
import wt.util.DebugType;
import wt.util.DebugWriter;
import wt.util.WTException;

/* Changes required here:


* Imports necessary for listening to particular events, in this case
* check-in and check-out events */
import wt.vc.wip.Workable;
import wt.vc.wip.WorkInProgressServiceEvent;

/**
* Listens for pre/post checkin events. When an event is
* "heard", prints messages to the MethodServer log and console.
* <p>
* Use the <code>newStandardListenService</code> static factory method(s),
* not the <code>StandardListenService</code> constructor, to construct
* instances of this class. Instances must be constructed using the static
* factory(s), in order to ensure proper initialization of the instance.
* <p>
*

Creating Non-Modeled Services for Listening C-3


**/

/* Change to your class name */


public final class StandardListenService extends StandardManager
implements ListenService {

/* Standard class identification string */


private static final String CLASSNAME =
StandardListenService.class.getName();

/* Standard debug variables for services */


private static final boolean DEBUG = DebugProperties.isDebugOn(CLASSNAME);
private static final DebugWriter LOG =
(DEBUG ? DebugProperties.getWriter(CLASSNAME) : null);

/* Standard getter for class name */


public String getConceptualClassname() {
return CLASSNAME;
}

/*
* Standard default factory for the class.
*
*/

public static StandardListenService newStandardListenService()


throws WTException {
StandardListenService instance = new StandardListenService();
instance.initialize();
return instance;
}

/*
* Initializations of event listeners
*/

/* Override inherited method */


protected void performStartupProcess() throws ManagerException {

/* Standard debug output */


if (DEBUG && DebugProperties.isTrace(this))
LOG.enter(CLASSNAME,"performStartupProcess");

/* Standard way to become admin */


SessionContext prev = SessionContext.newContext();
try {
SessionHelper.manager.setAdministrator();
}
catch (WTException wte) {
System.err.println("StandardListenService: failed to set Administrator (ok
if installation)");
return;
}
finally {
SessionContext.setContext(prev);
}

C-4 Windchill Customizer’s Guide


/* Change: Add event listeners here */
getManagerService().addEventListener(
new ServiceEventListenerAdapter( this.getConceptualClassname() ) {
public void notifyVetoableEvent( Object event )
throws WTException {
final Workable target =
((WorkInProgressServiceEvent)event).getOriginalCopy();
System.out.println("Listen hears PRE_CHECKIN: ");
System.out.print(" target:");
System.out.println(target.toString());
}
},
WorkInProgressServiceEvent.generateEventKey(
WorkInProgressServiceEvent.PRE_CHECKIN ));

getManagerService().addEventListener(
new ServiceEventListenerAdapter( this.getConceptualClassname() ) {
public void notifyVetoableEvent( Object event )
throws WTException {
final Workable target =
((WorkInProgressServiceEvent)event).getOriginalCopy();
System.out.println("Listen hears POST_CHECKIN: ");
System.out.print(" target:");
System.out.println(target.toString());
}
},
WorkInProgressServiceEvent.generateEventKey(
WorkInProgressServiceEvent.POST_CHECKIN ));

/* Standard debug output */


if (DEBUG && DebugProperties.isTrace(this))
LOG.exit(CLASSNAME,"performStartupProcess");
}
}

Compile
Compile your classes into:
<Windchill>/codebase/com/acme/listen

Creating Non-Modeled Services for Listening C-5


Register the New Service
The standard service manager must be notified that you have created a new
service. This is done by registering the service in the wt.properties file using
xconfmanager.
Use a unique service number that does not already appear in the wt.properties file.
Change the reference to the service interface and standard service class to your
own.
xconfmanager -t codebase/wt.properties -s
wt.services.service.4160=com.acme.listen.ListenService/com.acme.listen.StandardList
enService -p

Note that xconfmanager will add the entry to site.xconf and then propagate the
changes to wt.properties.

Restart the Method Server


The method server must be restarted so that the standard service manager will
start your service and implicitly register your event listeners.

C-6 Windchill Customizer’s Guide


D
Windchill Profiler

The Windchill Profiler can be used to help diagnose performance bottlenecks after
you have customized code. It enables you to capture an elapsed time profile while
executing application logic in the method server. The profile shows call stacks,
call counts, and context data (for example, SQL, bind parameters, JNDI strings,
son on). PTC recommends profiling in a test environment; however, profiling is
possible in a production environment without interrupting system operation.

Topic Page
Overview ............................................................................................................D-2
Profiler Features .................................................................................................D-2
Profiler Operation...............................................................................................D-2

D-1
Overview
The Windchill Profiler enables you to instrument server side application logic. A
user interface is provided to control the profiler, which is embedded within the
method server.

Note: Support for the profiler is limited and the profiler is subject to change
without notice.

Profiler Features
The Windchill Profiler supports the collection of performance profiles in the
following Windchill subsystems:
• JDBC execution
• CacheManager get/put/update
• WTAdapter JNDI Task
• RMI Object Serialization
The profiler allows you to filter call stacks by thread; sort call stacks by count or
by cost (for example, elapsed time). The call stacks, call counts, and elapsed times
are displayed in a JTree format. The output can include additional data such as
SQL bind parameters or cache keys.
Profiles can be saved to disk and reloaded, or they can be exchanged using e-mail.
HTML summaries can also be generated.

Profiler Operation
To launch the profiler, open a command shell on the Windchill server. From the
windchill shell, invoke the profiler as follows:
windchill wt.tools.profiler.WindchillProfiler

Note: A long running profile session might need a larger heap. In that case, use
the following command to start the profiler:

windchill --javaargs=-Xmx512m
wt.tools.profiler.WindchillProfiler

You are prompted to authenticate. Log in as the administrative user.


If the authentication is successful, the profiler opens.
From the Operations drop-down menu, select the area that you want to profile.
For example to profile all JDBC executed by the Method Server, select SQL +
Execution Time + Bind Parameters.
To start collecting the SQL profile, click the blue start button. To stop collecting
profile data, click the red button.

D-2 Windchill Customizer’s Guide


In the following example, an RMI-based client executed a number of method
calls. Notice that the profile frame is divided into two panes:
• The left pane allows you to select call stacks sorted by count or by cost.
• The right pane shows the call stacks for all threads captured by the profile.

Call stacks appearing in the right pane need to be expanded until the leaf node for
a given call stack is displayed. The leaf node of a call stack contains an SQL
string.

Windchill Profiler D-3


The call count field for SQL profiles may be a little confusing to interpret at first.
To illustrate, look at the following example
O-count=157:wt.pds.BasicResultCursor.next(BasicResultCursor.java:487):cost=16
O-count=155:wt.pds.BasicResultCursor.advance(BasicResultCursor.java:626):cost=16
| O-count=155:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java:159):
cost=16
| O-count=155:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java:
134):cost=16
| O-count=155:wt.util.TraceTimingThreadedLogger.addEndEntry(
TraceTimingThreadedLogger.java:208):cost=16
| '-count=155:DB FETCH: SELECT 'wt.epm.workspaces.EPMWorkspace',...
FROM EPMWorkspace A0
WHERE ((A0.idA3M5 = ?)) AND (A0.markForDeleteA2 = ?):cost=16
count=2:wt.pds.BasicResultCursor.advance(BasicResultCursor.java:633):cost=0
O-count=1:wt.pds.BasicResultCursor.getNextResultSet(BasicResultCursor.java:
683):cost=0
| O-count=1:wt.pds.BasicStatementBuilder.getStatement(BasicStatementBuilder.
java:236):cost=0
| O-count=1:wt.pom.WTConnection.prepareStatement(WTConnection.java:433):
cost=0
| O-count=1:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java:
159):cost=0
| O-count=1:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java:
134):cost=0
| O-count=1:wt.util.TraceTimingThreadedLogger.addEndEntry
(TraceTimingThreadedLogger.java:208):cost=0
| '-count=1:DB PREPARE:cost=0
O-count=1:wt.pds.BasicResultCursor.getNextResultSet(BasicResultCursor.java:
705):cost=0
O-count=1:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java:
159):cost=0
O-count=1:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java:
134):cost=0
O-count=1:wt.util.TraceTimingThreadedLogger.addEndEntry
(TraceTimingThreadedLogger.java:208):cost=0
'-count=1:SELECT 'wt.epm.workspaces.EPMWorkspace', … FROM EPMWorkspace A0
WHERE ((A0.idA3M5 = ?)) AND (A0.markForDeleteA2 = ?):cost=0

Every new query comprises three phases:


1. DB PREPARE
2. EXECUTE
3. FETCH
The sample above shows a count of 157 that is comprised of 1 Prepare, 1 Execute
and 155 rows fetched.
The cost field is milliseconds – it took 16 ms to execute this query.

D-4 Windchill Customizer’s Guide


E
Additional Topics - Client
Customization

This appendix provides additional procedures for performing client


customizations. These procedures are not expected to be commonplace, but may
be useful in advanced customization scenarios.

Topic Page
Defining Non-JSP Actions to be Executed From a JSP Page ........................... E-2
URLFactory in the JSP Environment................................................................. E-5
Using File-Handling Applets in Non-JSP Clients............................................ E-14

E-1
Defining Non-JSP Actions to be Executed From a JSP Page
Actions that will be executed from a page built using the Windchill JSP
framework must be defined in the file <Windchill>/codebase/actions.xml.
Each object type needs a defined element (i.e., using <objecttype></objecttype>).
Within this element is entered each of the actions that may be available for this
type of object. The name specified for this element is used as an alias for a fully
qualified class name. The class attribute is the fully qualified class name for the
object type.
The files <Windchill>/codebase/action_*.properties are complementary to
actions.xml, containing entries for things such as labels, tooltips, and icons to use
for the actions based on a certain locale.
Below is a snippet from the actions.xml file used in R7.0. These actions are used
for the Site tab and its sub-tabs.
<objecttype name="site" class="com.ptc.netmarkets.site">
<action name="view" checkaccess="true" enabledwhensuspended="true">
<command windowType="page"/>
</action>
<action name="listOrgs" checkaccess="true" enabledwhensuspended="true">
<command windowType="page"/>
</action>
<action name="listFiles" checkaccess="true" enabledwhensuspended="true">
<command windowType="page"/>
</action>
<action name="listAdmin" enabledwhensuspended="true">
<command windowType="page"/>
</action>
<action name="listTypes" enabledwhensuspended="true">
<command windowType="page"/>
</action>
<action name="listTemplates" enabledwhensuspended="true">
<command windowType="page"/>
</action>
<action name="listUtilities" enabledwhensuspended="true">
<command windowType="page"/>
</action>
<action name="site_audit_Reports" enabledwhensuspended="true">
<command windowType="page"/>
</action>
</objecttype>

Default Assignment of URL


The URL associated with an action is determined in one of several ways,
depending on how that action is registered in the actions.xml file. The default
mechanism maps the action to a URL of the form:
http://<hostname>/<webapp>/netmarkets/jsp/<type>/<action>.jsp

where <type> and <action> are, respectively, the names of the objecttype and
action specified in actions.xml.

E-2 Windchill Customizer’s Guide


For example, above is an action with name="view" defined under an objecttype
with name="site". Since a renderType attribute is not specified in the action
element, the URL
http://<hostname>/<webapp>/netmarkets/jsp/site/view.jsp

is assigned to this action. The corresponding JSP file is


<Windchill>/codebase/netmarkets/jsp/site/view.jsp

If you want to override this default you can specify a value of GENERAL,
GENERAL_WITH _CONTEXT, or PDM for the renderType on the action.

Assignment of URL When renderType="GENERAL" or


"GENERAL_WITH_CONTEXT"
For renderType="GENERAL", the method attribute of the command element is
used to specify the JSP file to use. For example, if the view action above were
defined as follows:
<action name="view" renderType="GENERAL">
<command windowType="page" method="/wtcore/jsp/customizedAction.jsp"/>
</action>

then the produced URL would be


http://<hostname>/<webapp>/wtcore/jsp/customizedAction.jsp

with
<Windchill>/codebase/wtcore/jsp/customizedAction.jsp

as the corresponding JSP file.


You can use renderType="GENERAL_WITH_CONTEXT" in the same fashion;
the difference is that the dynamically-generated URL will include the context
object OID.

Assignment of URL When renderType="PDM"


In contrast, renderType="PDM" can be used to indicate that the action generates a
template processing page, and therefore you are using a URLActionDelegate to
generate the URL to be assigned to the action. In this situation, the action name
must map to a URLActionDelegate entry in a properties file. For example, below
is an action entry for creating a document.
<action name="CREATEDOCUMENT1" renderType="PDM">
<command windowType="popup" method="CREATEDOCUMENT1"/>
</action>

The URLActionDelegate (CreateDocumentURLActionDelegate) that produces


the PDMLink URL to the Create Document wizard is identified in the properties
file <Windchill>/codebase/com/ptc/windchill/pdmlink/doc/doc.properties in the
following manner:

Additional Topics - Client Customization E-3


wt.services/svc/default/wt.enterprise.URLActionDelegate/CREATEDOCUMENT1
/java.lang.Object/0=com.ptc.windchill.pdmlink.doc.server.processors
.CreateDocumentURLActionDelegate/duplicate

The selector for this action, CREATEDOCUMENT1, corresponds to the method


attribute of the command element in the action’s XML definition. This should be
identical to the name of the action.
In the above example, the type is specified in the property entry as
java.lang.Object. This means you do not need to specify a class attribute on the
command element -- the default is java.lang.Object.
In some cases, you may need to specify the class to find the appropriate
URLActionDelegate. Suppose you wanted to use a URLActionDelegate whose
property entry is defined as follows:
wt.services/svc/default/wt.enterprise.URLActionDelegate/list2
/wt.pdmlink.PDMLinkProduct/0=com.ptc.windchill.pdmlink.templateutil.server
.processors.DefaultProjectLinkURLActionDelegate/duplicate

Then your action element should specify a class:


<action name="list2" renderType="PDM">
<command class="wt.pdmlink.PDMLinkProduct" method="list2" windowType="page"/>
<access name="read"/>
</action>
If you didn’t specify the class in the command element of the action, there is no
guarantee that this property entry will be determined as the best match. This is
because the list2 action is provided when the user has not yet viewed a Product, so
they don’t have a context set. Therefore, Windchill can’t dynamically determine
the class to use for the lookup.
By specifying the class in the command element of the action, Windchill can
match it to the appropriate property entry.

actions.xml Elements
Listed in the following table are the valid elements and their attributes that can be
used to register an action.

Value (Default if not


Element Attribute Required specified) Description

objecttype name Yes NA A unique name for the alias to


use for the object type.
class No NA The fully qualified path to the
actual class representing this
type
action name Yes NA A unique name for the given
objecttype to identify the action

E-4 Windchill Customizer’s Guide


checkaccess No true/false Indicates to execute the
checkAvailable() method on
the class specified for the
objecttype
cad No true/false Indicates if this action is valid
only within the Wildfire
Embedded Browser.
renderType No <no- Indicates what mechanism is
value>/GENERAL/P used to determine the URL.
DM
command windowType No page/popup/ Indicates if the action will open
no_content/normal a new window or replace the
page in the current window
class No NA Indicates the command class to
use for this action if the action is
a PJL action or the class to use
in the lookup of the appropriate
URL action delegate if the
action renderType is PDM.
method No NA The method to call on the
command class if the action is a
PJL action or the selector to use
in the lookup of the appropriate
URL action delegate if the
action renderType is PDM.
access name No read/update/full Indicates what level of access of
the user should have to be able
to execute this action.

URLFactory in the JSP Environment


See The URLFactory in the Generic UI Customizations chapter on page 10-21 for
more information on the URLFactory.
There are several discrete steps required to utilize the URLFactory in the JSP
environment.
1. Create a URLFactory Bean to be used for a given scope.
2. Setup the reference point for all HREFs (from a request, Base Tags, or fully
qualified).
3. Create HREFs.

Additional Topics - Client Customization E-5


Note: There is a URLFactoryBean created by begin.jspf :
urlFactoryBean.getFactory().

Creating an URLFactory
All Windchill Java client Server Pages or Servlets should set the context by using
the WTContextBean using the code below:
<% [ ] /*** The WTContextBean is a JavaBean for use in
Java Server
Pages or Servlets that wish to use Windchill Java client
or server
APIs ***/ % [ ]> <jsp:useBean id="wtcontext"
class="wt.httpgw.WTContextBean" scope="request"
<jsp:setProperty name="wtcontext" property="request"
value="<% [ ]=request% [ ]>"/> </jsp:useBean>

Next, an URLFactory instance may be created for the current codebase by using
the useBean JSP command and setting the scope of the URLFactory (in this case
for the request, which supports JSP include commands).
<% [ ] /*** The URLFactory is a JavaBean for use in the
generation of HREFs used in Windchill HTML clients ***/ % [ ]>
<jsp:useBean id="url_factory" class="wt.httpgw.URLFactory"
scope="request" />

If a remote codebase needs to be accessed (note the request from the server) an
URLFactory object can be instantiated by first creating the bean as above, and
then recreating the URLFactory pointing it to the new codebase. (NOTE: The
codebase ends with a ’/’ marking it as a directory.)
<% [ ] /*** The URLFactory is a JavaBean for use in the
generation of HREFs used in Windchill HTML clients ***/ % [ ]>
<jsp:useBean id="url_factory" class="wt.httpgw.URLFactory"
scope="request" > <% [ ] url_factory = new wt.httpgw.URLFactory
( SomeURLToRemoteWindchill );
% [ ]> </jsp:useBean>

Setting the JSP Reference Point


The URLFactory needs to be informed of the current location, or way in which
HREFs are to be generated. This can be done using three methods;
1. Setting the context to the current request (Recommended)
2. Setting the BaseTag in the page so that all HREFs are relative to the BaseTag
3. Forcing all HREFs to be fully qualified

Current Request Context


This is the recommended approach for developers. What needs to be done is to set
the RequestURI of the URLFactory to be the request URI that was sent to the
WEBServer. This will properly support reverse proxy configurations and
firewalls. To configure URLFactory for this, utilize the setRequestURL method.

E-6 Windchill Customizer’s Guide


<% [ ]
url_factory.setRequestURL(request.getScheme()
,request.getHeader("HOST"),request.getRequestURI());
% [ ]>

Setting a BaseTag
This configuration has the advantage of allowing a user to reload a page after it
has been persisted (say to a local file system) and still have all the links work
properly. If the base is to be the Windchill Codebase then a call to
setRequestURItoBase() will suffice.
<BASE HREF="<% [ ]= url_factory.setRequestURItoBase() % [ ]>">

However in many situations, you may wish to set the base tag relative to some
point in the Windchill codebase. An example is you want to generate a search
page and have all the links be relative to some starting position. In this case, a
little more is involved. If you can obtain the current request context (i.e., you are
developing either a jsp or servlet page) then first you should set the request
information using the setRequestURL() method described above.

Setting the BaseTag Within JSP pages and Servlets


<% [ ]
// First set the request URI to be relative to the
request (thus maintaining
// the protocol, port and host information.
url_factory.setRequestURL(request.getScheme(),
request.getHeader("HOST"),
request.getRequestURI() );
// Next set the request URI to be null
(ie. to the Windchill codebase)
url_factory.setRequestURI(null);
// Now set the request URI to be relative
to the resource you desire.
url_factory.setRequestURI("wt/clients/login/
Login.html");
// Now the Base tag can be set to this resource
% [ ]> <BASE HREF="<% [
]=url_factory.getFullyQualifiedRequestURI
()% [ ]>">

Setting the BaseTag Within a Non-JSP Page or Servlet (i.e, Java code)
We will not have access to the request object in Java code that is not a servlet.
Therefore we have to set the RequestURI to be relative to initially the Windchill
codebase based on the configured host, protocol and port information and then set
the requestURI to desired resource.
...
// Set the request URI to the Windchill codebase.
url_factory.setRequestURItoBase();
// Now set the request URI to the desired resource.
url_factory.setRequestURI("wt/clients/login/Login.html");
// Now we can obtain the string for the Base Tag
String baseTag = url_factory.getFullyQualifiedRequestURI();

Additional Topics - Client Customization E-7


Forcing all HREFs to be Fully-Qualified
If there is a need to force fully qualified HREFs (such as the current
configuration) this can be accomplished using the following;
<% [ ] url_factory.setRequestURI( (java.lang.String)null ); % [
]>

Generating Links on the Page


There are five types of HREFs used in the Windchill Environment.
1. Standard resources located under the codebase.
2. Access to a Windchill Servlet via a Gateway (for example Authenticated
Gateway)
3. Access to an external source
4. Forcing a fully qualified link with a URLFactory that has a non-null request
URI
5. Creating a link from the request.getRequestURI() String

Standard Resources Under the Codebase


In order to generate links on the page, simply calling getHREF(resource) from
URLFactory will create relative HREF Strings for the desired resource base on the
RequestURI that was set earlier. The resources are all designated relative to the
Windchill Codebase. For example, to obtain a link for Login.html located in
wt/clients/login, the following line could be used:
<A HREF="<% [ ]= url_factory.getHREF( "wt/clients/login/Login.
html"
) % [ ]>"> Link to Login.html </A>

Depending on the Request Context setup above, the correct HREF String will be
returned and inserted into the output page at compile time.

Access Through a Servlet


In order to generate links via a Windchill Servlet the appropriate ServletHelper
class should be referenced. There are ServletHelpers available for the Anonymous
/ Authenticated Gateways (WindchillGW / WindchillAuthGW), and also for the
UIServlet and System Administrator (WindchillSAGW). See the
GatewayServletHelper class entry in your installed Windchill Javadoc for more
information.
<A HREF="<% [ ]= wt.httpgw.GatewayServletHelper.
buildAnonymousHREF( url_factory,
"wt.httpgw.HTTPServer", "echo", (java.lang.String)null )
% [ ]>">Windchill Echo</A>

E-8 Windchill Customizer’s Guide


Access to an External Source
To generate a link to an external source, simply make a call to getHREF as in
example 1, except explicitly define the HREF to the resource you want. Whenever
possible calls for external HREFs should be made through URLFactory to take
advantage of possible future features.
<A HREF="<% [ ]= url_factory.getHREF( "http://www.ptc.com" )
% [ ]>"> Link to PTC’s
Website</A>

Forcing a Fully Qualified Link With a URLFactory that has a Non-null Request URI
If you want to create a link that opens a file in a new window (such as through the
Javascript.open( ) method) the string must be fully qualified. However, the rest of
the links on the page may be relative.
Most getHREF() methods have a form which accepts a boolean. By using this
form, it is possible to request a fully-qualified URL from a URLFactory which is
otherwise configured to generate relative URLs.
<A HREF="<% [ ]= url_factory.getHREF( "wt/clients/login/Login.html"
, true ) % [ ]>">Fully Qualified Link</A>

Creating a Link From the Request.getRequestURI() String


This only applies to servlets and JSP Pages. The request object has a method
getRequestURI( ) which returns the path to the web resource (usually starting
after the hostname/port onward). This String includes a leading ’/’ which by
definition in the URLFactory would redefine the resource and not create a relative
link. However, there is a chance to create a relative link if the getRequestURI( )
path and the Windchill codebase are common. This is where usage of the
determineResource( ) method may be used.
<A HREF="<% [ ]= url_factory.getHREF(
url_factory.determineResource(request.getRequestURI()))% [ ]>"
> Resource Link</A>

Internationalizing JSP Pages in Windchill


With the introduction of JSP and new browser technology, it is no longer
necessary to use separate encodings for each language. Instead, a single encoding:
UTF-8 can be utilized. All JSP Pages in the Windchill environment should be
written to utilize UTF-8 as their character set. This will allow a single JSP Page to
be deployed for any language variant. (Previous versions implemented separate
language versions for all HTML templates.)

International Encoding on JSP Pages


There are two steps that are needed to develop pages properly using UTF-8.

Additional Topics - Client Customization E-9


1. To set the content type of the current page that is being processed within the
JSP Parser. The JSP page directive needs to be called with the content type
being set.
<% [ ]@ page contentType="text/html; charset=UTF-8"% [ ]>

2. Set the response content type. This will set the encoding of the HTML page
returned to the client. It should be set near the start of the JSP page (after Bean
declarations). In order to do this the following needs to be added:
<% [ ] response.setContentType( "text/html; charset=UTF-8" ); %
[ ]>

Note: The response content type method must be called before any call to
request.getParameter() is made.

Decoding UTF-8 Encoded Text


If you set the encoding as explained above, the text your code receives will be
encoded using the UTF-8 encoding. However, the Java String class uses 16-bit
integers to represent Unicode characters. You need to do the conversion from
UTF-8 to Java String in your code.

EncodingConverter

Note: See the EncodingConverter class entry in your installed Windchill Javadoc
for more information.

The EncodingConverter class (in the wt.httpgw package) contains a series of


decode() methods that may be used to efficiently decode text that has been
encoded in UTF-8 format. This must be called on ALL text that is read from
parameters that were submitted from a FORM element. There are two ways to
decode text:
The first method is to use the decode() methods of wt.httpgw.EncodingConverter
to efficiently decode text that has been encoded in UTF-8 format. This must be
called for every text entry that was submitted from a FORM element, or any
parameters that contain encoded text. This methodology supports both request
query strings and FORM data. For example:
// Create an instance of the encoding converter for the page
//
EncodingConverter encoder = new EncodingConverter
();
// Using the EncodingConverter with the default
encoding (UTF-8 )
//
String tag = encoder.decode( request.getParameter
("tag") );
// Using the EncodingConverter with a specific
encoding
//

E-10 Windchill Customizer’s Guide


String tag = encoder.decode( request.getParameter
("tag"), "UTF-8");

The second method that can be to used is the parseQueryString() method of the
URLFactory() class. Usage of the parseQueryString() method takes an encoded
query string and decodes it. The result is placed into a HashMap. The HashMap
values may then be queried using the HashMap ’get’ method. This method will
only work with Request Parameters and not form elements. For example:
// Use the URLFactory to parse the Query String
//
java.util.HashMap query_map =
url_factory.parseQueryString(

request.getQueryString() );
// Retrieve the (already decoded) string
from the hash map
//
String tag = query_map.get("tag");

Deprecation of WTURLEncoder
As of Windchill release 6.0 WTURLEncoder SHOULD NOT be used for text
encoding or decoding. This class may be removed post-R 6.0.

Encoding of Forms
By default POST submitted forms are submitted using the encoding application/x-
www-form-urlencoded. The methods provided above for decoding the text will
allow these form’s data to be written properly.
All HREFs and URLs should be generated using the URLFactory class. The
URLFactory provides methods to automatically encode any non-ASCII characters
in the query string, if a HashMap containing the parameters is provided to the
URLFactory. If a string is being passed in for a query string that has been created
within your code, you must encode it first, with a call to
EncodingConverter.encode()

Note: See the URLFactory class entry in your installed Windchill Javadoc for
more information.

Sample JSP Page


Below is a sample JSP Page that illustrates how to utilize the URLFactory, and
proper UTF-8 encoding with a HTML form. If the file is saved into your
Windchill codebase directory as sample.jsp, you can execute this sample. To see
the power of this sample try to paste different languages into the text field and
then click the button.
<HTML>
<% [ ] /*** WTContest bean for Windchill Client ***/ % [ ]>
<jsp:useBean id="wtcontext" class="wt.httpgw.WTContextBean" scope="request">
<jsp:setProperty name="wtcontext" property="request" value="<% [ ]=request% [ ]>"/>
</jsp:useBean>

Additional Topics - Client Customization E-11


<jsp:useBean id="url_factory" class="wt.httpgw.URLFactory" scope="request" >
<% [ ] // Set the URLFactory to the current page request
url_factory.setRequestURL(request.getScheme(), request.getHeader("HOST"),
request.getRequestURI());
% [ ]>
</jsp:useBean>
<% [ ]@ page contentType="text/html; charset=UTF-8" % [ ]>
<HEAD>

<% [ ]
// Set the content type for the response
response.setContentType("text/html; charset=UTF-8");
// Get the current locale for the browser that is supported by Windchill
// This to used with WTMessage.getLocalizedMessage(RESOURCE,"tagname",locale)
java.util.Locale locale = wt.httpgw.LanguagePreference.getLocale(
request.getHeader("Accept-Language") );
% [ ]>

</HEAD>

<BODY>
<h1>Sample Form</H1>
<% [ ]
String text = request.getParameter("sample_text");
if ( text != null )
{
% [ ]>

Here was the text that was submitted: <i>


<% [ ]= url_factory.decode(text) % [ ]> </I>
<BR><% [ ]= new String(text.getBytes("ISO8859_1"),"UTF-8")% [ ]>
<% [ ] } % [ ]>
<P>
<FORM METHOD="POST"
ACTION="<% [ ]=url_factory.getHREF("sample.jsp",request.
getQueryString
() ) % [ ]>" >
<% [ ]
if ( request.getParameter("sample_text") != null )
{
% [ ]>
<INPUT TYPE="text" NAME="sample_text"
VALUE="<% [ ]= url_factory.decode( text) % [ ]>">
<% [ ] }
else {
% [ ]>
<INPUT TYPE="text" NAME="sample_text" >
<% [ ] } % [ ]>
<INPUT TYPE="submit" NAME="button" VALUE="click here">
</FORM>
</BODY>
</HTML>

Localizable text on JSP pages


Any displayed text should be obtained from ResourceBundles or RbInfo files that
are language specific as defined by the Internationalization/Localization

E-12 Windchill Customizer’s Guide


techniques located here. IMPORTANT: you must not hard-code localizable text
directly on the JSP page! This would ruin the whole concept of having language-
independent JSP pages. Whenever text needs to be displayed on a JSP page, it
should be pulled in during runtime from an RbInfo file.

Additional Topics - Client Customization E-13


Using File-Handling Applets in Non-JSP Clients
For more UI flexibility and more robust handling of file upload/download/
selection than is available through straight HTML, a basic set of lightweight file-
handling applets has been provided. These applets can be used in a variety of
HTML-generating architectures, including HTML template processing, and can
be used with a variety of Windchill business objects.

The Three Applets


File selection applet
<Windchill>/codebase/wt/clients/util/FileChooserDropApplet (combined file
drop target and file browser launch button or "hyperlink" which launches
single-select or multi-select JFileChooser)
Content upload applet
<Windchill>/codebase/wt/clients/util/http/UploadApplet.java
Content download applet
<Windchill>/codebase/wt/clients/util/http/DownloadApplet.java

Advantages and Disadvantages


The primary advantages of these applets compared to straight HTML are:
1. Multiple-file handling - can handle multiple files in a single
select/upload/download operation.
2. Drag-and-drop file selection - can drag and drop one or more files from the
desktop or Windows Explorer into a Windchill UI
3. Configurability - can configure file select/upload/download behavior through
user preferences.
4. Checksum handling - can persist/compare checksums to avoid unnecessary
uploads.
5. Deferred upload and remembered values - can be used to implement multi-
page wizard or clerk which maintains the selected upload filepaths when
switching between pages, and defers all file uploads until all pages of
wizard/clerk are completed.
6. Pre-fillable file selection values - ability to update a previously-uploaded file
without needing to re-browse for local filepath.
The primary disadvantages of these applets compared to straight HTML are the
necessary installation prerequisites for each user.
1. Plug-in - they require the one-time installation of a particular Java plug-in on
the client machine.
2. Bootstrap loader - for certain secure server configurations, they require the
one-time installation to the client machine of the Windchill bootstrap loader

E-14 Windchill Customizer’s Guide


which enables the RMI tunneling necessary for the applet to communicate
with the server
3. Java class archive - they require the one-time download of a Java class
archive, which creates a noticeable loading delay the first time an applet is
accessed from a given client machine. Subsequent visits to the same page are
much faster because the class archive is cached locally by the Java plug-in.

The File Selection Applet

File Selection
There are two ways to choose one or more files for upload in Windchill.
1. File Browse: Launch a file browser from the Windchill UI and navigate to the
desired file(s).
2. Drag-and-Drop: Drag one or more file icons from the desktop or Windows
Explorer onto a drop target in the Windchill UI.

File Browse Launchers


There are two looks for the applet button that launches a Java file browser. The
"button" look is typically used in a single-select situation where the selected file
will be written to an adjacent HTML textfield, in order to look and act like an
HTML file input (only smarter!).

Button look:
<param name="buttonLook" value="true">

The "hyperlink with icon" look is typically used in a multi-select situation where
each selected file will result in another row added to a table.

Additional Topics - Client Customization E-15


Hyperlink-with-icon look:
<param name="buttonLook" value="false">
<param name="imageFilename" value="wtcore/images/attach_add.gif">
<param name="multiSelect" value="true">

Drag-and-Drop targets
The presence/absence of a file drop target next to the file browse launcher is
determined by the following parameter (true means drop target, false means no
drop target):
<param name="acceptFileDrop" value="true">

When using a drop target, you will need to provide a pair of images to use for the
drop target's normal state and active (dragged-over) state.
The following images are provided by Windchill for this purpose:
Normal:
<Windchill>/codebase/wtcore/images/droptarget.gif

E-16 Windchill Customizer’s Guide


Active:
<Windchill>/codebase/wtcore/images/droptarget_active.gif

Processing File Selection Output


The file selection applet will output the selected filepaths to the page by calling a
Javascript method of specified signature: setPath (newValue, fileSep,
pathComplete). The name of the method may be changed by setting an applet
parameter, but the number and type of arguments must conform to the applet's
expectations (see examples).
For single-select situations, the Javascript method typically takes the result string
from an applet, verifies that only a single file has been selected, then calls another
method that writes the filepath to a form field.
For multiple-select situations, the Javascript method typically takes the result
string from an applet, then calls another method that performs parsing and/or
concatenation on the result string in order to update hidden field values and
submit the page to some sort of processor that generates an additional row in the
table for each file selected.
Various browser and encoding issues may affect handling of the backslash file
separators in Windows filepaths. Some sort of escaping or replacement of these
file separators is recommended, such as is performed by the method
CheckFilePathSeparators in the file
<Windchill>/codebase/templates/doc/WTDocumentSharedFunctions.js.

Sample Single-Select Javascript for FileChooserDropApplet


var DELIM = ";;;qqq"; // same as applet's delim parameter
var appletString = "";

function setPathFromApplet(newValue,fileSep,pathComplete) {
appletString = appletString + newValue;
if ( pathComplete != null && pathComplete == "true" ) {
window.focus();
var endPos = newValue.indexOf( DELIM, 0 );
if ( endPos >= 0 ) {
wfalert( tooManyFilesDroppedMsg );
} else {
setPath(CheckFilePathSeparators(appletString,fileSep));
}
appletString = "";
}
}

Additional Topics - Client Customization E-17


Sample Multi-Select Javascript for FileChooserDropApplet
var DELIM = ";;;qqq"; // same as applet's delim parameter
var appletString = "";

function setPath(newValue,fileSep,pathComplete) {
appletString = appletString + newValue;
if ( pathComplete != null && pathComplete == "true" ) {
window.focus();
submitNewAttachments(CheckFilePathSeparators(appletString,fileSep) );
appletString = "";
}
}

Configuring File Select Behavior - User Preferences


The Default Local Directory preference (node=/wt/content key= workspacePath)
determines where the file browse dialog will initially be launched. Users who
have a particular directory where they like to keep all their Windchill files might
like to set this preference to that directory. If no value is specified, or if the
specified path does not exist on the local machine, then a default directory will be
used as specified by the environment variables of the local machine's operating
system.

E-18 Windchill Customizer’s Guide


FileChooserDropApplet Parameters
Parameter
Name Sample Value Description

java_codebase http://machinename.ptcnet.ptc.com/Windchill/ Provided by taglib generator

type application/x-java-applet;version=1.4 Provided by taglib generator

java_code wt/clients/util/FileChooserDropApplet Applet location in codebase – never


changes

cache_archive "contentCust.jar, contentDSU.jar, Java archives containing the


contentFCS.jar, lib/HTTPClient.jar, classfiles used by this applet –
content3rdParty.jar, content.jar" typically never changes

java_archive wt/security/security.jar Never changes

cabinets wt/security/security.cab Never changes

cache_option Plugin Never changes

SCRIPTABLE true Never changes

MAYSCRIPT true Never changes

wt.context.locale en_US Locale of user’s browser

bgcolor 15066585 Decimal version of desired


background color (i.e. what is seen
around the button), typically
matches the background color of
the page or table cell where the
applet is located

bgcoloractive 15066585 (Optional) Decimal version of


desired background color (i.e. what
is seen around the button) when
button is active. Defaults to same
as bgcolor.

buttoncolor 13421772 (Optional) Decimal version of


desired button color. Defaults to
same as bgcolor.

buttoncoloractive 15066585 (Optional) Decimal version of


desired button color when button is
active. Defaults to same as bgcolor.

jsSetMethod setPathFromMultiSelectApplet (Optional) Name of Javascript


method to be invoked from applet
with the selected filepath value(s).
Defaults to "setPath".

buttonLabel "Browse... ", "Add Attachments... ", "Add Files... Label for button or "hyperlink"
" seen in HTML page

Additional Topics - Client Customization E-19


acceptFileDrop true, false Normally true, change to false if
you don’t want a drop target
dropImageFilen wtcore/images/droptarget.gif Image displayed when drop
ame target is idle
dropImageFilena wtcore/images/droptarget_active.gif Image displayed when drop target
meActive is dragged-over

buttonLook true, false Normally true for single-select


usage, normally false for multi-
select usage

imageFilename wtcore/images/attach_add.gif (Optional) Icon shown above


"hyperlink" if buttonLook is false

actionLabel "Open", "Choose File", "Select Attachments" (Optional) Label for window and
action button on file browser dialog

defaultPath C:/temp/MyWindchillFiles/ (Optional) Normally retrieved from


workspacePath user preference
setting, determines where file
browse dialog initially launches.

multiSelect true, false (Optional) Defaults to false for


single-select, change to true for
multi-select.

delim ;;;zzz (Optional) Delimiter string used to


separate filepaths if multiSelect is
true

debug true, false (Optional) Defaults to false, change


to true for Java Console output
during processing

Sample HTML for FileChooserDropApplet

Single-select, button look (Create/Update/Checkin Document primary content)

<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet"


width="200" height="40"
codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4_2-windows-
i586.cab#Version=1,4,2">
<param name="java_code" value="wt/clients/util/FileChooserDropApplet">
<param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/">
<param name="java_archive" value="wt/security/security.jar">
<param name="type" value="application/x-java-applet;version=1.4">
<param name="SCRIPTABLE" value="true">
<param name="actionLabel" value="Open">
<param name="debug" value="false">
<param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar,
lib/HTTPClient.jar, content3rdParty.jar, content.jar">
<param name="dropImageFilenameActive" value="wtcore/images/droptarget_active.gif">
<param name="buttonLabel" value="Browse...">

E-20 Windchill Customizer’s Guide


<param name="acceptFileDrop" value="true">
<param name="MAYSCRIPT" value="true">
<param name="buttonLook" value="true">
<param name="cabinets" value="wt/security/security.cab">
<param name="dropImageFilename" value="wtcore/images/droptarget.gif">
<param name="cache_option" value="Plugin">
<param name="wt.context.locale" value="en_US">
<param name="bgcolor" value="15066585">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="200"
height="40" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html"
java_code="wt/clients/util/FileChooserDropApplet"
java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/"
java_archive="wt/security/security.jar"
SCRIPTABLE="true"
actionLabel="Open"
debug="false"
cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar,
content3rdParty.jar, content.jar"
dropImageFilenameActive="wtcore/images/droptarget_active.gif"
buttonLabel="Browse..."
acceptFileDrop="true"
buttonLook="true"
cabinets="wt/security/security.cab"
dropImageFilename="wtcore/images/droptarget.gif"
cache_option="Plugin"
wt.context.locale="en_US"
bgcolor="15066585"
><NOEMBED>
</COMMENT>
</NOEMBED></EMBED>
</OBJECT>

Multi-select, hyperlink-with-icon look (Create/Update Document attachments, Create Multiple


Documents)
<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet"
width="300" height="50"
codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4_2-windows-
i586.cab#Version=1,4,2">
<param name="java_code" value="wt/clients/util/FileChooserDropApplet">
<param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/">
<param name="java_archive" value="wt/security/security.jar">
<param name="type" value="application/x-java-applet;version=1.4">
<param name="SCRIPTABLE" value="true">
<param name="actionLabel" value="Open">
<param name="debug" value="false">
<param name="delim" value=";;;zzz">
<param name="multiSelect" value="true">
<param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar,
lib/HTTPClient.jar, content3rdParty.jar, content.jar">
<param name="dropImageFilenameActive" value="wtcore/images/droptarget_active.gif">
<param name="acceptFileDrop" value="true">
<param name="buttonLabel" value="Add+Attachment">
<param name="MAYSCRIPT" value="true">
<param name="imageFilename" value="wtcore/images/attach_add.gif">
<param name="cabinets" value="wt/security/security.cab">

Additional Topics - Client Customization E-21


<param name="dropImageFilename" value="wtcore/images/droptarget.gif">
<param name="cache_option" value="Plugin">
<param name="wt.context.locale" value="en_US">
<param name="bgcolor" value="15066585">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="300"
height="50" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html"
java_code="wt/clients/util/FileChooserDropApplet"
java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/"
java_archive="wt/security/security.jar"
SCRIPTABLE="true"
actionLabel="Open"
debug="false"
delim=";;;zzz"
multiSelect="true"
cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar,
content3rdParty.jar, content.jar"
dropImageFilenameActive="wtcore/images/droptarget_active.gif"
acceptFileDrop="true"
buttonLabel="Add+Attachment"
imageFilename="wtcore/images/attach_add.gif"
cabinets="wt/security/security.cab"
dropImageFilename="wtcore/images/droptarget.gif"
cache_option="Plugin"
wt.context.locale="en_US"
bgcolor="15066585"
><NOEMBED>
</COMMENT>
</NOEMBED></EMBED>
</OBJECT>

The Upload Applet


UploadApplet is an "invisible" applet, that is, a 2-pixel by 2-pixel applet whose
background color matches the page. It starts the upload as soon as the page has
loaded and the applet has initialized, using the values in the applet parameters.
This behavior makes UploadApplet most appropriate for use in a "processing"
page or popup rather than an interactive form page.
In order to perform an upload, the applet needs to know what content item to
upload and an upload destination where it should be uploaded. The item is
described by a target type (FILE, URL or NONE) and a target. Items of type FILE
have a filepath as a target, items of type URL have a URL string as a target. The
upload destination is described by an upload destination URL. The only
Windchill-supported use of UploadApplet is to upload content to an upload URL
that leads to the saveContent method of the wt.content.ContentHttp class in the
Windchill Method Server.

Caution: While it may be possible to use UploadApplet to upload content to


some other type of upload URL, such as an Info*Engine URL or even a
totally non-Windchill URL, any such "off-label" use of UploadApplet is NOT
considered supported by Windchill's tech support or R & D.

E-22 Windchill Customizer’s Guide


Initial Upload of Primary and/or Secondary Content to a Single Windchill Object
When initially uploading to a Windchill object, such as during a Create Document
or Create Document Template, or when updating a Windchill object which has
not previously had content, there is no existing Windchill content item yet in the
database so a new content item object will have to be created. This is indicated for
primary content by setting the callingAction parameter to "create", and for
secondary content by indicating "newfile" in place of the OID within the
concatenated attachments parameter.

Initial Upload of Multiple Primary Files to Multiple Windchill Objects


When creating multiple documents, multiple primary files can be uploaded to
multiple destinations with a single instance of UploadApplet. This is done by
setting the "target" parameter to a concatenated list of target filepaths, and setting
the "uploadURL" parameter to a concatenated list of uploadURLs corresponding
in quantity and order to the concatenated "target" values.

Subsequent Upload to Update/Replace/Remove Content of a Windchill Object


When uploading to a single Windchill object that already has content, the about-
to-be-uploaded primary file needs to be validated and compared to the currently-
persisted primary content item, to avoid unnecessary uploads. This is indicated by
setting the callingAction parameter to "updateReplace" and providing persisted
filename and checksum information about the existing content item. The result of
the validation/comparison, along with certain user preference values, determines
whether to upload the file, skip the upload, or prompt the user for an upload
decision or different filepath. (Secondary content is validated but no comparisons
are performed.)
Existing content items, both primary and secondary, need to have their OID
provided so that the upload modifies the content of the existing content item rather
than creating an additional content item. When removing primary or secondary
content, the OID needs to be provided so that the correct existing content item can
be removed. This is indicated for primary content by setting the oidString
parameter to the OID of the current primary content item, and for secondary
content by providing the OID of the to-be-removed-or-replaced attachment
content item within the concatenated attachments parameter.

Caution: The OID must be in the format of


"wt.content.ApplicationData:1437923". Attempting to use an OID with a
different format, such as "OR:wt.content.ApplicationData:1437923", will
result in server-side failure to persist the uploaded object.

Handling Success/Error Navigation and Feedback on Uploads


To enable UploadApplet to be used in a variety of architectures/situations but
maintain feedback behavior and language appropriate to each usage,
UploadApplet allows the parameters and the page Javascript to define the
appropriate feedback display handling and post-upload navigation.

Additional Topics - Client Customization E-23


When uploading to a single location, the selected primary content filepath is
validated, preference values are checked and the user is prompted if necessary to
decide what to do should the selected filepath be invalid. If the file is valid or the
preferences and/or user prompt authorize skipping the upload, then the upload is
considered successful, and the applet will forward to the "completionUrl" and/or
"completionJSMethod" upon completion (if both are provided, completionUrl
will be passed into completionJSMethod as an argument value). In Windchill
Foundation & PDM, this typically submits to post-processing code followed by
the properties page for the document. In Windchill PDMLink, this typically
submits to post-processing code followed by closing the wizard window. In the
absence of both completionUrl and completionJSMethod parameter values,
completionJSMethod will default to "displayInvalidPaths".

Note: The "uploadFeedback" argument provided to the completionJSMethod


will be a value from the class wt.clients.util.http.UploadConstants indicating
whether some kind of non-upload completion was reached (NO_UPLOAD,
FILE_NOT_FOUND, FILE_UNCHANGED, DECLINED_UPLOAD). This
can be used for customizing a feedback status message for a non-error
outcome.

If the file is invalid and the preferences and/or user prompt do not authorize
skipping the upload, or if the file is valid but the upload is unsuccessful, or if the
user cancels, then the applet will forward to the "failureUrl" and/or
"failureJSMethod" (if both are provided, failureUrl will be passed into
failureJSMethod as an argument value). This typically displays some sort of error
feedback message (unless cancelled) and returns to the form where the primary
filepath was originally selected.
When performing a multiple-file upload, such as multiple primary files or
attachments, individual feedback is not provided on each file. Instead, all valid
files are uploaded and a list of all invalid filepaths is compiled. When the upload
is complete, this list of invalid filepaths is sent as an argument to a designated
Javascript method, along with the appropriate URL. When uploading multiple
primary files, this will always be the Javascript method and URL specified in the
applet parameters for the completion case. When uploading secondary files, the
method and URL may be from either the completion or failure cases, depending
on the outcome of the selected primary content file upload.

Sample Javascript for UploadApplet Feedback and Navigation

Note: This Javascript assumes the existence of a hidden HTML form in the page
named <form name>, containing named hidden fields <checksum form field
name> and <uploadFeedback form field name>. The real names of this form and
these fields should be substituted into this Javascript before use.

<SCRIPT language=javascript>

// localized display messages retrieved from resource bundles

E-24 Windchill Customizer’s Guide


var invalidPathMessage = "The following files were not uploaded due to invalid
filepaths:";
var uploadFailureMessage = "A problem occurred while uploading content to
server. Please notify administrator if this problem continues.";

function uploadCompleted( invalidPaths, nextURL, newChecksum, uploadFeedback ) {


document.<form name>.<checksum form field name>.value = newChecksum;
if ( uploadFeedback != null && uploadFeedback.length > 0 ) {
\document.<form name>.<uploadFeedback form field name>.value =
uploadFeedback;
}
if ( invalidPaths != null && invalidPaths.length > 0 ) {
alert( invalidPathMessage + invalidPaths );
}
if ( nextURL != null && nextURL.length > 0 && nextURL != "null" ) {
submitForm( nextURL );
} else {
submitForm( propertiesPageURL ); // generated value
}
}

function uploadFailed( invalidPaths, nextURL, cancelled ) {


if ( invalidPaths != null && invalidPaths.length > 0 ) {
alert( invalidPathMessage + invalidPaths );
}

if ( !cancelled ) {
alert( uploadFailureMessage );
}

if ( nextURL != null && nextURL.length > 0 && nextURL != "null" ) {


submitForm( nextURL );
} else {
submitForm( previousPageURL ); // generated value
}
}

function displayInvalidPaths( invalidPaths, nextURL ) {


alert( invalidPathMessage + invalidPaths );
location = nextURL;
}

</SCRIPT>

Persisting Information After an Upload


When uploading to a single document, the primary file checksum should be
persisted after a successful upload, for use in future upload comparisons. To
minimize network traffic, the checksum is appended to the end of the
completionURL query string so that it can be processed in the same server hit as
the request for the completion page. The server-side delegate or JSP that handles
the completionURL request should check whether the "uploaded" flag on the
query string is set to "true", and if so should persist the "checksum" query string
value to the context object's primary content item.

Additional Topics - Client Customization E-25


Checksum persistence code:
Here are the essential steps for persisting the checksum (in reality, there may also
be some error handling). The context object has to be a FormatContentHolder,
such as a WTDocument.
Properties props = getQueryData();
String uploaded = (String)props.get("uploaded");
if ( uploaded != null && uploaded.equalsIgnoreCase("true") ) {
long checksum = 0;
checksum = Long.parseLong((String)props.get("checksum"));
FormatContentHolder holder =
(FormatContentHolder)getContextObj();
holder =
(FormatContentHolder)ContentHelper.service.getContents(holder);
ContentItem item = ContentHelper.getPrimary( holder );

if ( item instanceof ApplicationData ) {


ApplicationData app = (ApplicationData)item;
app.setChecksum( checksum );
ContentHelper.service.updateAppData( holder, app );
}
}

Configuring Upload Behavior - System Properties


The optional "validEmptyFile" and "uploadImpl" applet parameters are typically
set by retrieving the wt.properties values for "wt.content.validEmptyFile" and
"wt.content.uploadImpl", respectively.
The validEmptyFile parameter allows a particular implementation to determine
whether or not a 0-size "empty" file is considered a valid content file or not - the
default value is "false", that an empty file is not considered valid. This value
typically will not be changed unless Windchill is being used to automate data
storage from some other application that generates 0-size placeholder files.
The uploadImpl parameter permits switching between RMI and HTTP upload
mechanisms - the default value is "rmi" which provides full-functionality
Windchill upload including full support of file vault caching and content
replication. The other alternative is "http" which permits uploading to a non-
Windchill URL but has severe limitations in both functionality and performance.
This value typically will not be changed at the wt.properties level due to loss of
functionality, but can be overridden at the page level by setting the applet
parameter to allow an isolated unsupported instance of UploadApplet uploading
to a non-RMI upload URL, without losing the RMI upload functionality in all
other instances of UploadApplet.

Caution: Changing the value of the wt.content.uploadImpl wt.properties value or


uploadImpl applet parameter away from the default value is possible but is NOT
officially supported - use at your own risk.

E-26 Windchill Customizer’s Guide


Configuring Upload Behavior - User Preferences
The upload applet knows how to compare the new primary content filepath with
the previously-persisted filename/checksum, and how to make sure the new
filepath is valid, but the resulting behavior is determined by parameters that are
typically set by the individual user's preferences.
The Changed File Behavior preference (node=/wt/content key=
uploadIfFileChanged) determines whether changes to the primary file are
automatically uploaded, or whether the user wants to have the option to accept the
upload or not. Most users will prefer to automatically upload a changed file
without prompting, but some users who frequently do updates and checkins for
metadata or attachments reasons might prefer the ability to be prompted in case
the changes they're making to the primary content aren't yet ready to be checked
in for others to see.
The File Not Found Behavior preference (node=/wt/content
key=continueIfFileNotFound) determines whether an invalid filepath means a
failure condition or not. Most users will prefer to be notified of an invalid filepath
so that they can correct the selection, but some users who frequently do updates
and checkins for metadata or attachments reasons might set their download
preferences to automatically skip the primary content download on checkout and
set this upload preference to automatically skip the upload on update/checkin if
the primary content file doesn't exist locally.
The Unchanged File Behavior preference (node=/wt/content key=
continueIfFileUnchanged) determines whether the absence of changes to the
primary file automatically means to skip the upload as unnecessary, or whether
the user wants to be notified and have the option to skip the upload or select a
different primary file. Most users will only have a single local copy of the primary
file and thus will prefer to skip the upload if the primary content hasn't changed,
but users who routinely edit a copy of the primary content file in a different
location or under a different filename might want to have the option to be
reminded in case they accidentally attempt to upload the original file rather than
the changed file.

Additional Topics - Client Customization E-27


Upload Applet Parameters
Parameter Name Sample Value Description

java_codebase http://machinename.ptcnet.ptc.com/Windch Provided by taglib generator


ill/

type application/x-java-applet;version=1.4 Provided by taglib generator

java_code wt/clients/util/UploadApplet Applet location in codebase – never


changes

cache_archive "contentCust.jar, contentDSU.jar, Java archives containing the classfiles


contentFCS.jar, lib/HTTPClient.jar, used by this applet
content3rdParty.jar, content.jar"

java_archive wt/security/security.jar Never changes

cabinets wt/security/security.cab Never changes

cache_option Plugin Never changes

SCRIPTABLE true Never changes

MAYSCRIPT true Never changes

wt.context.locale en_US Locale of user’s browser

bgcolor 16777215 Decimal version of desired


background color, typically matches
the background color of the page or
table cell where the applet is located

removable true Never changes

target C:/Temp/MyFolder/Sample.jpg Local filepath(s) to the new primary


content item(s) to be uploaded

targetType FILE, URL, NONE Category of newly-selected primary


content

uploadURL http://mecasey03d.ptcnet.ptc.com/Windchil URL(s) to accept the upload,


l/servlet/WindchillAuthGW/wt.content.Con typically leads to saveContent
tentHttp/saveContent?wt.doc.WTDocument method of wt.content.ContentHttp in
%3A656270 the Windchill Method Server

docOperation create, update Refers to context document – create if


this upload takes place as part of the
initial creation of the document,
update if this is a subsequent update
or checkin

callingAction create, updateReplace Refers to primary content item -


create if there is currently no persisted
primary content item, updateReplace
if there is already a persisted primary
content item

E-28 Windchill Customizer’s Guide


oidString wt.content.ApplicationData:656261 On updateReplace, the OID of the
persisted primary content item

attachments FILE;;;qqqnewfile;;;qqqC:\TEMP\ Type, content item OID (if any),


DgadReq.doc;;;qqqADD;;;zzzURL;;;qqqne filepath/URL, description (if any) and
wURL;;;qqqwww.amazon.com;;;qqq;;;qqq action for any attachments to be
ADD;;;zzzFILE;;;qqqwt.content.Applicatio added, removed or replaced.
nData:656293;;;qqqC:\TEMP\ Attachments are separated by
MyDoc.doc;;;qqqREPLACE;;;zzzURL;;;qq contentRecordDelim value,
qwt.content.URLData:656295;;;qqqhttp://w individual fields for each attachment
ww.askjeeves.com;;;qqqAsk Jeeves are separated by contentDelim value
website;;;qqqREPLACE;;;zzzFILE;;;qqqwt.
content.ApplicationData:656902;;;qqq;;;qq
qREMOVE;;;zzzURL;;;qqqwt.content.URL
Data:656904;;;qqq;;;qqqREMOVE

multipleQuantity 3 (Optional) Number of different


primary files/destinations

contentDelim ;;;qqq (Optional) Delimiter within


attachments entries and between
multiple-upload targets/uploadURLs,
defaults to ;;;qqq

contentRecordDelim ;;;zzz (Optional) Delimiter used between


separate attachments entries, defaults
to ;;;zzz

completionJSMethod uploadCompleted (Optional) Methodname of Javascript


method to be called if upload doesn’t
error out

completionUrl "http://mecasey03d.ptcnet.ptc.com/Windchi (Optional) URL to follow if upload


ll/servlet/WindchillAuthGW/wt.enterprise. doesn’t error out
URLProcessor/invokeAction?action=Create
DocCloseWindow&class=wt.doc.WTDocu
ment&OID=VR%3Awt.doc.WTDocument
%3A288876&refresh=true&formName=Cr
eateDocumentWizard">

failureJSMethod uploadFailed (Optional) Methodname of Javascript


method to be called if upload errors
out

failureUrl "http://mecasey03d.ptcnet.ptc.com/Windchi (Optional) URL to follow if upload


ll/servlet/WindchillAuthGW/wt.enterprise. errors out
URLProcessor/invokeAction?nextAction=
CreateDocument2&action=CreateDocumen
tUploadFailure&class=wt.doc.WTDocume
nt&OID=VR%3Awt.doc.WTDocument%3
A288876&uploaded=false&formName=Cr
eateDocumentWizard

Additional Topics - Client Customization E-29


checksum 3774325531 (Optional on updateReplace) The
checksum from previous upload of
persisted primary content item

fileName MyDoc.doc (Optional on updateReplace) The


filename of the persisted primary
content item

uploadedFromPath C:/temp/MyDoc.doc (Optional on updateReplace) The


filepath from previous upload of
persisted primary content item

continueIfFileNotFo true, false (Optional on updateReplace)


und Determines whether to automatically
skip the upload and keep current
primary content if the selected file
cannot be found, normally retrieved
from user preference setting

continueIfFileUncha true, false (Optional on updateReplace)


nged Determines whether to automatically
skip the upload and keep current
primary content if the selected file has
not changed since the previous
upload, normally retrieved from user
preference setting

uploadIfFileChanged true, false (Optional on updateReplace)


determines whether to automatically
upload the file if it has changed since
the previous upload, normally
retrieved from user preference setting

workspacePath C:/temp/MyWindchillFiles/ (Optional) Normally retrieved from


user preference setting

validEmptyFile true, false (Optional) Normally false, change to


true if you want to permit 0-size files
to be considered valid Windchill
content

uploadImpl rmi, http (Optional) Defaults to rmi, change to


http only for unsupported uses of this
applet.

debug true, false (Optional) Defaults to false, change


to true for Java Console output during
processing

E-30 Windchill Customizer’s Guide


Sample HTML for UploadApplet

Create Document (add primary/attachment files to single upload destination)

<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet"


width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall-
1_4_2-windows-i586.cab#Version=1,4,2">
<param name="java_code" value="wt/clients/util/http/UploadApplet">
<param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/">
<param name="java_archive" value="wt/security/security.jar">
<param name="type" value="application/x-java-applet;version=1.4">
<param name="bgcolor" value="16777215">
<param name="validEmptyFile" value="false">
<param name="oid" value="">
<param name="SCRIPTABLE" value="true">
<param name="callingAction" value="create">
<param name="cache_option" value="Plugin">
<param name="MAYSCRIPT" value="true">
<param name="checksum" value="">
<param name="contentRecordDelim" value=";;;zzz">
<param name="continueIfFileNotFound" value="false">
<param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar,
lib/HTTPClient.jar, content3rdParty.jar, content.jar">
<param name="uploadedFromPath" value="">
<param name="completionUrl"
value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.enterp
rise.URLProcessor/invokeAction?action=CreateDocCloseWindow&class=wt.doc.WTDocument&
OID=VR%3Awt.doc.WTDocument%3A288876&refresh=true&formName=CreateDocumentWizard">
<param name="workspacePath" value="">
<param name="docOperation" value="create">
<param name="debug" value="false">
<param name="failureUrl"
value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.enterp
rise.URLProcessor/invokeAction?nextAction=CreateDocument2&action=CreateDocumentUplo
adFailure&class=wt.doc.WTDocument&OID=VR%3Awt.doc.WTDocument%3A288876&uploaded=fals
e&formName=CreateDocumentWizard">
<param name="uploadIfFileChanged" value="true">
<param name="targetType" value="">
<param name="cabinets" value="wt/security/security.cab">
<param name="continueIfFileUnchanged" value="true">
<param name="oidString" value="">
<param name="contentDelim" value=";;;qqq">
<param name="wt.context.locale" value="en_US">
<param name="delim" value=";;;qqq">
<param name="uploadURL"
value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.conten
t.ContentHttp/saveContent?wt.doc.WTDocument%3A288877">
<param name="removable" value="true">
<param name="attachments" value="FILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\New
Microsoft Excel Worksheet.xls;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\
MyFolder\New Microsoft PowerPoint
Presentation.ppt;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\New
Microsoft Word Document.doc;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\
New Text Document.txt;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\New
WinZip File.zip;;;qqqADD">
<param name="fileName" value="">

Additional Topics - Client Customization E-31


<param name="target" value="c:\temp\MyDoc.doc">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2"
height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html"
java_code="wt/clients/util/http/UploadApplet"
java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/"
java_archive="wt/security/security.jar"
bgcolor="16777215"
validEmptyFile="false"
oid=""
SCRIPTABLE="true"
callingAction="create"
cache_option="Plugin"
checksum=""
contentRecordDelim=";;;zzz"
continueIfFileNotFound="false"
cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar,
content3rdParty.jar, content.jar"
uploadedFromPath=""
completionUrl="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/w
t.enterprise.URLProcessor/invokeAction?action=CreateDocCloseWindow&class=wt.doc.WTD
ocument&OID=VR%3Awt.doc.WTDocument%3A288876&refresh=true&formName=CreateDocumentWiz
ard"
workspacePath=""
docOperation="create"
debug="false"
failureUrl="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.e
nterprise.URLProcessor/invokeAction?nextAction=CreateDocument2&action=CreateDocumen
tUploadFailure&class=wt.doc.WTDocument&OID=VR%3Awt.doc.WTDocument%3A288876&uploaded
=false&formName=CreateDocumentWizard"
uploadIfFileChanged="true"
targetType=""
cabinets="wt/security/security.cab"
continueIfFileUnchanged="true"
oidString=""
contentDelim=";;;qqq"
wt.context.locale="en_US"
delim=";;;qqq"
uploadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.co
ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A288877"
removable="true"
attachments="FILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\New Microsoft Excel
Worksheet.xls;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\New Microsoft
PowerPoint Presentation.ppt;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\
New Microsoft Word Document.doc;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\
MyFolder\New Text Document.txt;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\
MyFolder\New WinZip File.zip;;;qqqADD"
fileName=""
target="c:\temp\MyDoc.doc"
><NOEMBED>
</COMMENT>
</NOEMBED></EMBED>
</OBJECT>

E-32 Windchill Customizer’s Guide


Create Document (add primary/attachment URLs to single upload destination)

<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet"


width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall-
1_4_2-windows-i586.cab#Version=1,4,2">
<param name="java_code" value="wt/clients/util/http/UploadApplet">
<param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/">
<param name="java_archive" value="wt/security/security.jar">
<param name="type" value="application/x-java-applet;version=1.4">
<param name="bgcolor" value="16777215">
<param name="validEmptyFile" value="false">
<param name="oid" value="">
<param name="SCRIPTABLE" value="true">
<param name="callingAction" value="create">
<param name="cache_option" value="Plugin">
<param name="MAYSCRIPT" value="true">
<param name="checksum" value="">
<param name="contentRecordDelim" value=";;;zzz">
<param name="continueIfFileNotFound" value="false">
<param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar,
lib/HTTPClient.jar, content3rdParty.jar, content.jar">
<param name="completionJSMethod" value="uploadCompleted">
<param name="uploadedFromPath" value="">
<param name="completionUrl" value="">
<param name="workspacePath" value="">
<param name="docOperation" value="create">
<param name="failureJSMethod" value="uploadFailed">
<param name="debug" value="false">
<param name="failureUrl" value="">
<param name="uploadIfFileChanged" value="true">
<param name="targetType" value="URL">
<param name="cabinets" value="wt/security/security.cab">
<param name="continueIfFileUnchanged" value="true">
<param name="oidString" value="">
<param name="contentDelim" value=";;;qqq">
<param name="wt.context.locale" value="en_US">
<param name="delim" value=";;;qqq">
<param name="uploadURL"
value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.conten
t.ContentHttp/saveContent?wt.doc.WTDocument%3A656270">
<param name="removable" value="true">
<param name="fileName" value="">
<param name="attachments" value="URL;;;qqqnewURL;;;qqqwww.google.com;;;qqqGoogle
search engine;;;qqqADD;;;zzzURL;;;qqqnewURL;;;qqqwww.cnn.com;;;qqq;;;qqqADD">
<param name="target" value="www.ptc.com">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2"
height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html"
java_code="wt/clients/util/http/UploadApplet"
java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/"
java_archive="wt/security/security.jar"
bgcolor="16777215"
validEmptyFile="false"
oid=""
SCRIPTABLE="true"
callingAction="create"
cache_option="Plugin"

Additional Topics - Client Customization E-33


checksum=""
contentRecordDelim=";;;zzz"
continueIfFileNotFound="false"
cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar,
content3rdParty.jar, content.jar"
completionJSMethod="uploadCompleted"
uploadedFromPath=""
completionUrl=""
workspacePath=""
docOperation="create"
failureJSMethod="uploadFailed"
debug="false"
failureUrl=""
uploadIfFileChanged="true"
targetType="URL"
cabinets="wt/security/security.cab"
continueIfFileUnchanged="true"
oidString=""
contentDelim=";;;qqq"
wt.context.locale="en_US"
delim=";;;qqq"
uploadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.co
ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A656270"
removable="true"
fileName=""
attachments="URL;;;qqqnewURL;;;qqqwww.google.com;;;qqqGoogle search
engine;;;qqqADD;;;zzzURL;;;qqqnewURL;;;qqqwww.cnn.com;;;qqq;;;qqqADD"
target="www.ptc.com"
><NOEMBED>
</COMMENT>
</NOEMBED></EMBED>
</OBJECT>

Create Multiple Documents (add primary files to multiple upload destinations)

<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" width="2" height="2"


codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4_2-windows-
i586.cab#Version=1,4,2">
<param name="java_code" value="wt/clients/util/http/UploadApplet.class">
<param name="java_codebase" value="http://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700">
<param name="java_archive" value="wt/security/security.jar">
<param name="type" value="application/x-java-applet;version=1.4">
<param name="bgcolor" value="16777215">
<param name="oid" value="">
<param name="SCRIPTABLE" value="true">
<param name="multipleQuantity" value="3">
<param name="callingAction" value="create">
<param name="cache_option" value="Plugin">
<param name="type" value="application/x-java-applet">
<param name="MAYSCRIPT" value="true">
<param name="contentRecordDelim" value=";;;zzz">
<param name="continueIfFileNotFound" value="false">
<param name="cache_archive" value="lib/HTTPClient.jar, contentCust.jar,
contentDSU.jar, contentFCS.jar, content3rdParty.jar, content.jar">
<param name="jreversion" value="1.4">
<param name="completionJSMethod" value="completion">
<param name="uploadedFromPath" value="">

E-34 Windchill Customizer’s Guide


<param name="workspacePath" value="">
<param name="failureJSMethod" value="failure">
<param name="debug" value="true">
<param name="java_archive" value="wt/security/security.jar">
<param name="uploadIfFileChanged" value="true">
<param name="targetType" value="">
<param name="cabinets" value="wt/security/security.cab">
<param name="continueIfFileUnchanged" value="true">
<param name="java_code" value="wt/clients/util/http/UploadApplet">
<param name="contentDelim" value=";;;qqq">
<param name="wt.context.locale" value="en_US">
<param name="delim" value=";;;qqq">
<param name="uploadURL"
value="http://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700/servlet/WindchillAuthGW/wt.co
ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A20350;;;qqqhttp://lqkohpsh.ptcnet
.ptc.com:2801/PDMLink700/servlet/WindchillAuthGW/wt.content.ContentHttp/saveContent
?wt.doc.WTDocument%3A20335;;;qqqhttp://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700/serv
let/WindchillAuthGW/wt.content.ContentHttp/saveContent?wt.doc.WTDocument%3A20365">
<param name="removable" value="true">
<param name="attachments" value="">
<param name="target" value="c:\temp\myfolder\New Text Document.txt;;;qqqc:\temp\
myfolder\New Bitmap Image.bmp;;;qqqc:\temp\myfolder\New WinZip File.zip">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.4" width="2" height="2"
MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html"
java_code="wt/clients/util/http/UploadApplet.class"
java_codebase="http://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700"
java_archive="wt/security/security.jar"
bgcolor="16777215"
oid=""
SCRIPTABLE="true"
multipleQuantity="3"
callingAction="create"
cache_option="Plugin"
type="application/x-java-applet"
contentRecordDelim=";;;zzz"
continueIfFileNotFound="false"
cache_archive="lib/HTTPClient.jar, contentCust.jar, contentDSU.jar, contentFCS.jar,
content3rdParty.jar, content.jar"
jreversion="1.4"
completionJSMethod="completion"
uploadedFromPath=""
workspacePath=""
failureJSMethod="failure"
debug="true"
java_archive="wt/security/security.jar"
uploadIfFileChanged="true"
targetType=""
cabinets="wt/security/security.cab"
continueIfFileUnchanged="true"
java_code="wt/clients/util/http/UploadApplet"
contentDelim=";;;qqq"
wt.context.locale="en_US"
delim=";;;qqq"

Additional Topics - Client Customization E-35


uploadURL="http://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700/servlet/WindchillAuthGW/w
t.content.ContentHttp/saveContent?wt.doc.WTDocument%3A20350;;;qqqhttp://lqkohpsh.pt
cnet.ptc.com:2801/PDMLink700/servlet/WindchillAuthGW/wt.content.ContentHttp/saveCon
tent?wt.doc.WTDocument%3A20335;;;qqqhttp://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700/
servlet/WindchillAuthGW/wt.content.ContentHttp/saveContent?wt.doc.WTDocument%3A2036
5"
removable="true"
attachments=""
target="c:\temp\myfolder\New Text Document.txt;;;qqqc:\temp\myfolder\New Bitmap
Image.bmp;;;qqqc:\temp\myfolder\New WinZip File.zip"
><NOEMBED>
</COMMENT>
</NOEMBED></EMBED>
</OBJECT>

Update Document (replace primary file)

<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet"


width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall-
1_4_2-windows-i586.cab#Version=1,4,2">
<param name="java_code" value="wt/clients/util/http/UploadApplet">
<param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/">
<param name="java_archive" value="wt/security/security.jar">
<param name="type" value="application/x-java-applet;version=1.4">
<param name="bgcolor" value="16777215">
<param name="validEmptyFile" value="false">
<param name="oid" value="VR:wt.doc.WTDocument:656218">
<param name="SCRIPTABLE" value="true">
<param name="callingAction" value="updateReplace">
<param name="cache_option" value="Plugin">
<param name="MAYSCRIPT" value="true">
<param name="checksum" value="3774325531">
<param name="contentRecordDelim" value=";;;zzz">
<param name="continueIfFileNotFound" value="false">
<param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar,
lib/HTTPClient.jar, content3rdParty.jar, content.jar">
<param name="completionJSMethod" value="uploadCompleted">
<param name="uploadedFromPath" value="c:/temp/MyDoc.doc">
<param name="completionUrl" value="">
<param name="workspacePath" value="">
<param name="docOperation" value="update">
<param name="failureJSMethod" value="uploadFailed">
<param name="debug" value="false">
<param name="failureUrl" value="">
<param name="uploadIfFileChanged" value="true">
<param name="targetType" value="FILE">
<param name="cabinets" value="wt/security/security.cab">
<param name="continueIfFileUnchanged" value="true">
<param name="oidString" value="wt.content.ApplicationData:656261">
<param name="contentDelim" value=";;;qqq">
<param name="wt.context.locale" value="en_US">
<param name="delim" value=";;;qqq">
<param name="uploadURL"
value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.conten
t.ContentHttp/saveContent?wt.doc.WTDocument%3A656220">
<param name="removable" value="true">
<param name="fileName" value="MyDoc.doc">

E-36 Windchill Customizer’s Guide


<param name="attachments" value="">
<param name="target" value="C:/TEMP/MyFolder/Sample.jpg">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2"
height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html"
java_code="wt/clients/util/http/UploadApplet"
java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/"
java_archive="wt/security/security.jar"
bgcolor="16777215"
validEmptyFile="false"
oid="VR:wt.doc.WTDocument:656218"
SCRIPTABLE="true"
callingAction="updateReplace"
cache_option="Plugin"
checksum="3774325531"
contentRecordDelim=";;;zzz"
continueIfFileNotFound="false"
cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar,
content3rdParty.jar, content.jar"
completionJSMethod="uploadCompleted"
uploadedFromPath="c:/temp/MyDoc.doc"
completionUrl=""
workspacePath=""
docOperation="update"
failureJSMethod="uploadFailed"
debug="false"
failureUrl=""
uploadIfFileChanged="true"
targetType="FILE"
cabinets="wt/security/security.cab"
continueIfFileUnchanged="true"
oidString="wt.content.ApplicationData:656261"
contentDelim=";;;qqq"
wt.context.locale="en_US"
delim=";;;qqq"
uploadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.co
ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A656220"
removable="true"
fileName="MyDoc.doc"
attachments=""
target="C:/TEMP/MyFolder/Sample.jpg"
><NOEMBED>
</COMMENT>
</NOEMBED></EMBED>
</OBJECT>

Update Document (remove primary file)

<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet"


width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall-
1_4_2-windows-i586.cab#Version=1,4,2">
<param name="java_code" value="wt/clients/util/http/UploadApplet">
<param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/">
<param name="java_archive" value="wt/security/security.jar">
<param name="type" value="application/x-java-applet;version=1.4">
<param name="bgcolor" value="16777215">
<param name="validEmptyFile" value="false">

Additional Topics - Client Customization E-37


<param name="oid" value="VR:wt.doc.WTDocument:656218">
<param name="SCRIPTABLE" value="true">
<param name="callingAction" value="updateReplace">
<param name="cache_option" value="Plugin">
<param name="MAYSCRIPT" value="true">
<param name="checksum" value="3774325531">
<param name="contentRecordDelim" value=";;;zzz">
<param name="continueIfFileNotFound" value="false">
<param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar,
lib/HTTPClient.jar, content3rdParty.jar, content.jar">
<param name="completionJSMethod" value="uploadCompleted">
<param name="uploadedFromPath" value="c:/temp/MyDoc.doc">
<param name="completionUrl" value="">
<param name="workspacePath" value="">
<param name="docOperation" value="update">
<param name="failureJSMethod" value="uploadFailed">
<param name="debug" value="false">
<param name="failureUrl" value="">
<param name="uploadIfFileChanged" value="true">
<param name="targetType" value="NONE">
<param name="cabinets" value="wt/security/security.cab">
<param name="continueIfFileUnchanged" value="true">
<param name="oidString" value="wt.content.ApplicationData:656261">
<param name="contentDelim" value=";;;qqq">
<param name="wt.context.locale" value="en_US">
<param name="delim" value=";;;qqq">
<param name="uploadURL"
value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.conten
t.ContentHttp/saveContent?wt.doc.WTDocument%3A656220">
<param name="removable" value="true">
<param name="fileName" value="MyDoc.doc">
<param name="attachments" value="">
<param name="target" value="">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2"
height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html"
java_code="wt/clients/util/http/UploadApplet"
java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/"
java_archive="wt/security/security.jar"
bgcolor="16777215"
validEmptyFile="false"
oid="VR:wt.doc.WTDocument:656218"
SCRIPTABLE="true"
callingAction="updateReplace"
cache_option="Plugin"
checksum="3774325531"
contentRecordDelim=";;;zzz"
continueIfFileNotFound="false"
cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar,
content3rdParty.jar, content.jar"
completionJSMethod="uploadCompleted"
uploadedFromPath="c:/temp/MyDoc.doc"
completionUrl=""
workspacePath=""
docOperation="update"
failureJSMethod="uploadFailed"
debug="false"

E-38 Windchill Customizer’s Guide


failureUrl=""
uploadIfFileChanged="true"
targetType="NONE"
cabinets="wt/security/security.cab"
continueIfFileUnchanged="true"
oidString="wt.content.ApplicationData:656261"
contentDelim=";;;qqq"
wt.context.locale="en_US"
delim=";;;qqq"
uploadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.co
ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A656220"
removable="true"
fileName="MyDoc.doc"
attachments=""
target=""
><NOEMBED>
</COMMENT>
</NOEMBED></EMBED>
</OBJECT>

Update Document (no primary content handling, add/replace/remove attachment files/URLs)

<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet"


width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall-
1_4_2-windows-i586.cab#Version=1,4,2">
<param name="java_code" value="wt/clients/util/http/UploadApplet">
<param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/">
<param name="java_archive" value="wt/security/security.jar">
<param name="type" value="application/x-java-applet;version=1.4">
<param name="bgcolor" value="16777215">
<param name="validEmptyFile" value="false">
<param name="oid" value="VR:wt.doc.WTDocument:656269">
<param name="SCRIPTABLE" value="true">
<param name="callingAction" value="create">
<param name="cache_option" value="Plugin">
<param name="MAYSCRIPT" value="true">
<param name="checksum" value="">
<param name="contentRecordDelim" value=";;;zzz">
<param name="continueIfFileNotFound" value="false">
<param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar,
lib/HTTPClient.jar, content3rdParty.jar, content.jar">
<param name="completionJSMethod" value="uploadCompleted">
<param name="uploadedFromPath" value="">
<param name="completionUrl" value="">
<param name="workspacePath" value="">
<param name="docOperation" value="update">
<param name="failureJSMethod" value="uploadFailed">
<param name="debug" value="false">
<param name="failureUrl" value="">
<param name="uploadIfFileChanged" value="true">
<param name="targetType" value="NONE">
<param name="cabinets" value="wt/security/security.cab">
<param name="continueIfFileUnchanged" value="true">
<param name="oidString" value="">
<param name="contentDelim" value=";;;qqq">
<param name="wt.context.locale" value="en_US">
<param name="delim" value=";;;qqq">

Additional Topics - Client Customization E-39


<param name="uploadURL"
value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.conten
t.ContentHttp/saveContent?wt.doc.WTDocument%3A656270">
<param name="removable" value="true">
<param name="fileName" value="">
<param name="attachments" value="FILE;;;qqqnewfile;;;qqqC:\TEMP\
DGadReq.doc;;;qqqADD;;;zzzURL;;;qqqnewURL;;;qqqwww.amazon.com;;;qqq;;;qqqADD;;;zzzF
ILE;;;qqqwt.content.ApplicationData:656293;;;qqqC:\TEMP\
MyDoc.doc;;;qqqREPLACE;;;zzzURL;;;qqqwt.content.URLData:656295;;;qqqhttp://www.askj
eeves.com;;;qqqAsk Jeeves
website;;;qqqREPLACE;;;zzzFILE;;;qqqwt.content.ApplicationData:656902;;;qqq;;;qqqRE
MOVE;;;zzzURL;;;qqqwt.content.URLData:656904;;;qqq;;;qqqREMOVE">
<param name="target" value="">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2"
height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html"
java_code="wt/clients/util/http/UploadApplet"
java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/"
java_archive="wt/security/security.jar"
bgcolor="16777215"
validEmptyFile="false"
oid="VR:wt.doc.WTDocument:656269"
SCRIPTABLE="true"
callingAction="create"
cache_option="Plugin"
checksum=""
contentRecordDelim=";;;zzz"
continueIfFileNotFound="false"
cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar,
content3rdParty.jar, content.jar"
completionJSMethod="uploadCompleted"
uploadedFromPath=""
completionUrl=""
workspacePath=""
docOperation="update"
failureJSMethod="uploadFailed"
debug="false"
failureUrl=""
uploadIfFileChanged="true"
targetType="NONE"
cabinets="wt/security/security.cab"
continueIfFileUnchanged="true"
oidString=""
contentDelim=";;;qqq"
wt.context.locale="en_US"
delim=";;;qqq"
uploadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.co
ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A656270"
removable="true"
fileName=""

E-40 Windchill Customizer’s Guide


attachments="FILE;;;qqqnewfile;;;qqqC:\TEMP\
DGadReq.doc;;;qqqADD;;;zzzURL;;;qqqnewURL;;;qqqwww.amazon.com;;;qqq;;;qqqADD;;;zzzF
ILE;;;qqqwt.content.ApplicationData:656293;;;qqqC:\TEMP\
MyDoc.doc;;;qqqREPLACE;;;zzzURL;;;qqqwt.content.URLData:656295;;;qqqhttp://www.askj
eeves.com;;;qqqAsk Jeeves
website;;;qqqREPLACE;;;zzzFILE;;;qqqwt.content.ApplicationData:656902;;;qqq;;;qqqRE
MOVE;;;zzzURL;;;qqqwt.content.URLData:656904;;;qqq;;;qqqREMOVE"
target=""
><NOEMBED>
</COMMENT>
</NOEMBED></EMBED>
</OBJECT>

The Download Applet


DownloadApplet is an "invisible" applet, that is, a 2-pixel by 2-pixel applet whose
background color matches the page. It starts the download as soon as the page has
loaded and the applet has initialized, using the values in the applet parameters.
This behavior makes DownloadApplet most appropriate for use in a "processing"
page or popup rather than an interactive form page.

Download of a Single File


Downloading a file through DownloadApplet requires two pieces of information:
the filename to download and the URL to download it from. These are indicated
by setting the "filename" and "downloadURL" parameters. Depending on the
user's preference for Download Operation Type, Windchill may open the file in
application, save the file to disk in a location chosen by the user, or prompt the
user to choose between open and save.

Download of Multiple Files from One or More Windchill Objects


Files can be downloaded from multiple Windchill documents or multiple content
items to a single destination with a single instance of DownloadApplet. This is
done by setting the "filename" parameter to a concatenated list of filenames, and
setting the "downloadURL" parameter to a concatenated list of downloadURLs
corresponding in quantity and order to the concatenated filename values, and
setting the "downloadQuantity" parameter to the quantity of files to be
downloaded. Depending on the user's preference for Download Operation Type,
Windchill may open the first file in application, saved the first file to disk in a
location chosen by the user, or prompt the user to choose between open and save
for that file. All other files will be downloaded to the same directory chosen for
the first file, without further prompting.

Configuring Download Behavior - User Preferences


The applet's prompt behavior and download location are determined by
parameters that are typically set by the individual user's preferences.
The Download Operation Type preference (node=/wt/content key=
downloadOpType) determines whether the downloaded file should be opened in
application, saved to disk or whether the user should be prompted to make that

Additional Topics - Client Customization E-41


choice. The default is to prompt. For downloads of multiple files, this decision
only applies to the first file downloaded (all other files will be saved to disk, in the
same location).
The Default Local Directory preference (node=/wt/content key= workspacePath)
determines where the file will be downloaded upon open-in-application, or where
the file chooser will open to upon save-to-disk. Users who have a particular
directory where they like to keep all their Windchill files might like to set this
preference to that directory. If no value is specified, or if the specified path does
not exist on the local machine, then a default directory will be used as specified by
the environment variables of the local machine's operating system.

E-42 Windchill Customizer’s Guide


Download Applet Parameters
Parameter
Name Sample Value Description

java_codebase http://machinename.ptcnet.ptc.c Provided by taglib generator


om/Windchill/

type application/x-java- Provided by taglib generator


applet;version=1.4

java_code wt/clients/util/DownloadApplet Applet location in codebase – never changes

cache_archive "contentCust.jar, Java archives containing the classfiles used by this


contentDSU.jar, contentFCS.jar, applet
lib/HTTPClient.jar,
content3rdParty.jar, content.jar"

java_archive wt/security/security.jar Never changes

cabinets wt/security/security.cab Never changes

cache_option Plugin Never changes

wt.context.loc en_US Locale of user’s browser


ale

bgcolor 16777215 Decimal version of desired background color,


typically matches the background color of the page
or table cell where the applet is located

downloadURL http://mecasey03d.ptcnet.ptc.co URL that content will be downloaded from


m/Windchill/servlet/WindchillA
uthGW/wt.fv.master.RedirectDo
wnload/redirectDownload/1026
508screenshot.doc?u8&HttpOpe
rationItem=wt.content.Applicati
onData%3A294016&ContentHo
lder=wt.doc.WTDocument%3A
294014"

filename MyDoc.doc Filename of file to be downloaded, used in prompt


dialogs, can be changed during download.

url http://mecasey03d.ptcnet.ptc.co URL to follow after processing is complete


m/Windchill/servlet/WindchillA
uthGW/wt.enterprise.URLProce
ssor/invokeAction?action=Chec
kOutDocCloseWindow&OID=
VR%3Awt.doc.WTDocument%
3A294013&formName=CheckO
utDocumentWizard

downloadQua 3 (Optional) Number of different files and download


ntity sources, if downloading more than one file

Additional Topics - Client Customization E-43


contentDelim ;;;qqq (Optional) Delimiter string used to separate
filepaths if downloading more than one file

downloadOpT ALWAYS_ASK, (Optional) Normally retrieved from user preference


ype ALWAYS_SAVE, setting, determines whether user is prompted to
ALWAYS_OPEN open-in-app vs. save-to-disk

defaultPath C:/temp/MyWindchillFiles/dum (Optional) Normally retrieved from workspacePath


my.txt user preference setting, determines where file is
downloaded for open-in-app or where file browser
is launched for save-to-disk

debug true, false (Optional) Defaults to false, change to true for Java
Console output during processing

remember true, false (Optional) Defaults to false, change to true to have


main file's checksum and local download path
appended to the URL query string for persistence
by the post-processing code.

Sample HTML for DownloadApplet

Download (single file)

<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet"


width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall-
1_4_2-windows-i586.cab#Version=1,4,2">
<param name="java_code" value="wt/clients/util/http/DownloadApplet">
<param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/">
<param name="java_archive" value="wt/security/security.jar">
<param name="type" value="application/x-java-applet;version=1.4">
<param name="filename" value="1026508screenshot.doc">
<param name="url"
value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.enterp
rise.URLProcessor/invokeAction?action=CheckOutDocCloseWindow&OID=VR%3Awt.doc.WTDocu
ment%3A294013&formName=CheckOutDocumentWizard">
<param name="debug" value="FALSE">
<param name="delim" value=";;;qqq">
<param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar,
lib/HTTPClient.jar, content3rdParty.jar, content.jar">
<param name="cabinets" value="wt/security/security.cab">
<param name="downloadOpType" value="ALWAYS_ASK">
<param name="cache_option" value="Plugin">
<param name="wt.context.locale" value="en_US">
<param name="downloadQuantity" value="1">
<param name="defaultPath" value="">
<param name="downloadURL"
value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.mas
ter.RedirectDownload/redirectDownload/1026508screenshot.doc?u8&HttpOperationItem=wt
.content.ApplicationData%3A294016&ContentHolder=wt.doc.WTDocument%3A294014">
<param name="recordDelim" value=";;;zzz">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2"
height="2" pluginspage="http://java.sun.com/getjava/download.html"
java_code="wt/clients/util/http/DownloadApplet"

E-44 Windchill Customizer’s Guide


java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/"
java_archive="wt/security/security.jar"
filename="1026508screenshot.doc"
url="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.enterpri
se.URLProcessor/invokeAction?action=CheckOutDocCloseWindow&OID=VR%3Awt.doc.WTDocume
nt%3A294013&formName=CheckOutDocumentWizard"
debug="FALSE"
delim=";;;qqq"
cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar,
content3rdParty.jar, content.jar"
cabinets="wt/security/security.cab"
downloadOpType="ALWAYS_ASK"
cache_option="Plugin"
wt.context.locale="en_US"
downloadQuantity="1"
defaultPath=""
downloadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.
fv.master.RedirectDownload/redirectDownload/1026508screenshot.doc?u8&HttpOperationI
tem=wt.content.ApplicationData%3A294016&ContentHolder=wt.doc.WTDocument%3A294014"
recordDelim=";;;zzz"
><NOEMBED>
</COMMENT>
</NOEMBED></EMBED>
</OBJECT>

Download (multiple files)

<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet"


width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall-
1_4_2-windows-i586.cab#Version=1,4,2">
<param name="java_code" value="wt/clients/util/http/DownloadApplet">
<param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/">
<param name="java_archive" value="wt/security/security.jar">
<param name="type" value="application/x-java-applet;version=1.4">
<param name="filename"
value=";;;qqqRequirements_Template.doc;;;qqqAgenda_Template.doc;;;qqqMemo_Template.
doc;;;qqqMinutes_Template.doc;;;qqqMS_Project_Plan_Template.mpp;;;qqqPresentation_T
emplate.ppt;;;qqq">
<param name="url" value="javascript:close()">
<param name="debug" value="FALSE">
<param name="delim" value=";;;qqq">
<param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar,
lib/HTTPClient.jar, content3rdParty.jar, content.jar">
<param name="cabinets" value="wt/security/security.cab">
<param name="downloadOpType" value="ALWAYS_ASK">
<param name="cache_option" value="Plugin">
<param name="wt.context.locale" value="en_GB">
<param name="downloadQuantity" value="6">
<param name="defaultPath" value="">
<param name="downloadURL"
value=";;;qqqhttp://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.
fv.master.RedirectDownload/redirectDownload/Requirements_Template.doc?u8&HttpOperat
ionItem=wt.content.ApplicationData%3A295941&ContentHolder=wt.doc.WTDocument%3A29593
9;;;qqqhttp://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.mas
ter.RedirectDownload/redirectDownload/Agenda_Template.doc?u8&HttpOperationItem=wt.c
ontent.ApplicationData%3A294345&ContentHolder=wt.doc.WTDocument%3A294335;;;qqqhttp:
//mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.Redirect

Additional Topics - Client Customization E-45


Download/redirectDownload/Memo_Template.doc?u8&HttpOperationItem=wt.content.Applica
tionData%3A294363&ContentHolder=wt.doc.WTDocument%3A294353;;;qqqhttp://mecasey03d.p
tcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload/redir
ectDownload/Minutes_Template.doc?u8&HttpOperationItem=wt.content.ApplicationData%3A
294381&ContentHolder=wt.doc.WTDocument%3A294371;;;qqqhttp://mecasey03d.ptcnet.ptc.c
om/Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload/redirectDownload
/MS_Project_Plan_Template.mpp?u8&HttpOperationItem=wt.content.ApplicationData%3A294
399&ContentHolder=wt.doc.WTDocument%3A294389;;;qqqhttp://mecasey03d.ptcnet.ptc.com/
Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload/redirectDownload/Pr
esentation_Template.ppt?u8&HttpOperationItem=wt.content.ApplicationData%3A295917&Co
ntentHolder=wt.doc.WTDocument%3A295907;;;qqq">
<param name="recordDelim" value=";;;zzz">
<COMMENT>
<EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2"
height="2" pluginspage="http://java.sun.com/getjava/download.html"
java_code="wt/clients/util/http/DownloadApplet"
java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/"
java_archive="wt/security/security.jar"
filename=";;;qqqRequirements_Template.doc;;;qqqAgenda_Template.doc;;;qqqMemo_Templa
te.doc;;;qqqMinutes_Template.doc;;;qqqMS_Project_Plan_Template.mpp;;;qqqPresentatio
n_Template.ppt;;;qqq"
url="javascript:close()"
debug="FALSE"
delim=";;;qqq"
cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar,
content3rdParty.jar, content.jar"
cabinets="wt/security/security.cab"
downloadOpType="ALWAYS_ASK"
cache_option="Plugin"
wt.context.locale="en_GB"
downloadQuantity="6"
defaultPath=""
downloadURL=";;;qqqhttp://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuth
GW/wt.fv.master.RedirectDownload/redirectDownload/Requirements_Template.doc?u8&Http
OperationItem=wt.content.ApplicationData%3A295941&ContentHolder=wt.doc.WTDocument%3
A295939;;;qqqhttp://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.
fv.master.RedirectDownload/redirectDownload/Agenda_Template.doc?u8&HttpOperationIte
m=wt.content.ApplicationData%3A294345&ContentHolder=wt.doc.WTDocument%3A294335;;;qq
qhttp://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.Re
directDownload/redirectDownload/Memo_Template.doc?u8&HttpOperationItem=wt.content.A
pplicationData%3A294363&ContentHolder=wt.doc.WTDocument%3A294353;;;qqqhttp://mecase
y03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload
/redirectDownload/Minutes_Template.doc?u8&HttpOperationItem=wt.content.ApplicationD
ata%3A294381&ContentHolder=wt.doc.WTDocument%3A294371;;;qqqhttp://mecasey03d.ptcnet
.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload/redirectDo
wnload/MS_Project_Plan_Template.mpp?u8&HttpOperationItem=wt.content.ApplicationData
%3A294399&ContentHolder=wt.doc.WTDocument%3A294389;;;qqqhttp://mecasey03d.ptcnet.pt
c.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload/redirectDownl
oad/Presentation_Template.ppt?u8&HttpOperationItem=wt.content.ApplicationData%3A295
917&ContentHolder=wt.doc.WTDocument%3A295907;;;qqq"
recordDelim=";;;zzz"
><NOEMBED>
</COMMENT>
</NOEMBED></EMBED>
</OBJECT>

E-46 Windchill Customizer’s Guide


Index

A Best practices
modifying files, 5-9
Access control new files, 5-26
Property, 2-12 Bill of Materials
Access control package, 31-5 Customizing, 22-19
Accessor methods Hierarchy Visitor, 22-20
Overriding, 36-9 product structure, 22-19
Adding report, 22-19
content holder data formats, 45-2 bin directory, 2-2
API BOM
report generation, 28-31 see Bill of Materials
Applet Business Classes, 22-2
Advantages, E-14 Business classes
Content Download Applet, E-14 Revision controlled business class, 37-6
Content Upload Applet, E-14 Business data types
Default Local Directory, E-18 Implementing, 36-8
Disadvantages, E-14 Business objects
Download Applet, E-41 Modeling, 4-1
Download Applet Parameters, E-43 Business services
File Selection Applet, E-14 Implementing, 36-14
File Selection files for upload, E-15
FileChooserDropAppletParameters, E-19 C
FileChooserDropAppletsample HTML, E-20
Multi-Select Javascript sample, E-18 cat files, 2-7
Processing File Selection Output, E-17 For sharing code, 2-8
Sample Javascript for Feedback and Navigation, Change Management Delegates, 23-2
E-24 ChooseFolderDelegate, 23-2
Single-Select Javascript sample, E-17 ChooseLifeCycleDelegate, 23-2
Upload Applet Parameters, E-28 ConcreteAssociationDelegate, 23-3
Upload Behavior-System Properties, E-26 DisplayIdentificationDelegate, 23-4
Upload Behavior-User Preferences, E-27 Change Management Workflow Process Templates
UploadApplet, E-22 Change Issue Process, 25-6
Audit Event Code Impacted, 25-12
configaudit.xml file, 29-7 Custom Workflow Process Templates, 25-12
Handler Classes, 29-7 customizing, 25-6
ProjectAuditEvent, 29-4 Existing Installations, 25-11
Audit Recorders, 29-7 Installation and Upgrade, 25-11
auditing events New Installations, 25-11
configuration file, 29-3 Synch on Change Request Submit, 25-8
Windchill Auditing Framework, 29-2 Synch on Multiple Object State Change, 25-10
synchronization robots, 25-6
B checkAttribute method, 36-12
ChooseFolderDelegate, 23-2
Batch scripts, 2-2 ChooseLifeCycleDelegate, 23-2

Index-1
Class files, 2-5 overriding, 21-9
Class path environment variable, 2-9 Customized files, 5-2
Classes Customizing, 28-16
Document, 37-10 Customizing Modeled Business Objects
Folder resident business class, 37-4 Windchill Customization Points, 1-8
Foundation classes, 4-10 Customizing workflows
Item, 4-10 key points, 25-14
Link, 4-11 lock/unlock promotion targets, 25-14
Managed business class, 37-5 owner role, 25-16
Part, 37-13 review promotion request activity, 25-15
Simple business class, 37-2
WTObject, 4-10 D
ClassInfo.ser files
Location, 2-6, 2-13 Data Model Customizations, 1-5
CLASSPATH environment variable, 2-9 Database
Client JAR files, 5-7, 5-11, 5-14 Access set by properties, 2-14
Code db.properties.file, 2-14
Sharing, 2-8 Default table size, 2-13
Code generation Properties file, 2-3
Files, 2-7 Property file
See system generation See db.properties file
tools.properties file, 2-13 Database indexes, 22-12
Code Impacted db directory, 2-3
Change Management Workflow Process Tem- db.properties file
plates, 25-12 Database access properties, 2-14
codebase directory General description, 2-10
Details, 2-5 wt.pom.dbPassword property, 2-14
Location, 2-3 wt.pom.dbUser property, 2-14
codebase files, 5-13 wt.pom.serviceName property, 2-14
Column Length Debug tracing, 2-12
change for modeled attribute, 33-2 debug.properties file
customizing, 33-2 General description, 2-10
default location, 33-2 Default Local Directory, E-18
comment defaultValue
EnumeratedType, 34-2 EnumeratedType, 34-2
CompositeUnique property, 22-13 Design Pattern
ConcreteAssociationDelegate, 23-3 Business Service, 35-3
constantEnumeratedType, 34-6 cookie abstraction, 35-4
Content Download Applet, E-14 helper abstraction, 35-4
Content holders service abstraction, 35-5
data formats, 45-2 ServiceEvent abstraction, 35-5
Content Upload Applet, E-14 ServiceException abstraction, 35-6
Control units, 2-8 type abstraction, 35-4
cookie abstraction Iterated interface, 35-7
Design Pattern, 35-4 Master Iteration, 35-7
createSafeArea target, 5-6 Mastered interface, 35-7
Creating new packages, 5-26 Object Reference, 35-2
CSS Customization, 28-17 Development environment
csvReport Template, 28-11 Directory structure, 2-2
elements, 28-11 Environment variables, 2-9
Custom Reports, 1-6 Files, 2-3, 2-7
custom_getFieldData Property files, 2-10

Index-2 Windchill Customizer’s Guide


Source code control, 2-8 RBrbInfo, 34-7
Directory resource bundle, 34-9
Ant, 2-2 resource info header, 34-7
apacheConf, 2-2 runtime resources, 34-8
bin, 2-2 start utility, 34-12
cgi-bin, 2-2 Enumerated Types
codebase creating subclass, 34-3
Details, 2-5 EnumeratedType class, 34-2
Location, 2-3 comment, 34-2
codebase/wt, 2-6 defaultValue, 34-2
db, 2-3 display, 34-2
installer, 2-3 order, 34-2
lib, 2-3 selectable, 34-2
loadFiles, 2-3 value, 34-2
loadXMLFiles, 2-3 enumVerify tool, 34-8
logs, 2-3 Environment variables
Module, 2-3 Class path, 2-9
RoseExtensions, 2-9 Rational Rose virtual path map, 2-9
src SQL path, 2-9
Details, 2-7 Events
Location, 2-3 Managing, 36-4
src/wt, 2-7 Examples
srclib, 2-3 Development process, 3-1
Structure after installation, 2-2 Executable class files, 2-5
upgrade, 2-4 ExportReport Template, 28-13
display optional parameters, 28-13
EnumeratedType, 34-2
DisplayIdentificationDelegate, 23-4 F
Doc package, 37-10
Document class, 37-10 feedback, E-23
Document package, 37-10 File Browse Launchers
Download Applet, E-41 launch Java file, E-15
Download Behavior-User Preferences, E-41 File Selection Applet, E-14
Downloading a file, E-41 File Browse Launchers, E-15
Downloading multiple files, E-41 Processing Output, E-17
Sample HTML, E-44 upload files, E-15
Download Applet Parameters, E-43 User Preferences, E-18
Drag and Drop Targets, E-16 FileChooserDropApplet Parameters, E-19
drop, E-16 Files
new, 5-26
E site-modified, 5-2, 5-5
Folder resident business class, 37-4
Enterprise package, 37-2 Foundation classes
enumCustomize tool, 5-10, 34-11 Definitions, 4-10
Enumerated Type
Customization Utility, 34-11 G
editing resource info, 34-7
entry contents, 34-7 Generate Form URL, 28-33
entry format, 34-7
Extending, 34-10 H
GUI Usage, 34-12
localizing, 34-9 helper abstraction

Index-3
Design Pattern, 35-4 L
HTML files
Location of, 2-6 Link class, 4-11
HTML templates, 5-12 listSiteChanges target, 5-6, 5-8
listSiteChangesIgnored target, 5-6
I listSiteModExclusions target, 5-6
loadFiles directory, 2-3
IdentificationObject, 22-6, 22-8 Loading
implements identified, 22-8 Initial data, 2-3
implements UniquelyIdentified, 22-10 LoadReport Template, 28-11
Identified, 22-7 standalone mode options, 28-13
Identity Attributes Localization, 40-1
flowchart, 22-5 Location of required files, 2-6
IdentityService, 22-5 Localizing
modify, 22-2 Text, 40-5
RevisionControlled Identity, 22-4 Logging
SemanticKeys, 22-11 Default location for trace logs, 2-3
System Assigned, 22-2 Enable/disable logging, 2-12
UniquelyIdentified, 22-11 Trace messages
User-Assigned, 22-2 From method server, 2-12
Identity attributes, 22-2 From server manager, 2-12
IdentityService LogicalAttributes.xml file, 5-12
How to use, 22-6 logs directory, 2-3
Implementation of Visitors, 22-22
quantity units, 22-22 M
Indexed-Search webject
customized search application, 21-2 Macros
IndexObject method reference, 21-10 customizing, 28-35
IndexSearch report parameter, 28-9
indexed text, 21-6 make_jar.config_jars target, 5-7
Info*Engine, 1-6 Managed business class, 37-5
Info*Engine tasks, 5-13 Managing client JAR files, 5-14
INI files, 5-13 mData files, 2-7
Installation and Upgrade Location, 2-13
Change Management Workflow Process Tem- mdl files, 2-7
plates, 25-11 Meetings, 30-2
installSiteChanges target, 5-6, 5-8 Method server
Internationalization, 40-1 Logging trace messages, 2-12
Item class, 4-10 Model files, 2-7
Iteration and Version Identifiers Modeled
Customizing, 22-17 PSE Support, 20-5
multicharacter series, 22-18 Modeling
Iteration Identifiers Business objects, 4-1
integer series, 22-17 Modifying files, 5-9
Multicharacter Series, 22-18
J MyDerivedItem
enumerated type, 34-10
java.rmi.server.hostname property, 2-12 MyDerivedSize
java.util.Date, 28-29 enumerated type, 34-10
Javascript method MySize
File Selection Applet, E-17 enumerated type, 34-10

Index-4 Windchill Customizer’s Guide


O System Configurator, 2-11
wt.properties file, 2-10
Object Identity PSE
System Managed, 22-4 Modeled and Soft Type Support, 20-5
User Managed, 22-4 ptcCurrent directory, 5-3, 5-4
Object Initialization Rules, 1-3 ptcOrig directory, 5-3, 5-5
Oracle password property, 2-14
Oracle service name property, 2-14 Q
Oracle user name property, 2-14
order QueryBuilder, 28-28
EnumeratedType, 34-2 QueryBuilder Types
Organization and Container Templates, 1-4 Report Generation, 28-37
QueryResult, 38-5
P QuerySpec, 38-4

Packages R
Access control, 31-5
Control units, 2-8 Rational Rose, 4-2
Doc, 37-10 Virtual path map, 2-9
Document, 37-10 Windchill extensions, 2-9
Enterprise, 37-2 WT_EXTENSIONS entry, 2-9
Location, 2-6 WT_STD_PACKAGES entry, 2-9
Overview, 31-2 WT_WORK entry, 2-9, 2-13
Part, 37-13 Rational Rose Modeler Edition, 5-27
Query, 38-4 RB.java files
Packages, new, 5-26 Location, 2-6
Parameters RB.rbInfo
Input to the webject, 21-2 enumerated type, 34-7
report generation, 28-7 RBINFO files, 5-9, 5-10
Part class, 37-13 Rebuilding client JAR files, 5-7, 5-11
Part package, 37-13 Report Generation
PATH environment variable, 2-9 API, 28-31
Path environment variable, 2-9 basic example, 28-2
Persistence client, 28-30
Management, 38-1 csvReport Template, 28-11
Manager, 38-2 customization details, 28-15
Query, 38-4 CSS Customization, 28-17
Preferences, 1-2 new formats, 28-26
Product Structure Explorer query, 28-15
See PSE report format, 28-16
ProjectAuditEvent class, 29-4 stylesheets, 28-18
Promotion Request Approval Process, 25-13 XML Resource Bundles, 28-25
Promotion Request Review Process, 25-14 XML Result Format, 28-27
Promotion Request Workflow Processes XSLT Customization, 28-17
customizing, 25-13 customizing macros, 28-35
Properties, 1-2 ExportReport Template, 28-13
Properties and Preferences, 1-2 Generate Form URL, 28-33
Property files, 5-11 initial query steps, 28-2
db.properties file, 2-10 LoadReport Template, 28-11
debug.properties file, 2-10 macro generation form steps, 28-10
Editing, 2-11 macros, 28-9
service.properties file, 2-10 new client, 28-33

Index-5
parameters, 28-7 Event management, 36-4
QueryBuilder Types, 28-37 Managing, 36-2
Report Templates, 28-11 Overview, 31-1
URL customizing, 28-33 Query, 38-4
XSLT API, 28-32 Servlet Helper
XSLT standard, 28-26 GatewayServletHelper, 22-30
XSLT Stylesheets as Report Formats, 28-30 URLFactory Functionality, 22-30
Report Generation Form, 28-31 Sharing code, 2-8
Report Generation Output, 28-32 Simple business class, 37-2
Resource bundles site.xconf file, 5-11
Localizing, 40-5 siteMod directory, 5-3, 5-4
Location, 2-6 Soft Typing, 1-4
Revision control, 37-6 Source code management, 2-8
Revision controlled business class, 37-6 Source files, 2-3, 2-7
RevisionControlled Identity, 22-4 SQL path environment variable, 2-9
Rose model components, 2-7 SQL scripts, 2-3
RoseExtensions directory, 2-9 Location, 2-13
Runtime environment SQLPATH environment variable, 2-9
Files, 2-3, 2-5 src directory, 2-3
Runtime Resources Details, 2-7
building, 34-8 Stylesheets, 28-18
Supported API, 1-8
S class, 1-8
method, 1-9
Safe area, 5-2, 5-3 swmaint.xml script, 5-5
Search Synchronization robots, 25-6
Indexed-Search, 21-2 System, 22-2
Indexing Behavior, 21-6 System generation
IndexObject reference, 21-10 Overview, 32-1
IndexSearch, 21-6 Using, 32-50
Input Parameters, 21-2 System-Managed Identity, 22-15
overriding custom_getFieldData(), 21-9
SearchCondition, 38-5 T
selectable
EnumeratedType, 34-2 Template files, 5-12
SemanticKey, 22-11 Text tailoring, 5-2, 5-9, 5-10
Server logic tools.properties file
Overview of developing, 36-1 Use by code generator, 2-13
Server manager wt.classRegistry.search.path property, 2-13
Logging trace messages, 2-12 wt.classRegistry.search.pattern property, 2-13
service abstraction wt.generation.bin.dir property, 2-13
Design Pattern, 35-5 wt.generation.source.dir property, 2-13
Service Customizations, 1-5 wt.generation.sql.dir property, 2-13
Service provider property file, 5-27 wt.generation.sql.xxxTablesSize property, 2-13
service.properties file ToolsSetup.bat, 2-2
General description, 2-10 Trace logs
ServiceEvent abstraction Default location, 2-3
Design Pattern, 35-5 Trace messages
ServiceException abstraction Logging
Design Pattern, 35-6 From method server, 2-12
Services From server manager, 2-12
Access control, 31-5 Transactions, 38-8

Index-6 Windchill Customizer’s Guide


type abstraction Windchill Info*Engine tasks, 5-13
Design Pattern, 35-4 Workflow
customizing, 25-2
U Workflow HTML template
customization steps, 25-3
Unique database indexes, 22-12 Workflow HTML Templates
UniquelyIdentified, 22-11 customizing, 25-2
Updating Workflow Templates, 1-3
client JAR files, 5-11, 5-14 wt directory
content holder data formats, 45-3 See also Packages
Upload Applet, E-22 WT_EXTENSIONS entry, 2-9
Checksum, E-26 WT_STD_PACKAGES entry, 2-9
feedback, E-23 WT_WORK entry, 2-9, 2-13
multiple files initial upload, E-23 wt.access.enforce property, 2-12
Persisting Information, E-24, E-25 wt.change2 package
Primary/Secondary initial upload, E-23 change management delegates, 23-2
Sample HTML, E-31 wt.change2.WTChangeRequest2
Update/Replace/Remove, E-23 identified instructions, 22-7
Upload Applet Parameters, E-28 wt.classRegistry.search.path property, 2-13
uploadImpl parameter wt.classRegistry.search.pattern property, 2-13
System Properties, E-26 wt.generation.bin.dir property, 2-13
URL parameters wt.generation.source.dir property, 2-13
report generation table, 28-33 wt.generation.sql.dir property, 2-13
URLFactory implementation wt.generation.sql.xxxtablesSize property, 2-13
example, 22-31 wt.home property, 2-11
User Interface Customizations, 1-6 wt.logs.enabled property, 2-12
User Preferences wt.manager.verboseClient property, 2-12
customizing, 22-24 wt.manager.verboseServer property, 2-12
wt.method.verboseClient property, 2-12
V wt.method.verboseServer property, 2-12
wt.pom.dbPassword property, 2-14
validEmptyFile parameter wt.pom.dbUser property, 2-14
System Properties, E-26 wt.pom.properties property, 2-14
value wt.pom.serviceName property, 2-14
EnumeratedType, 34-2 wt.properties file
Version Identifiers Double back slashes in path names, 2-11
harvard series, 22-17 Format of path names, 2-11
Virtual path map General description, 2-10
Rational Rose java.rmi.server.hostname property, 2-12
Purpose, 2-9 wt.access.enforce property, 2-12
WT_EXTENSIONS entry, 2-9 wt.home property, 2-11
WT_STD_PACKAGES entry, 2-9 wt.logs.enabled property, 2-12
WT_WORK entry, 2-9, 2-13 wt.manager.verboseClient entry, 2-12
wt.manager.verboseServer entry, 2-12
W wt.method.verboseClient entry, 2-12
wt.method.verboseServer entry, 2-12
Webex meetings wt.pom.properties property, 2-14
customizing authentication scheme, 30-2 wt.server.codebase entry, 2-11
Windchill Auditing Framework wt.server.codebase property, 2-11
configuration, 29-7 wtCustom directory, 5-2, 5-9
Windchill Customization Points, 1-8 WTObject class, 4-10
Windchill directory structure, 2-2 wtSafeArea directory, 5-2, 5-3

Index-7
X
XCONF files, 5-11, 5-12, 5-28
xconfmanager, 6-2
XML Query results
top level elements, 28-29
XML Resource Bundles, 28-25
XML Result Format, 28-27
XSLT API
report generation, 28-32
XSLT Customization, 28-17
XSLT standard, 28-26
XSLT Stylesheets
Report Formats, 28-30
XSLT stylesheets
XML resource bundles, 28-25

Index-8 Windchill Customizer’s Guide

You might also like