Integration Guide
Integration Guide
Integration Guide
Release 9.0.6
©2018 Guidewire Software, Inc.
For information about Guidewire trademarks, visit http://guidewire.com/legal-notices.
Guidewire Proprietary & Confidential — DO NOT DISTRIBUTE
Contents
Part 1
Planning integration projects
1 Integration overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29
Overview of integration methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29
PolicyCenter integration elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .32
Preparing for integration development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .33
Integration documentation overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .34
API reference documentation for integration programmers . . . . . . . . . . . . . . . . . . . . . . . . . . . . .34
Data Dictionary documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .34
Regenerating integration libraries and WSDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .35
Regenerating the Java API libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .35
WS-I web service regeneration of WSDL for local GUnit tests . . . . . . . . . . . . . . . . . . . . . . . . . .35
What are required files for integration programmers?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .35
Public IDs and integration code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .36
Creating your own public IDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .37
Guidewire internal methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .37
Part 2
Web Services
2 Web services introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .41
What are web services? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .41
Publish or consume web services from Gosu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .41
What happens during a web service call? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .42
Reference of all base configuration web services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .42
3
Guidewire PolicyCenter 9.0.6 Integration Guide
5
Guidewire PolicyCenter 9.0.6 Integration Guide
Part 3
Plugins
7 Overview of plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Overview of PolicyCenter plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Implementing plugin interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Choose a plugin implementation type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Writing a plugin implementation class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Registering a plugin implementation class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Deploying Java files, including Java code called from Gosu plugins . . . . . . . . . . . . . . . . . . . . . . 137
Error handling in plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
Enabling or disabling a plugin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Example Gosu plugin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Special notes for Java plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Getting plugin parameters from the plugins registry editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Getting the local file path of the root and temp directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Plugin registry APIs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Getting references to plugins from Gosu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Plugin thread safety . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Using Java concurrent data types, even from Gosu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Avoid singletons due to thread-safety issues. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Design plugin implementations to support server clusters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Reading system properties in plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Do not call local web services from plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Creating unique numbers in a sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Restarting and testing tips for plugin developers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Summary of all PolicyCenter plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
7
Guidewire PolicyCenter 9.0.6 Integration Guide
Calculate a term type from period start and end dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Calculate period end from a based on PolicyPeriod. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Proration plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Leap days and proration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Add a plugin parameter to the proration plugin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Provide your own prorater subclass. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Quote purging plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Create context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Prepare for purge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Take actions after purge. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Skip policy period for purge. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Skip orphaned policy period for purge. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Get allowed job subtypes for purging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Get allowed job subtypes for pruning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Calculate next purge check date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Get purge job date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Get prune job date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Disable purging archived policy periods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Purge context object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Reference date plugin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Coverage reference date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Exclusion reference date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Modifier reference date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Period reference date. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Renewal plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Get renewal start date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Get automated renewal user . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Determine whether to use renewal offers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Underwriting company plugin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
9
Guidewire PolicyCenter 9.0.6 Integration Guide
Part 4
Messaging
18 Messaging and events. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Overview of messaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Message history . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Messaging destinations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Root object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Primary entity and primary object. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Acknowledgment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
Safe ordering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
Transport neutrality. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
Overview of messaging flow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
Messaging flow details. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
Overview of message destinations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
Use the Messaging editor to create new messaging destinations . . . . . . . . . . . . . . . . . . . . . . . . . 303
11
Guidewire PolicyCenter 9.0.6 Integration Guide
12
Guidewire PolicyCenter 9.0.6 Integration Guide
Part 5
Policy-related integrations
19 Rating integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
The rating framework. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
Guidewire Rating Management and PCRatingPlugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
Overview of cost data objects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
Where to override the default rating engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
Common questions about the default rating engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
Optional asynchronous rating. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
Implementing rating for a new line of business . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
What do cost data objects contain? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
Cost core properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
Adding line-specific cost properties and methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
Fixed ID keys link a cost data object to another object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
Cost data object methods and constructors to override. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
Cost data APIs that you can call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383
Checklist for relationship changes in cost data objects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
Writing your own line-specific rating engine subclass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
A rating line example for Personal Auto: PersonalAutoCovCostData. . . . . . . . . . . . . . . . . . . . . . . 393
A close look at PersonalAutoCovCostData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Constructors for PersonalAutoCovCostData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Setting specific properties on cost for PersonalAutoCovCostData. . . . . . . . . . . . . . . . . . . . . . . . 395
Versioned costs for PersonalAutoCovCostData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
Key values for PersonalAutoCovCostData. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
Rating slice details for PersonalAutoCovCostData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396
Rate window method for PersonalAutoCovCostData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
Rating variations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
13
Guidewire PolicyCenter 9.0.6 Integration Guide
Part 6
Claim and policy integrations
23 Claim and policy integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
Claim search from PolicyCenter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
Get claim details. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
Permission to view a claim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
Policy system notifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
Receiving a notification of a large loss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
PolicyCenter implementation of the large loss notification web service . . . . . . . . . . . . . . . . . . . . 450
Claim to policy system notification web service API. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
Policy search web service for claim system integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
Retrieving a policy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
Extend the search criteria. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
Typecode maximum length and trimmed typecodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
Policy search SOAP API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
PolicyCenter exit points to ClaimCenter and BillingCenter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
PolicyCenter product model import into ClaimCenter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
Configuring the ClaimCenter typelist generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
Run the ClaimCenter typelist generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
Using generated typelists in ClaimCenter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
Typelist localization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
Policy location search API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
Dependencies of the policy location search API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
Finding policy locations within geographic bounding boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
Part 7
Billing integrations
24 Billing integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
Billing integration overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
Mechanisms for integrating PolicyCenter and a billing system . . . . . . . . . . . . . . . . . . . . . . . . . . 470
Integrating PolicyCenter and BillingCenter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
Integrating policy center with another billing system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
How billing data flows between applications. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
Notifying a billing system of policy changes and premiums. . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
Tracking policies term by term . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
PolicyCenter properties for billing system usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
Asynchronous communication between PolicyCenter and billing system. . . . . . . . . . . . . . . . . . . 472
Exit points between PolicyCenter and billing system applications . . . . . . . . . . . . . . . . . . . . . . . 474
Configuring which system receives contact updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
Using integration-specific containers for integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
Billing producers and producer codes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
Using producer information in BillingCenter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
Comparison of producer codes in PolicyCenter and BillingCenter . . . . . . . . . . . . . . . . . . . . . . . 476
PolicyCenter producer to BillingCenter properties mapping. . . . . . . . . . . . . . . . . . . . . . . . . . . . 476
Billing accounts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
PolicyCenter billing account to BillingCenter properties mapping . . . . . . . . . . . . . . . . . . . . . . . 477
Billing plan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
Delinquency plan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
Invoicing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
15
Guidewire PolicyCenter 9.0.6 Integration Guide
Contacts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
Policy period merges. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480
Service tier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480
Billing instructions in BillingCenter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480
Billing instruction subtypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
PolicyCenter financials to BillingCenter charge properties mapping . . . . . . . . . . . . . . . . . . . . . . 483
Sending PolicyCenter transaction information to BillingCenter . . . . . . . . . . . . . . . . . . . . . . . . . 483
Billing flow for new-period jobs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
Flow of submission, renewal, and rewrite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
Policy period mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486
Billing methods and payment plans. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486
New periods and term confirmed flag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486
Billing flow for existing-period jobs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
Billing implications of midterm changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
Midterm changes to a policy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 488
Midterm changes to billing method or payment plan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 488
Holding billing on midterm policy transaction charges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 488
Midterm changes to producer of record or producer of service . . . . . . . . . . . . . . . . . . . . . . . . . . 488
Moving a policy to a new account in midterm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
Billing implications of renewals or rewrites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
Choosing the renewal flow type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
Account creation for conversion on renewal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
Copying billing data to new periods on renewal or rewrite. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
Billing implications for cancellations and reinstatements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
Cancellations that start in PolicyCenter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
Cancellations that start in BillingCenter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
Billing implications of audits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
Holding periods open for audits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
Generating an audit report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
Sending audit premiums as incremental. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
Audit reversals and revisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
Billing implications for premium reporting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
Billing implications of delinquency for failure to report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
Billing implications of deposits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
Deposits in submission, renewal, or rewrite jobs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499
Deposits in policy change and reinstatement jobs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500
Deposits in premium reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500
Deposits in cancellation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500
Deposits in final audit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500
Billing implications of up-front payments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501
Implementing the billing system plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501
Account management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
Policy period management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
Getting period information from the billing system. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504
Billing system notifications of PolicyCenter policy actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504
Producer management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505
Agency bill plan availability retrieval . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
Commission plan management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
Payment plans and installment previews . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
Updating contacts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
Other billing system plugin methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
Implementing the billing summary plugin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
Interfaces used by the billing summary plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
Getting policies billed to accounts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
Retrieving account billing summaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
16
Guidewire PolicyCenter 9.0.6 Integration Guide
Part 8
Contact integrations
25 Contact integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529
Integrating with a contact management system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529
Inbound contact integrations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
Asynchronous messaging with the contact management system . . . . . . . . . . . . . . . . . . . . . . . . . 530
Retrieve a contact . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531
Contact searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
Support for finding duplicate contacts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
Finding duplicate contacts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
Find duplicate contacts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
Adding contacts to the external system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534
Updating contacts in the external system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534
Overwriting the local contact with latest values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534
Configuring how PolicyCenter handles contacts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
Configuring available account contact role types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
Configuring mapping of contact type to account contact role . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
Configuring account contact role type display name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
Configuring account contact role type for a policy contact role . . . . . . . . . . . . . . . . . . . . . . . . . 535
Configuring allowed contact types for policy contact role type. . . . . . . . . . . . . . . . . . . . . . . . . . 535
Configuring whether to treat an account contact type as available. . . . . . . . . . . . . . . . . . . . . . . . 535
Synchronizing contacts with accounts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
Account contact plugin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
Account contact role plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
Contact web service APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
Deleting a contact. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
Adding a contact . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538
Updating a contact . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539
Merging contact addresses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539
Merging contacts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540
Handling rejection and approval of pending changes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540
Activating and deactivating contacts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
Getting associated policy transactions for a contact. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
Getting associated policies for a contact . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
Getting associated accounts for a contact. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
Address APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
Updating an address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
Part 9
Importing policy data
17
Guidewire PolicyCenter 9.0.6 Integration Guide
Part 10
Other integration topics
27 GX models. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561
GX models overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561
Create a GX model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561
Including a GX model inside another GX model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563
Mappable and unmappable properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564
Normal and key properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564
Automatic publishing of the generated XSD schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564
Create an instance of a GX model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565
GXOptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565
GX model labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566
Assign a label to a GX model property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567
Reference a GX model label . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567
Create an instance of a GX model with labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567
GX model label example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569
Serialize a GX model object to XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569
Arrays of entities in XML output. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570
Sending a message only if data model fields changed. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570
Conversion from Gosu types to XSD types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
19
Guidewire PolicyCenter 9.0.6 Integration Guide
31 Servlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627
Implementing servlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627
Create a basic servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 628
Test your basic servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 628
Example of a basic servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
@Servlet annotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
Important HTTPServletRequest object properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630
Implementing servlet authentication. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 631
Create a servlet that provides basic authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 631
Test your basic authentication servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 632
Example of a basic authentication servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 632
Supporting multiple authentication types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
Abstract HTTP basic authentication servlet class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
Abstract Guidewire authentication servlet class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
ServletUtils authentication methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
Example of a servlet using multiple authentication types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
Test your servlet using multiple authentication types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636
20
Guidewire PolicyCenter 9.0.6 Integration Guide
21
Guidewire PolicyCenter 9.0.6 Integration Guide
22
Guidewire PolicyCenter 9.0.6 Integration Guide
Document Purpose
InsuranceSuite Guide If you are new to Guidewire InsuranceSuite applications, read the InsuranceSuite Guide for informa‐
tion on the architecture of Guidewire InsuranceSuite and application integrations. The intended read‐
ers are everyone who works with Guidewire applications.
Application Guide If you are new to PolicyCenter or want to understand a feature, read the Application Guide. This guide
describes features from a business perspective and provides links to other books as needed. The in‐
tended readers are everyone who works with PolicyCenter.
Database Upgrade Guide Describes the overall PolicyCenter upgrade process, and describes how to upgrade your PolicyCenter
database from a previous major version. The intended readers are system administrators and imple‐
mentation engineers who must merge base application changes into existing PolicyCenter application
extensions and integrations.
Configuration Upgrade Guide Describes the overall PolicyCenter upgrade process, and describes how to upgrade your PolicyCenter
configuration from a previous major version. The intended readers are system administrators and im‐
plementation engineers who must merge base application changes into existing PolicyCenter applica‐
tion extensions and integrations. The Configuration Upgrade Guide is published with the Upgrade
Tools and is available from the Guidewire Community.
New and Changed Guide Describes new features and changes from prior PolicyCenter versions. Intended readers are business
users and system administrators who want an overview of new features and changes to features. Con‐
sult the “Release Notes Archive” part of this document for changes in prior maintenance releases.
Installation Guide Describes how to install PolicyCenter. The intended readers are everyone who installs the application
for development or for production.
System Administration Guide Describes how to manage a PolicyCenter system. The intended readers are system administrators re‐
sponsible for managing security, backups, logging, importing user data, or application monitoring.
Configuration Guide The primary reference for configuring initial implementation, data model extensions, and user inter‐
face (PCF) files for PolicyCenter. The intended readers are all IT staff and configuration engineers.
PCF Reference Guide Describes PolicyCenter PCF widgets and attributes. The intended readers are configuration engineers.
Data Dictionary Describes the PolicyCenter data model, including configuration extensions. The dictionary can be gen‐
erated at any time to reflect the current PolicyCenter configuration. The intended readers are configu‐
ration engineers.
Security Dictionary Describes all security permissions, roles, and the relationships among them. The dictionary can be
generated at any time to reflect the current PolicyCenter configuration. The intended readers are con‐
figuration engineers.
Globalization Guide Describes how to configure PolicyCenter for a global environment. Covers globalization topics such as
global regions, languages, date and number formats, names, currencies, addresses, and phone num‐
bers. The intended readers are configuration engineers who localize PolicyCenter.
Rules Guide Describes business rule methodology and the rule sets in Guidewire Studio for PolicyCenter. The in‐
tended readers are business analysts who define business processes, as well as programmers who
write business rules in Gosu.
Contact Management Guide Describes how to configure Guidewire InsuranceSuite applications to integrate with ContactManager
and how to manage client and vendor contacts in a single system of record. The intended readers are
PolicyCenter implementation engineers and ContactManager administrators.
Document Purpose
Best Practices Guide A reference of recommended design patterns for data model extensions, user interface, business
rules, and Gosu programming. The intended readers are configuration engineers.
Integration Guide Describes the integration architecture, concepts, and procedures for integrating PolicyCenter with ex‐
ternal systems and extending application behavior with custom programming code. The intended
readers are system architects and the integration programmers who write web services code or plu‐
gin code in Gosu or Java.
Java API Reference Javadoc‐style reference of PolicyCenter Java plugin interfaces, entity fields, and other utility classes.
The intended readers are system architects and integration programmers.
Gosu Reference Guide Describes the Gosu programming language. The intended readers are anyone who uses the Gosu lan‐
guage, including for rules and PCF configuration.
Gosu API Reference Javadoc‐style reference of PolicyCenter Gosu classes and properties. The reference can be generated
at any time to reflect the current PolicyCenter configuration. The intended readers are configuration
engineers, system architects, and integration programmers.
Glossary Defines industry terminology and technical terms in Guidewire documentation. The intended readers
are everyone who works with Guidewire applications.
Product Model Guide Describes the PolicyCenter product model. The intended readers are business analysts and implemen‐
tation engineers who use PolicyCenter or Product Designer. To customize the product model, see the
Product Designer Guide.
Product Designer Guide Describes how to use Product Designer to configure lines of business. The intended readers are busi‐
ness analysts and implementation engineers who customize the product model and design new lines
of business.
narrow bold The name of a user interface element, such Click Submit.
as a button name, a menu item name, or a
tab name.
monospace Code examples, computer output, class and The getName method of the IDoStuff API returns the name of the
method names, URLs, parameter names, object.
string literals, and other objects that might
appear in programming code.
monospace italic Variable placeholder text within code Run the startServer server_name command.
examples, command examples, file paths, Navigate to http://server_name/index.html.
and URLs.
Support
For assistance, visit the Guidewire Community.
24 About PolicyCenter documentation
Guidewire PolicyCenter 9.0.6 Integration Guide
Guidewire customers
https://community.guidewire.com
Guidewire partners
https://partner.guidewire.com
Integration overview
You can integrate a variety of external systems with PolicyCenter by using services and APIs that link PolicyCenter
with custom code and external systems. This overview provides information to help you plan integration projects for
your PolicyCenter deployment and provides technical details critical to successful integration efforts.
A service-oriented architecture.
Encapsulate your integration code so that upgrading the core application requires few other changes. Also, a
service-oriented architecture enables APIs to use different languages or platforms.
Flexible export.
Providing different types of export minimizes data conversion logic. Simplifying the conversion logic improves
performance and code maintainability for integrating with diverse and complex legacy systems.
Integration overview 29
Guidewire PolicyCenter 9.0.6 Integration Guide
Plugins
PolicyCenter plugins are classes that PolicyCenter invokes to perform an action or calculate a result. Guidewire
recommends writing plugins in Gosu, although you can also write plugins in Java. Gosu code, like Java code, can
call third-party Java classes and Java libraries.
Several types of plugins are supported.
Messaging plugins
Send messages to remote systems, and receive acknowledgments of each message. PolicyCenter has a
sophisticated transactional messaging system to send information to external systems in a reliable way. Any
server in the cluster can create a message for any data change. The only servers that send messages are servers
with the messaging server role.
Authentication plugins
Integrate custom authentication systems. For instance, define a user authentication plugin to support a
corporate directory that uses the LDAP protocol. Or define a database authentication plugin to support custom
authentication between PolicyCenter and its database server.
Other plugins
Some examples are plugins that generate policy numbers (IPolicyNumGenAdapter) or get a claim related to a
policy from a claims system (IClaimSearchAdapter).
Templates
Generate text-based formats that contain combinations of PolicyCenter data and fixed data. Templates are ideal
for name-value pair export, HTML export, text-based form letters, or simple text-based protocols.
The following table compares the main integration methods.
Integration overview 31
Guidewire PolicyCenter 9.0.6 Integration Guide
Renewal Policy
Reporting added to
Send PolicyCenter
Send
payment payment Legacy
status info
Policy Admin System
Reporting Tools (PAS)
Guidewire BillingCenter
See also
• For information about integrating with BillingCenter, see “Billing integration” on page 469.
• For information about integrating with ClaimCenter, see “Claim and policy integration” on page 449.
• For information about integrating with ContactManager, see the Contact Management Guide.
PolicyCenter/modules/configuration
Some of the main configuration subdirectories are described in the following table.
config/web Your web application configuration files, also known as PCF files.
config/logging The logging configuration file logging.properties.
config/templates Two types of templates relevant for integration.
Plugin templates
Use Gosu plugin templates for a small number of plugin interfaces that require them. These
plugin templates extract important properties from entity instances and generate text that
describes the results. Whenever PolicyCenter needs to call the plugin, PolicyCenter passes the
template results to the plugin as String parameters.
Messaging templates
Use optional Gosu messaging templates for your messaging code. Use messaging templates to
define notification letters or other similar messages contain large amounts of text but a small
amount of Gosu code.
The base configuration provides versions of some of these templates.
plugins Your Java plugin files.
Register your plugin implementations in the Plugins registry in Studio. When you register the plu‐
gin in the Plugins registry, you can specify a plugin directory, which is the name of a subdirectory of
the plugins directory. If you do not specify a subdirectory, PolicyCenter uses the shared subdirec‐
tory as the plugin directory.
For a messaging plugin, you must register this information in two different registries:
• The plugin registry in the plugin editor in Studio
• The messaging registry in the Messaging editor in Studio.
Some additional important integration-related directories are described in the following table.
Directory under the PolicyCenter installation Files that the directory contains
directory
PolicyCenter installation directory Command‐prompt tools such as gwb.bat. Use for the following integration
tasks:
• Regenerating the Java API libraries and local WSI web service WSDL.
• Regenerating the Data Dictionary.
Integration overview 33
Guidewire PolicyCenter 9.0.6 Integration Guide
Directory under the PolicyCenter installation Files that the directory contains
directory
modules/configuration/gsrc/wsi/ WSDL files generated locally.
local/gw/webservice/
modules/configuration/gsrc/wsi/
local/gw/wsi/
admin Command‐prompt tools that control a running PolicyCenter server. Almost all
of these tools are small Gosu scripts that call public web service APIs.
See also
gwb genJavaApi
As part of its normal behavior, the script displays some warnings and errors. Note that the Java API libraries are
regenerated, but the command does not regenerate the static Java API Reference documentation.
The location for the Java generated libraries is:
PolicyCenter/java-api/lib
gwb genWsiLocal
As part of its normal behavior, the script displays some warnings and errors.
The location for WS-I web service WSDL that you can use for writing test classes is:
PolicyCenter/modules/configuration/gsrc/wsi/local/
Integration overview 37
Guidewire PolicyCenter 9.0.6 Integration Guide
Web Services
Guidewire PolicyCenter 9.0.6 Integration Guide
chapter 2
You can write web service APIs in Gosu and access them from remote systems using the standard web services
protocol SOAP, the standard Simple Object Access Protocol. Web services provide a language-neutral, platform-
neutral mechanism for invoking actions or requesting data from other applications across a network. The SOAP
protocol defines request/response mechanisms for translating a function call and its response into XML-based
messages, typically across the standard HTTP protocol. PolicyCenter publishes its own built-in web service APIs
that you can use.
You can write web service APIs in Gosu and access them from remote systems using the standard web services
protocol SOAP. The SOAP protocol defines request/response mechanisms for translating a function call and its
response into XML-based messages typically sent across computer networks over the standard HTTP protocol. Web
services provide a language-neutral and platform-neutral mechanism for invoking actions or requesting data from
another application across a network. PolicyCenter publishes its own built-in web service APIs that you can use.
send to the API. If the remote API returns a result, PolicyCenter deserializes the XML response into local Gosu
objects for your code to use.
Guidewire provides built-in web service APIs for common general tasks and tasks for business entities of
PolicyCenter. However, writing your own custom web service for each integration point is the best approach for
maximum performance and maintainability. Guidewire strongly encourages you to write as many web services as
necessary to elegantly provide APIs for each integration point.
For example, write new web services to communicate with a check printing service, a legacy financials system,
reporting service, or document management system. External systems can query PolicyCenter to calculate values,
trigger actions, or to change data within the PolicyCenter database.
Publishing a web service may be as simple as added one special line of code called an annotation immediately
before your Gosu class declaration.
Guidewire provides a Java language binding for published web services. Using these bindings, you can call the
published web services from Java program as easy as making a local method invocation. You can use other
programming languages if it has a SOAP implementation and can access the web service over the Internet. Because
Gosu and Java are the typical languages for web service client code, PolicyCenter documentation uses Gosu and
Java syntax and terminology to demonstrate APIs. If you write APIs to integrate two or more Guidewire
applications, you probably will write your web service code in Gosu using its native SOAP syntax rather than Java.
package example.wsi.myobjects
uses gw.xml.ws.annotation.WsiExportable
@WsiExportable
final class MyCheckPrintInfo {
var checkID : String
var checkRecipientDisplayName : String
}
Does PolicyCenter automatically Yes. See “Getting WSDL from a running server” on page 54.
generate WSDL files from a run‐
ning server?
Does PolicyCenter automatically Yes. See “Generating WSDL” on page 54.
generate WSDL files locally if you
regenerate the SOAP API files?
Does PolicyCenter automatically No, but it is easy to generate with the Java built‐in utility wsimport. The documentation in‐
generate JAR files for Java SOAP cludes examples. See “Calling a PolicyCenter web service from Java” on page 56.
client code if you regenerate the
SOAP API files?
Can serialize Gosu class instan‐ Yes, but with certain requirements. See “Overview of web service publishing” on page 45.
ces, sometimes called POGOs:
Plain Old Gosu Objects?
Can web services serialize or de‐ No. To transfer entity data, create your own data transfer objects (DTOs) that contain only
serialize Guidewire entity instan‐ the data you need for the service. DTO objects can be either Gosu class instances or XML
ces? objects from XSD types. See in this table “Can serialize Gosu class instances”).
Can serialize a XSD‐based type Yes. Add the XSD to the source tree, run the code generation command in Studio, and write
Gosu using the XmlElement APIs. See “Using predefined XSD and WSDL” on page 65.
Can you use GX models to gen‐ Yes
erate XML types that can be ar‐
guments or return types?
Can web services serialize a GX Yes. The web services framework will generate matching XSD types in the WSDL.
model as an argument or return
type?
Can web services serialize a Java Generally speaking, no. Exceptions include Simple Java objects. Such objects include but are
object as an argument type or not limited to Date, Double, and String.
return type?
class MyClass{
@Throws(SOAPServerException,
"If communication error or any other SOAP problem occurs.")
public function myMethod() { ... }
}
Logging in to the server Each web service request embeds necessary authentication and security information in
each request. If you use Guidewire authentication, you must add the appropriate SOAP
headers before making the connection.
Package name of web services The package in which you put your web service implementation class defines the package
from the SOAP API client per‐ for the web service from the SOAP API client perspective. The biggest benefit from this
spective change is reducing the chance of namespace collisions in general. In addition, the web serv‐
ice namespace URL helps prevent namespace collisions. See “Declaring the namespace for a
web service” on page 50.
Calling a local version of the web Gosu creates types that use the original package name to avoid namespace collisions.
service from Gosu API references in the package wsi.local.ORIGINAL_PACKAGE_NAME
In production environments, if the operation is exposed only as a web service, instantiate
the web service implementation class directly and call the method. This technique avoids
having multiple transactions process the same action, which can result in possible race con‐
ditions, CDCEs (concurrent data change exceptions), or rollback issues.
For testing purposes only, the local files must be rebuilt by running the following command
from the PolicyCenter installation directory.
gwb genWsiLocal
Create SOAP 1.2 custom fault Custom fault subcodes are not supported in PolicyCenter. However, configuration code can
subcodes throw a gw.xml.ws.WsdlFault exception, which includes properties that can be populated
and subsequently retrieved.
setCode(FaultCode code)
getCode() : FaultCode
setCodeQName(QName codeQName)
getCodeQName() : QName
setDetail(XmlElement detail)
getDetail() : XmlElement
The properties returned by the WsdlFault will not be documented in the generated WSDL.
Annotation Description
@WsiAdditionalSchemas Expose additional schemas to web service clients in the WSDL.Use this to pro‐
vide references to schemas that might be required but are not automatically in‐
cluded.
“Reference additional schemas in your published WSDL” on page 69
@WsiAvailability Set the minimum server run level for this service
“Specifying minimum run level for a web service” on page 51
@WsiCheckDuplicateExternalTransaction Detect duplicate operations from external systems that change data
“Checking for duplicate external transaction IDs” on page 78
@WsiExportable Add this annotation on a Gosu class to indicate that it supports serialization
with web services. The annotation accepts an optional String argument that
specifies a namespace.
“Overview of web service publishing” on page 45
@WsiExposeEnumAsString Instead of exposing typelist types and enumerations as enumerations in the
WSDL, you can expose them as String values.
“Exposing typelists and enums as enumeration values and string values” on
page 79
@WsiInvocationHandler Perform advanced implementation of a web service that conforms to externally‐
defined standard WSDL. This is for unusual situations only. This approach limits
protection against some types of common errors.
“Using predefined XSD and WSDL” on page 65
@WsiParseOptions Add validation of incoming requests using additional schemas in addition to the
automatically generated schemas.
“Validate requests using additional schemas as parse options” on page 69
@WsiPermissions Set the required permissions for this service
“Specifying required permissions for a web service” on page 51
@WsiReduceDBConnections A database query triggers the retrieval of a database connection from the con‐
nection pool. The management of database connections is handled by the pool
The @WsiReduceDBConnections annotation configures the web service opera‐
tions to retrieve and re‐use a single database connection from the pool. With‐
out the annotation, a connection is retrieved from and returned to the pool for
each query.
In most scenarios, the @WsiReduceDBConnections annotation is not needed. It
can result in connections becoming effectively locked, reducing the efficiency of
the connection pool and slowing web service execution.
The annotation can be used in special situations only. An example is when a sin‐
gle web service performs a very large number of database queries, where re‐
trieving and returning a pool connection for each query would cause excessive
thrashing.
@WsiRequestTransform Add transformations of incoming or outgoing data as a byte stream. Typically
@WsiResponseTransform you would use this to add advanced layers of authentication or encryption. Con‐
trast to the annotations in the next row, which operate on XML elements.
“Data stream transformations” on page 73
@WsiRequestXmlTransform Add transformations of incoming or outgoing data as XML elements. Use this for
@WsiResponseXmlTransform transformations that do not require access to byte data. Contrast to the annota‐
tions in the previous row, which operate on a byte stream.
“Request or response XML structural transformations” on page 63
@WsiSchemaTransform Transform the generated schema that PolicyCenter publishes.
“Transforming a generated schema” on page 63
@WsiSerializationOptions Add serialization options for web service responses, for example supporting en‐
codings other than UTF‐8.
“Setting response serialization options, including encodings” on page 73
Annotation Description
@WsiWebMethod The @WsiWebMethod annotation can perform two actions.
• Override the web service operation name to something other than the
default, which is the method name.
• Suppress a method from generating a web service operation even though
the method has public access.
“Overriding a web service method name or visibility” on page 51
@WsiWebService Declare a class as implementing a web service
“Publishing and configuring a web service” on page 50
package example
uses gw.xml.ws.annotation.WsiWebService
@WsiWebService
class HelloWorldAPI {
Choose your package declaration carefully. The package in which you put your web service implementation class
defines the package for the web service from the SOAP API client perspective.
Arguments and return values must be WS-I exportable. This includes simple types like String, as well as XSD
types and Gosu classes declared final and that have a special annotation. Arguments of array types are not
supported.
package example
uses gw.xml.ws.annotation.WsiWebService
@WsiWebService("http://mycompany.com")
class HelloWorldAPI {
You can omit the namespace declaration entirely and provide no arguments to the annotation. If you omit the
namespace declaration in the constructor, the default is "example.com".
50 chapter 3: Publishing web services
Guidewire PolicyCenter 9.0.6 Integration Guide
Most tools that create stub classes for web services use the namespace to generate a package namespace for related
types.
package example
uses gw.xml.ws.annotation.WsiWebService
uses gw.xml.ws.annotation.
@WsiAvailability(MAINTENANCE)
@WsiWebService
class HelloWorldAPI {
package example
uses gw.xml.ws.annotation.WsiWebService
uses gw.xml.ws.annotation.WsiPermissions
class HelloWorldAPI {
@WsiWebMethod("newMethodName")
public function helloWorld() : String {
return "Hello!"
}
@WsiWebMethod(true)
public function helloWorld() : String {
return "Hello!"
}
@WsiWebMethod("newMethodName", true)
public function helloWorld() : String {
return "Hello!"
}
You can use these APIs to modify response headers from your web service and read request headers as needed.
For example, suppose you want to copy a specific request SOAP header XML object and copy to the response
SOAP header object. Create a private method to get a request SOAP header XML object.
From a web service operation method, declare the invocation context optional argument to your implementation
class. Then you can use code with the invocation context such as the following to get the incoming request header
and add it to the response headers.
3. In your implementation class, use the get and set methods to get or set the variable.
If you call get before calling set in the same web service request, the get method returns the value null.
Generating WSDL
Your web service definition in the WSDL defines a strict programmatic interface to external systems that use your
web service.
The WSDL encodes the structure of all parameters and return values. After moving code into production, be careful
not to change the WSDL. For example, do not modify data transfer objects (DTOs) after going into production or
widely distributing the WSDL in a user acceptance testing (UAT) environment.
SERVER_URL/WEB_APP_NAME/ws/WEB_SERVICE_PACKAGE/WEB_SERVICE_CLASS_NAME?WSDL
SERVER_URL/WEB_APP_NAME/ws/SCHEMA_PACKAGE/SCHEMA_FILENAME
For example, PolicyCenter generates and publishes the WSDL for web service class
example.webservice.TestWsiService at the location on a server with web application name pc.
http://localhost:PORTNUM/pc/ws/example/webservice/TestWsiService?WSDL
SERVER_URL/WEB_APP_NAME/ws
For example:
http://localhost:8580/pc/ws
Example WSDL
The following example demonstrates how a simple Gosu web service translates to WSDL.This example uses the
following simple example web service.
package example
uses gw.xml.ws.annotation.WsiWebService
@WsiWebService
class HelloWorldAPI {
PolicyCenter publishes the WSDL for the HelloWorldAPI web service at this location.
http://localhost:PORTNUMBER/pc/ws/example/HelloWorldAPI?WSDL
PolicyCenter generates the following WSDL for the HelloWorldAPI web service.
<?xml version="1.0"?>
<!-- Generated WSDL for example.HelloWorldAPI web service -->
<wsdl:definitions targetNamespace="http://example.com/example/HelloWorldAPI"
name="HelloWorldAPI" xmlns="http://example.com/example/HelloWorldAPI"
xmlns:gw="http://guidewire.com/xsd" xmlns:soap11="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xs:schema targetNamespace="http://example.com/example/HelloWorldAPI"
elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- helloWorld() : java.lang.String -->
<xs:element name="helloWorld">
<xs:complexType/>
</xs:element>
<xs:element name="helloWorldResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="return" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:portType name="HelloWorldAPIPortType">
<wsdl:operation name="helloWorld">
<wsdl:input name="helloWorld" message="helloWorld"/>
<wsdl:output name="helloWorldResponse" message="helloWorldResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorldAPISoap12Binding" type="HelloWorldAPIPortType">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="helloWorld">
<soap12:operation style="document"/>
<wsdl:input name="helloWorld">
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output name="helloWorldResponse">
<soap12:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="HelloWorldAPISoap11Binding" type="HelloWorldAPIPortType">
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorldAPI">
<wsdl:port name="HelloWorldAPISoap12Port" binding="HelloWorldAPISoap12Binding">
<soap12:address location="http://localhost:8180/pc/ws/example/HelloWorldAPI"/>
<gw:address location="${pc}/ws/example/HelloWorldAPI"/>
</wsdl:port>
<wsdl:port name="HelloWorldAPISoap11Port" binding="HelloWorldAPISoap11Binding">
<soap11:address location="http://localhost:8180/pc/ws/example/HelloWorldAPI"/>
<gw:address location="${pc}/ws/example/HelloWorldAPI"/>
</wsdl:port>
</wsdl:service>
<wsdl:message name="helloWorld">
<wsdl:part name="parameters" element="helloWorld"/>
</wsdl:message>
<wsdl:message name="helloWorldResponse">
<wsdl:part name="parameters" element="helloWorldResponse"/>
</wsdl:message>
</wsdl:definitions>
The preceding generated WSDL defines multiple ports for this web service. A port in the context of a web service is
unrelated to ports in the TCP/IP network transport protocol. Web service ports are alternative versions of a published
web service. The preceding WSDL defines a SOAP 1.1 version and a SOAP 1.2 version of the HellowWorldAPI
web service.
Generate Java classes that make SOAP client calls to a SOAP API
Procedure
1. Launch the server that publishes the web services.
2. On the computer from which you will run your SOAP client code, open a command prompt.
3. Change the working directory to a place on your local disk where you want to generate Java source files
and .class files.
4. Create the subdirectory of the current directory where you want to place the Java source files.
For example, you might choose the folder name src. Ensure that the subdirectory exists before you run the
wsimport tool in the next step. This topic calls this subdirectory SUBDIRECTORY_NAME.
5. Enter the following command:
If the SUBDIRECTORY_NAME directory does not already exist, the wsimport action fails with the error
directory not found.
For WSDL_LOCATION_URL, type the HTTP path to the WSDL. For example:
6. The tool generates Java source files and compiled class files. Depending on what you are doing, you probably
need only the class files or the source files, but not both.
a. The .java files are in the SUBDIRECTORY_NAME subdirectory. To use them, add this directory to your Java
project’s class path, or copy the files to your Java project’s src folder.
The location of the files represents the hierarchical structure of the web service namespace in reverse
order, followed by the fully qualified name.
The namespace is a URL that each published web service specifies in its declaration. It represents a
namespace for all the objects in the WSDL. A typical namespace would specify your company domain
name and perhaps other meaningful disambiguating or grouping information about the purpose of the
service. For example, http://mycompany.com.
You can specify the namespace for each web service by passing a namespace as a String argument to the
@WsiWebService annotation. If you do not override the namespace when you declare the web service, the
default is http://example.com.
The path to the Java source file has the following structure.
CURRENT_DIRECTORY/SUBDIRECTORY_NAME/REVERSED_NAMESPACE/FULLY_QUALIFIED_NAME.java
For example, suppose your web service's fully qualified name is com.mycompany.HelloWorld and the
namespace is the default http://example.com. If you use the SUBDIRECTORY_NAME value src, the
wsimport tool generates the .java file at the following location:
CURRENT_DIRECTORY/src/com/example/com/mycompany/HelloWorld.java
b. To use the generated Java .class files, add the generated directory to your Java project’s class path, or
copy the files to your Java project’s src folder.
The compiled .class files are placed in a hierarchy by package name with the same basic naming
convention as the .java files but with no SUBDIRECTORY_NAME.
CURRENT_DIRECTORY/SUBDIRECTORY_NAME/REVERSED_NAMESPACE/FULLY_QUALIFIED_NAME
The wsimport tool generates the .class files at the following location:
CURRENT_DIRECTORY/com/example/com/mycompany/HelloWorld.class
7. The next step depends on whether you want just the .class files to compile against, or whether you want to
use the generated Java files.
• To use the .java files, copy the SUBDIRECTORY_NAME subdirectory into your Java project’s src folder.
• To use the .class files, copy the files to your Java project’s src folder or add that directory to your
project’s class path.
8. Write Java SOAP API client code that compiles against these new generated classes.
new API_INTERFACE_NAME().getAPI_INTERFACE_NAMESoap11Port();
For example, for the API interface name HelloWorldAPI, the Java code looks like the following statement.
Once you have that port reference, you can call your web service API methods directly on it.
You can publish a web service that does not require authentication by overriding the set of permissions necessary for
the web service. See “Specifying required permissions for a web service” on page 51. The following is a simple
example to show calling the web service without worrying about the authentication-specific code.
import com.example.example.helloworldapi.HelloWorldAPI;
import com.example.example.helloworldapi.HelloWorldAPIPortType;
// Get a reference to the SOAP 1.1 port for this web service
HelloWorldAPIPortType port = new HelloWorldAPI().getHelloWorldAPISoap11Port();
// Print result
System.out.println("Web service result = " + res);
}
}
import com.example.example.helloworldapi.HelloWorldAPI;
import com.example.example.helloworldapi.HelloWorldAPIPortType;
import com.sun.xml.internal.ws.api.message.Headers;
import import javax.xml.ws.BindingProvider;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.ws.BindingProvider;
import java.util.Map;
// get a reference to the SOAP 1.1 port for this web service
The following code shows how to use Java client code to access a web service with the fully-qualified name
example.helloworldapi.HelloWorld using a custom SOAP header.
After authenticating, the example calls the helloWorld SOAP API method.
import com.example.example.helloworldapi.HelloWorldAPI;
import com.example.example.helloworldapi.HelloWorldAPI;
import com.example.example.helloworldapi.HelloWorldAPIPortType;
import com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl;
import com.sun.xml.internal.messaging.saaj.soap.ver1_1.Header1_1Impl;
import com.sun.xml.internal.messaging.saaj.soap.ver1_1.HeaderElement1_1Impl;
import com.sun.xml.internal.ws.developer.WSBindingProvider;
import com.sun.xml.internal.ws.api.message.Headers;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
// Get a reference to the SOAP 1.1 port for this web service.
HelloWorldAPIPortType port = new HelloWorldAPI().getHelloWorldAPISoap11Port();
// Create XML for special SOAP headers for Guidewire authentication of a user & password.
// Set the username and password, which are content within the username and password elements.
usernameElement.setTextContent("su");
passwordElement.setTextContent("gw");
// Uncomment the following lines to see the XML for the authentication header.
DOMSerializerImpl ser = new DOMSerializerImpl();
System.out.println(ser.writeToString(authElement));
}
}
gwb genWsiLocal
PolicyCenter generates the WSDL in the wsi.local package, followed by the fully qualified name of the web
service.
wsi.local.FQNAME.wsdl
mycompany.ws.v100.EchoAPI
PolicyCenter/modules/configuration/gsrc/wsi/local/mycompany/ws/v100/EchoAPI.wsdl
Call this web service locally with the following line of code.
If you change the code for the web service and the change potentially changes the WSDL, regenerate the WSDL.
PolicyCenter includes with WSDL for some local services in the default configuration. These WSDL files are in
Studio modules other than configuration. If PolicyCenter creates new local WSDL files from the
gwb genWsiLocal tool, it creates new files in the configuration module in the gsrc directory.
The wsi.local.* namespace exists only to call web services from GUnit unit tests. It is unsafe to write production
code that ever uses or calls wsi.local.* types.
To reduce the chance of accidental use of wsi.local.* types, Gosu prevents using these types in method signatures
of published web services.
package example
uses gw.xml.ws.annotation.WsiWebService
@WsiWebService("http://mycompany.com")
class HelloWorldAPI {
The following sample Gosu code is a GUnit test of the preceding HelloWorldAPI web service.
package example
uses gw.testharness.TestBase
construct() {
api.Config.Guidewire.Authentication.Username = "su"
api.Config.Guidewire.Authentication.Password = "gw"
var res = api.helloWorld();
For more thorough testing, test your web service from integration code on an external system. To ensure your web
service scales adequately, test your web service with as large a data set and as many objects as potentially exist in
your production system. To ensure the correctness of database transactions, test your web service to exercise all
bundle-related code.
always be a registered version of this plugin, otherwise web services that require permissions cannot authenticate
successfully.
The WebservicesAuthenticationPlugin plugin interface supports web service connections only.
_handler.verifyInternalCredentials(username, password)
See also
• “User authentication service plugin” on page 187
However, if your web service client code wants to explicitly test specific authentication credentials, PolicyCenter
publishes the built-in Login web service. Call this web service’s login method, which takes a user name as a
String and a password as a String. If authentication fails, the API throws an exception.
If the authentication succeeds, that server creates a persistent server session for that user ID and returns the session
ID as a String. The session persists after the call completes. In contrast, a normal API call creates a server session
for that user ID but clears the session as soon as the API call completes.
If you call the login method, you must call the matching logout method to clear the session, passing the session ID
as an argument. If you were merely trying to confirm authentication, call logout immediately.
However, in some rare cases you might want to leave the session open for logging purposes to track the owner of
multiple API calls from one external system. After you complete your multiple API calls, finally call logout with
the original session ID.
If you fail to call logout, all application servers are configured to time out the session eventually.
See also
• “Data stream transformations” on page 73
).ComplexType.Sequence.Element[1].MinOccurs = 1
} )
You can also change the XML associated with the WSDL outside the schema element.
package gw.examples
uses gw.xml.ws.annotation.WsiExportable
@WsiExportable
final class Car {
// Private fields defined with public Gosu property names in the recommended style
private var _color : String as Color
private var _model : String as Model
uses gw.xml.ws.WsiExportableUtil
uses gw.xml.XmlElement
WsiExportableUtil.marshal(xml, obj)
<?xml version="1.0"?>
<root xmlns:pogo="http://example.com/gw/examples">
<pogo:Color>Blue</pogo:Color>
<pogo:Model>234</pogo:Model>
</root>
The pogo: prefix is the short name for the namespace that was generated by the marshal method. If the
@WsiExportable annotation had specified an optional String namespace argument, that namespace would have
been used in the generated XML.
uses gw.xml.ws.WsiExportableUtil
uses gw.xml.XmlElement
// Alternatively, specify the DTO type as an argument and downcast the return value
// var car2 = unmarshal(incomingXML, gw.examples.Car) as gw.examples.Car
Some organizations require web service publishers to conform to predefined XML types defined in an XSD, or even
predefine WSDL. However, if you can use shared XSDs instead of a predefined WSDL, it is recommended to use
shared XSDs only.
You can write your web service to use a standard XSD to define individual types. For example, suppose a pre-
existing WSDL defines an XSD that defines 200 object types for method arguments and return types. You can add
the XSD to the source code tree in Studio and access all the XSD types directly from Gosu in a type-safe way. In
this case, the XSD types are acting as Data Transfer Objects (DTOs), a general term for a constrained data definition
specifically for web services. See the cross references at the end of this section.
If you are required to implement a preexisting service definition in a specific predefined WSDL, you can do so using
a feature called invocation handlers. By using a standardized WSDL, an organization can ensure that all related
systems conform to predefined specifications. The technical approach of invocation handlers can lead to more
complexity in your Gosu code, which can make it harder to catch problems at compile time.
• The invoke method does the actual dispatch work of the web service for all operations on the web service. Gosu
does not call any other methods on the web service implementation. Instead, the invocation handler handles all
operations that normally would be in various methods on a typical web service implementation class.
• Your invoke method can call its super implementation to trigger standard method calls for each operation based
on the name of the operation. Use this technique to run custom code before or after standard method invocation,
either for logging or special logic.
In the invoke method of your invocation handler, determine which operation to handle by checking the type of the
requestElement method parameter. For each operation, perform whatever logic makes sense for your web service.
Return an object of the appropriate type. Get the type of the return object from the XSD-based types created from
the WSDL.
Finally, for the WSDL for the service to generate successfully, add the preexisting WSDL to your web service using
the parse options annotation @WsiParseOptions. Pass the entire WSDL as the schema as described in that topic.
PolicyCenter/configuration/gsrc/ws/weather.wsdl
The schema for this file has the Gosu syntax: ws.weather.util.SchemaAccess. Its element types are available in
the Gosu type system as objects in the package ws.weather.elements.
The method signature of the invoke method returns an object of type XmlElement, the base class for all XML
elements. Be sure to carefully create the right subtype of XmlElement that appropriately corresponds to the return
type for every operation.
66 chapter 3: Publishing web services
Guidewire PolicyCenter 9.0.6 Integration Guide
The following example implements a web service that conforms to a preexisting WSDL and implements one of its
operations.
package gw.xml.ws
uses gw.xml.ws.annotation.WsiWebService
uses gw.xml.ws.annotation.WsiInvocationHandler
uses gw.xml.XmlElement
uses gw.xml.ws.annotation.WsiPermissions
uses gw.xml.ws.annotation.WsiAvailability
uses gw.xml.ws.annotation.WsiParseOptions
uses gw.xml.XmlParseOptions
uses java.lang.IllegalArgumentException
@WsiWebService("http://guidewire.com/px/ws/gw/xml/ws/WsiImplementExistingWsdlTestService")
@WsiPermissions({})
@WsiAvailability(NONE)
@WsiInvocationHandler(new WsiImplementExistingWsdlTestService.Handler())
@WsiParseOptions(new XmlParseOptions() { :AdditionalSchemas = { ws.weather.util.SchemaAccess } })
class WsiImplementExistingWsdlTestService {
// The following line declares an INNER CLASS within the outer class.
static class Handler extends DefaultWsiInvocationHandler {
// Here we implement the "weather" wsdl with our own GetCityForecastByZIP implementation.
override function invoke(requestElement : XmlElement, context : WsiInvocationContext)
: XmlElement {
// The next line uses type inference to instantiate XML object of the correct type
// rather than specifying it explicitly.
:GetCityForecastByZIPResult = new() {
:Success = true,
:City = "Demo city name for ZIP ${requestElement.ZIP}"
}
return returnResult
}
else {
throw new IllegalArgumentException("Unrecognized element: " + requestElement)
}
}
}
}
First, the invoke method checks if the requested operation is the desired operation. An operation normally
corresponding to a method name on the web service, but in this approach one method handles all operations. In this
simple example, the invoke method handles only the operation in the WSDL called GetCityForecastByZip. If the
requested operation is GetCityForecastByZip, the code creates an instance of the
GetCityForecastByZIPResponse XML element.
Next, the example uses Gosu object creation initialization syntax to set properties on the element as appropriate.
Finally, the code returns that XML object to the caller as the result from the API call.
For additional context of the WSI request, use the context parameter to the invoke method. The context
parameter has type WsiInvocationContext, which contains properties such as servlet and request headers.
• The application does not check for duplicate external transaction IDs if present.
However, you can support all these things in your web service even when using an invocation handler, and in typical
cases it is best to do so.
2. In your invocation handler's invoke method, determine which method to call based on the operation name.
3. Get a reference to the method info meta data for the method you want to call, using the # symbol to access
meta data of a feature (method or property).
4. Before calling your method, get a reference to the WsiInvocationContext object that is a method argument
to invoke. Call its preExecute method, passing the requestElement and the method info metadata as
arguments. If you do not require checking method-specific annotations for run level or permissions, for the
method info metadata argument you can pass null.
The preExecute method does several things.
• Enables profiling for the method you are about to call if profiling is available and configured.
• Checks the SOAP headers looking for headers that set the locale. If found, sets the specified locale.
• Checks the SOAP headers for a unique transaction ID. This ID is intended to prevent duplicate requests. If
this transaction has already been processed successfully (a bundle was committed with the same ID),
preExecute throws an exception.
• If the method info argument is non-null, preExecute confirms the run level for this service, checking both
the class level @WsiAvailability annotation and any overrides for the method. As with standard
implementation classes, the method level annotation supersedes the class level annotation. If the run level is
not at the required level, preExecute throws an exception.
• If the method info argument is non-null, preExecute confirms user permissions for this service, checking
both the class level @WsiPermissions annotation and any overrides for the method. As with standard
implementation classes, the method level annotation supersedes the class level annotation. If the permissions
are not satisfied for the web service user, preExecute throws an exception.
5. Call your method from the invocation handler.
See also
• “Example of an invocation handler for preexisting WSDL” on page 66
// The following line declares an INNER class within the outer class.
static class Handler extends DefaultWsiInvocationHandler {
// Get the local part (short name) from operation name, and get the method info for it
var method = _map.get(opName.LocalPart)
// Call your method using the method info and return its result
return method.CallHandler.handleCall(null, {requestElement}) as XmlElement
}
}
// After defining your invocation handler inner class, define the methods that do your work
// as separate static methods
This use is the only one supported for a WsiInvocationContext object’s preExecute method. Any use other than
calling it exactly once from within an invocation handler invoke method is unsupported.
@WsiAdditionalSchemas({ gw.xml.ws.wsimyschema.util.SchemaAccess })
of type XmlParseOptions, which contains a property called AdditionalSchemas. That property must contain a list
of schemas.
To add a single schema, you can use the following compact syntax.
For an XSD called WS.xsd in the source code file tree in the package com.abc, use the following syntax.
To include an entire WSDL file as an XSD, use the same syntax. For example, if the file is WS.wsdl.
gwb genSchemaJar
2. Create the Schema JAR file by running the gwb genSchemaJar task.
gwb genSchemaJar
The Schema JAR file is a dependency for building the Configuration module. The Configuration module is built by
running the gwb compile task.
gwb compile
ext {
xmlSchemaVersion = "1.0.0"
xmlSchemaJarFilename = "gw-xml-schemas-${xmlSchemaVersion}.jar".toString()
}
• In the build.gradle file located in the modules/schemas directory, append the following lines to the end of the
file.
afterEvaluate {
tasks.genSchemaJar.conventionMapping.archiveName = { xmlSchemaJarFilename }
}
• In the build.gradle file located in the modules/configuration directory, modify the genSchemaJar
dependencies block to reference the versioned filename, as shown below.
dependencies {
task (‘:modules:schemas:genSchemaJar’)
compile files(xmlSchemaJarFilename)
schemajars files(xmlSchemaJarFilename)
}
Whenever the JAR version changes, the Studio project must be regenerated to retrieve the new dependency for the
Configuration module. Regenerate the Studio project by running gwb idea on the command line. Alternatively,
regenerate the project in Studio by selecting Tools→Generate Project. Afterward, create the Schema JAR by running
Publishing web services 71
Guidewire PolicyCenter 9.0.6 Integration Guide
gwb genSchemaJar. Finally, build the application by either running gwb compile on the command line or selecting
Build→Rebuild Project in Studio.
ext {
xmlSchemaVersion = "1.0.0"
xmlSchemaGroupId = ‘com.myinsuranceco.cc’
xmlSchemaArtifactId = ‘schemas’
xmlSchemaJarFilename = ‘gw-xml-schemas.jar".toString()
}
• In the build.gradle file located in the modules/schemas directory, add the following line after the existing
apply plugin lines.
• In the same file, add the following lines after the closure of the tasks.compileSchemaSources.options.with
block. Replace the Maven repository url reference in the example with the URL of your own repository.
group = xmlSchemaGroupId
version = xmlSchemaVersion
artifacts {
archives genSchemaJar
}
publishing {
publications {
maven(MavenPublication) {
artifact genSchemaJar
}
}
repositories {
maven { url ‘http://nexus.myinsuranceco.com/content/repositories/releases’ }
}
}
• In the build.gradle file located in the modules/configuration directory, add the following lines after the
closure of the genSchemaJar dependencies block. Replace the Maven repository url reference in the example
with the URL of your own repository.
repositories {
maven { url ‘http://nexus.myinsuranceco.com/content/repositories/releases’ }
mavenLocal() // Used by integration developers only.
}
dependencies {
compile(xmlSchemasArtifact)
schemajars(xmlSchemasArtifact)
}
• If the referenced Maven url repository is not a local repository used for files under development, perform the
following step.
◦ Edit the gwb and gwb.bat files located in the PolicyCenter installation directory to remove all references to the
--offline argument.
To publish a new JAR version, perform the following steps.
72 chapter 3: Publishing web services
Guidewire PolicyCenter 9.0.6 Integration Guide
transformation followed by a digital signature transformation produces a different request data stream than if the
same transformations are performed in the opposite order.
The following example performs a simple search-and-replace operation on a request data stream. An encryption
operation could follow a similar process.
uses gw.util.StreamUtil
class sampleRequestTransform {
See also
• If the desired transformation operates more naturally on XML elements than on a byte stream, consider using the
APIs in “Request or response XML structural transformations” on page 63.
package gw.webservice.example
uses gw.util.StreamUtil
uses gw.xml.ws.annotation.WsiWebService
uses gw.xml.ws.annotation.WsiRequestTransform
uses gw.xml.ws.annotation.WsiResponseTransform
uses java.io.ByteArrayInputStream
uses java.io.InputStream
@WsiWebService
// Specify data stream transformations for web service requests and responses.
@WsiRequestTransform(WsiTransformTestService._xorTransform)
@WsiResponseTransform(WsiTransformTestService._xorTransform)
class WsiTransformTestService {
// Declare a static variable to hold a Gosu block that encrypts and decrypts data streams.
public static var _xorTransform(inputStream : InputStream) : InputStream = \ inputStream ->{
In the preceding example, the request transformation and the response transformation use the same Gosu block for
transformation logic because the block uses a symmetrical algorithm. In a typical production usage, the request
transformation and the response transformation use different Gosu blocks because their transformation logic differs.
See also
• “Using WSS4J for encryption, signatures, and other security headers” on page 75
package gw.webservice.example
uses gw.api.util.ConfigAccess
uses java.io.ByteArrayInputStream
uses java.io.ByteArrayOutputStream
uses java.io.InputStream
uses java.util.Vector
uses java.util.Properties
uses java.lang.RuntimeException
uses javax.xml.parsers.DocumentBuilderFactory
uses javax.xml.transform.TransformerFactory
uses javax.xml.transform.dom.DOMSource
uses javax.xml.transform.stream.StreamResult
uses org.apache.ws.security.message.*
uses org.apache.ws.security.*
uses org.apache.ws.security.handler.*
// Parse the input stream into a DOM (Document Object Model) tree.
var domEnvironment = parseDOM(inputStream)
// Parse the input stream into a DOM (Document Object Model) tree.
var envelope = parseDOM(inputStream)
if (eResult.Action != WSConstants.ENCR) {
print(eResult.Principal.Name);
}
}
return org.apache.ws.security.components.crypto.CryptoFactory.getInstance(cryptoProps)
}
return factory.newDocumentBuilder().parse(inputStream);
}
return baos.toByteArray();
}
}
package gw.webservice.example
uses gw.xml.ws.annotation.WsiWebService
uses gw.xml.ws.annotation.WsiRequestTransform
uses gw.xml.ws.annotation.WsiResponseTransform
uses gw.xml.ws.annotation.WsiPermissions
uses gw.xml.ws.annotation.WsiAvailability
@WsiWebService
@WsiAvailability(NONE)
@WsiPermissions({})
@WsiRequestTransform(\ inputStream ->DemoCrypto.removeCrypto(inputStream))
@WsiResponseTransform(\ inputStream ->DemoCrypto.addCrypto(inputStream))
// This web service computes the sum of two integers. The web service decrypts incoming SOAP
// requests and encrypts outgoing SOAP responses.
class DemoService {
Notice the following implementation details in this web service implementation class.
• The web service provides a method that adds two numbers, but the service itself has a request and response
transformation.
• The request transformation removes and confirms the cryptographic layer on the request, including the digital
signature and encryption, by calling DemoCrypto.removeCrypto(inputStream).
• The response transformation adds the cryptographic layer on the response by calling
DemoCrypto.addCrypto(inputStream).
Paste this code into the Gosu Scratchpad and run it.
<soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<gwsoap:gw_locale xmlns:gwsoap="http://guidewire.com/ws/soapheaders">fr_FR</gwsoap:gw_locale>
<gwsoap:gw_language xmlns:gwsoap="http://guidewire.com/ws/soapheaders">fr_FR</gwsoap:gw_language>
</soap12:Header>
<soap12:Body>
...
</soap12:Body>
</soap12:Envelope>
See also
• “Setting locale or language in a Guidewire application” on page 93
If the web service changes any database data, the application stores the transaction ID in an internal database table
for future reference. If in the future, some code calls the web service again with the same transaction ID, the
database commit fails and throws the following exception.
com.guidewire.pl.system.exception.DBAlreadyExecutedException
The caller of the web service can detect this exception to identify the request as a duplicate transaction.
Because this annotation relies on database transactions (bundles), if your web service does not change any database
data, this API has no effect.
See also
• If your client code is written in Gosu, to set the SOAP header see “Setting Guidewire transaction IDs on web
service requests” on page 91.
<xs:simpleType name="HouseType">
<xs:restriction base="xs:string">
<xs:enumeration value="apartment"/>
<xs:enumeration value="house"/>
<xs:enumeration value="shack"/>
<xs:enumeration value="mobilehome"/>
</xs:restriction>
</xs:simpleType>
The published web service validates any incoming values against the set of choices and throws an exception for
unknown values. Depending on the client implementation, the web service client might check if responses contain
only allowed enumeration values during de-serialization. For typical cases, this approach is the desired behavior for
both server and client.
For example, suppose you add new codes to a typelist or enumeration for responses. If the service returns an
unexpected value in a response, it might be desirable that the client throws an exception. System integrators would
quickly detect this unexpected change. The client system can explicitly refresh the WSDL and carefully check how
the system explicitly handles any new codes.
However, in some cases you might want to expose enumerations as String values instead.
• The WSDL for a service that references typelist or enumeration types can grow in size significantly. This is true
especially if some typelists or enumerations contain a vast number of choices. The number of values for a Java
enumeration type cannot exceed 2000.
• Changing enumeration values even slightly can cause an incompatible WSDL. Forcing the web service client to
refresh the WSDL might exacerbate upgrade issues on some projects. Although the client can refresh the WSDL
from the updated service, sometimes this is an undesirable requirement. For example, perhaps new enumeration
values on the server are predictably irrelevant to an older external system.
• In some cases, your actual web service client code might be middleware that passes through String values from
another system. In such cases, you may not require explicit detection of enumeration changes in the web service
client code.
To expose typelist types and enumerations (from Gosu or Java) as a String type, add the
@WsiExposeEnumAsString annotation before the web service implementation class. In the annotation constructor,
pass the typelist or enumeration type as the argument. For example, to expose the HouseType enumeration as a
String, add the following line before the web service implementation class declaration:
@WsiExposeEnumAsString(HouseType)
To expose multiple types as String values, repeat the annotation for each individual type on a separate
corresponding line. In this case, each separate line provides a different type as an argument. You can also add the
@WsiExposeEnumAsString value as a default.
uses gw.xml.ws.WsdlConfig
uses java.net.URI
uses wsi.remote.gw.webservice.ab.ab900.abcontactapi.ABContactAPI
// Get URL and override URL to force creation of local cookies to save session for load balancing
api.Config.ServerOverrideUrl = new URI(ABContactAPI.ADDRESS + "?stateful")
The code might look very different depending on your choice of web service client programming language and
SOAP library.
Gosu code can import SOAP API web services from external systems and call these services as a SOAP client. The
Gosu language handles all aspects of object serialization, object deserialization, basic authentication, and SOAP
fault handling.
gwb genFromWsc
Note: You cannot specify local: as the protocol to load a web service's WSDL. You must use the
URL of the server or a variable that resolves to a valid URL, and you must ensure that the server is
running before loading its WSDL.
Note: While you can specify multiple environments in the Environment field, the PolicyCenter server
runs in only one environment. In the case of a server cluster, PolicyCenter requires that all servers in
the cluster to start in the same environment.
Additionally, it is invalid to specify multiple identical environment-server pairs in a configuration.
Such configuration elements are duplicates and result in runtime errors.
Loading WSDL directly into the file system for testing purposes
For testing, or in other unusual cases, you might want to load WSDL directly to the file system without using a web
service collection.
Guidewire strongly recommends that you create a web service collection for consuming external web services
instead of loading WSDL directly to the file system.
To consume an external web service, put the appropriate WSDL and XML schema files (XSDs) in the Gosu class
hierarchy on your local system. Place them in the directory that corresponds to the package in which you want new
types to appear. For example, place the WSDL and XSD files next to the Gosu class files that call the web service,
organized in package hierarchies just like class files.
The following sample Gosu code shows how to manually fetch web service WSDLs for test purposes or for
command-line use from a web service server.
uses gw.xml.ws.*
uses java.net.URL
uses java.io.File
// Set the web service endpoint URL for the web service WSDL
var urlStr = "http://www.aGreatWebService.com/GreatWebService?wsdl"
// Set the location in your file system for the web service WSDL
var loc = "/wsi/remote/GreatWebService"
The urlStr variable stores the URL to the web service WSDL. The loc variable contains the path on your file
system where the fetched WSDL is stored. You can run your version of the preceding sample Gosu code in the Gosu
Scratchpad.
82 chapter 4: Calling web services from Gosu
Guidewire PolicyCenter 9.0.6 Integration Guide
ws.myservice.*
Suppose you add a WSDL file directly to your class hierarchy called MyService.wsdl in the package
example.pl.gs.wsic. Gosu creates all the types for your web service in the following namespace.
example.pl.gs.wsic.myservice.*
The name of MyService becomes lowercase myservice in the package hierarchy for the XML objects because the
Gosu convention for package names is lowercase. There are other name transformations as Gosu imports types from
XSDs.
The structure of a WSDL comprises the following items.
• One or more services
• For each service, one or more ports
A port represents a protocol or other context that might change how the WSDL defines that service. For example,
methods might be defined differently for different versions of SOAP, or an additional method might be added for
some ports. WSDL might define one port for SOAP 1.1 clients, one port for SOAP 1.2 clients, one port for
HTTP non-SOAP access, and so on. See discussion later in this topic for what happens if multiple ports exist in
the WSDL.
• For each port, one or more methods
A method, also called an operation or action, performs a task and optionally returns a result. The WSDL includes
XML schemas (XSDs), or it imports other WSDL or XSD files. Their purposes are to describe the data for each
method argument type and each method return type.
Suppose the WSDL has the following hierarchy.
<wsdl>
<types>
<schema>
<import schemaLocation="yourschema.xsd"/>
<!-- Now define various operations (API methods) in the WSDL ... -->
The details of the web service APIs are omitted in this example WSDL. Assume the web service contains exactly
one service called SayHello, and that service contains one method called helloWorld. For this first example,
Calling web services from Gosu 83
Guidewire PolicyCenter 9.0.6 Integration Guide
assume that the method takes no arguments, returns no value, and is published with no authentication or security
requirements.
In Gosu, you can call the remote service represented by the WSDL.
// Get a reference to the web service API object in the namespace of the WSDL
// Warning: This object is not thread-safe. Do not save in a static variable or singleton intance var.
var service = new ws.myservice.SayHello()
Of course, real APIs need to transfer data also. In our example WSDL, notice that the WSDL refers to a secondary
schema called yourschema.xsd.
Studio adds any attached XSDs into the web_service_name.wsdl.resources subdirectory.
Let us suppose the contents of your yourschema.xsd file look like the following.
<schema>
<element name="Root" type="xsd:int"/>
</schema>
Note that the element name is "root" and it contains a simple type (int). This XSD represents the format of an
element for this web service. The web service could declare a <root> element as a method argument or return type.
Now let us suppose there is another method in the SayHello service called doAction and this method takes one
argument that is a <root> element.
In Gosu, you can call the remote service represented by the WSDL.
// Create an XML document from the WSDL by using the Gosu XML API
var x = new ws.myservice.Root()
The package names are different if you place your WSDL file in a different part of the package hierarchy.
If you use Guidewire Studio, you do not need to manipulate the WSDL file manually. Studio automates getting the
WSDL and saving it when you add a Web Service in the user interface.
For each web service API call, Gosu first evaluates the method parameters. Gosu serializes the root XmlElement
instance and its child elements into XML raw data using the associated XSD data from the WSDL. Next, Gosu
sends the resulting XML document to the web service. In the SOAP response, the main data is an XML document,
whose schema is contained in (or referenced by) the WSDL.
Be warned that the WS-I API object is not thread-safe in all cases. It is dangerous to modify any configuration when
another thread might have a connection open. Also, some APIs may directly or indirectly modify the state on the
API object itself.
For example, the initializeExternalTransactionIdForNextUse method saves information that is specific to one
request, and then resets the transaction ID after one use.
element.PropertyName[0] = childElement
If the list does not exist yet for a list property at all, Gosu creates the list upon the first insertion. In other words,
suppose an element contains child elements that represent an address and the child element has the name
Address. If the XSD declares the element could exist more than once, the element.Address property is a list of
addresses. The following code creates a new Address:
ROOT_PACKAGE.WSDL_NAME_NORMALIZED.NORMALIZED_SERVICE_NAME
The NORMALIZED_SERVICE_NAME name of the package is the name of the service as defined by the WSDL, with
capitalization and conflict resolution as necessary. For example, if there are two services in the WSDL named
Report and Echo, then the API types are in the following location.
example.pl.gs.wsic.myservice.Report
example.pl.gs.wsic.myservice.Echo
Gosu chooses a default port for each service. If there is a SOAP 1.2 version, Gosu prefers that version.
Additionally, Gosu provides the ability to explicitly choose a port. For example, if there is a SOAP 1.1 port and a
SOAP 1.2 port, you could explicitly reference one of those choices. Gosu creates all the types for your web service
ports within the ports subpackage, with types based on the name of each port in the WSDL.
ROOT_PACKAGE.WSDL_NAME_NORMALIZED.ports.SERVICE_AND_PORT_NAME
The SERVICE_AND_PORT_NAME is the service name, followed by an underscore, followed by the port name.
For example, suppose the ports are called p1 and p2 and the service is called Report. Gosu creates types within the
following packages.
example.pl.gs.wsic.myservice.ports.Report_p1
example.pl.gs.wsic.myservice.ports.Report_p2
Additionally, if the port name happens to begin with the service name, Gosu removes the duplicate service name
before constructing the Gosu type. For example, if the ports are called ReportP1, and helloP2, Gosu creates types
within the following packages.
Each one of those hierarchies would include method names for that port for that service.
If a web service requires encryption, authentication, or digital signatures, there are two approaches available.
• Configuration objects on the service instance
Set the configuration options directly on the configuration object for the service instance. The service instance is
the newly-instantiated object that represents the service. In the previous example, the api variable holds a
reference for the service instance. That object has a Config property that contains the configuration object of
type WsdlConfig.
• Configuration providers in Studio
Add one or more WS-I web service configuration providers in the Studio Web Service Collection editor Settings
tab.
You can write zero, one, or more than one configuration providers and attach them to a web service collection. This
means that for each new connection to one of those services, each configuration provider has an opportunity to
(optionally) add configuration options to the WsdlConfig object.
For example, you could write one configuration provider that adds all configuration options for web services in the
collection, or write multiple configuration providers that configure different kinds of options. For an example of
multiple configuration providers, you could implement the following solution.
• Add one configuration provider that knows how to add authentication.
• Add a second configuration provider that knows how to add digital signatures.
• Add a third configuration provider that knows how to add an encryption layer.
Separating out these different types of configuration could be advantageous if you have some web services that
share some configuration options but not others. For example, perhaps all your web service collections use digital
signatures and encryption, but the authentication configuration provider class might be different for different web
service collections.
The list of configuration provider classes in the Studio editor is an ordered list. For typical systems, the order is very
important. For example, performing encryption and then a digital signature results in different output then adding a
digital signature and then adding encryption. You can change the order in the list by clicking a row and clicking
Move Up or Move Down. You can configure these settings by environment (Env) or server (Server). For default items, set
them first in the list and leave the Env or Server fields blank to indicate it as a default. For example, if you have a
default configuration provider, set that item to a blank Env setting and move it first in the list. Later items that might
specify a non-blank Env setting will override that default value. Follow a similar approach for any defaults for any
default settings using the Server settings.
The list of configuration providers in the Studio editor is an ordered list. If you use more than one configuration
provider, carefully consider the order you want to specify them. For any defaults, such as those with blank Env or
Server fields, put those at the top (beginning) of the list.
The following is an example of a configuration provider.
package wsi.remote.gw.webservice.ab
uses javax.xml.namespace.QName
uses gw.xml.ws.WsdlConfig
uses gw.xml.ws.IWsiWebserviceConfigurationProvider
In this example, the configuration provider adds Guidewire authentication to every connection that uses that
configuration provider. Any web service client code for that web service collection does not need to add these
options with each use of the service.
The built-in authentication schemes are HTTP basic authentication, HTTP digest authentication, and Guidewire
authentication.
88 chapter 4: Calling web services from Gosu
Guidewire PolicyCenter 9.0.6 Integration Guide
When you call a method on the WS-I API service object, authentication happens as follows.
1. Gosu reviews properties on the WsdlConfig object in the Config property on the API instance.
2. The server looks for properties for Guidewire authentication. If they exist, Gosu attempts to authenticate using
Guidewire authentication.
3. The server looks for properties for HTTP basic authentication. If they exist, Gosu attempts to authenticate
using HTTP basic authentication.
4. The server looks for properties for HTTP digest authentication. If they exist, Gosu attempts to authenticate
using HTTP basic authentication.
5. The server attempts to connect to the service without authentication.
api.Config.Http.Authentication.Basic
That object has a Username property for the user name and a Password property for the password. Set those two
values with the desired user name and password.
service.Config.Http.Authentication.Basic.Username = "jms"
service.Config.Http.Authentication.Basic.Password = "b5"
api.Config.Http.Authentication.Digest
That object has a Username property for the user name and a Password property for the password. Set those two
values with the desired user name and password.
Calling web services from Gosu 89
Guidewire PolicyCenter 9.0.6 Integration Guide
service.Config.Http.Authentication.Digest.Username = "jms"
service.Config.Http.Authentication.Digest.Password = "b5"
Guidewire authentication
If you are connecting to a Guidewire application, use Guidewire authentication, which authenticates against the user
database. To consume a web service that is not published by a Guidewire application, use Guidewire authentication.
User names and passwords are sent unencrypted in HTTP basic authentication and Guidewire authentication
schemes. If you use HTTP basic or Guidewire authentication across an insecure network, it is critical that you wrap
the web service requests with HTTPS/SSL connections to protect security credentials. In contrast, the HTTP digest
authentication uses a more secure hashing scheme that does not send the password unencrypted. However, even with
HTTP digest authentication, the request and response are unencrypted. Therefore using HTTPS/SSL connections is
still valuable for overall data security over insecure networks.
To add Guidewire application authentication to API request, use the Guidewire authentication object at the path as
follows. In this example, api is a reference to a SOAP API that you have already instantiated with the new operator:
api.Config.Guidewire.Authentication
That object has a Username property for the user name and a Password property for the password. Set those two
values with the desired user name and password.
service.Config.Guidewire.Authentication.Username = "jms"
service.Config.Guidewire.Authentication.Password = "b5"
<suite-config xmlns="http://guidewire.com/config/suite/suite-config">
<product name="cc" url="http://localhost:8080/cc"/>
<product name="pc" url="http://localhost:8180/pc"/>
<product name="ab" url="http://localhost:8280/ab"/>
<product name="bc" url="http://localhost:8580/bc"/>
</suite-config>
In production, the applications would be on separate physical servers with different domain names for each
application.
The optional env attribute can be specified in a <product> element to define an environment setting for the product.
A single product can have multiple configurations differentiated by their environments. For example, separate
ContactManager configurations can be defined for production and development environments.
90 chapter 4: Calling web services from Gosu
Guidewire PolicyCenter 9.0.6 Integration Guide
<suite-config xmlns="http://guidewire.com/config/suite/suite-config">
<product name="ab" url="http://localhost:8080/cc"/>
<product name="ab" url="http://localhost:8080/cc" env="development"/>
<product name="ab" url="http://ProductionClaimCenterServer:8080/cc" env="production"/>
</suite-config>
The env attribute is optional. A maximum of one configuration for a particular product can exclude the env attribute.
A product configuration without an env attribute is interpreted as the default configuration to use whenever an
explicit system environment for PolicyCenter is not specified.
When importing WS-I WSDL, PolicyCenter does the following.
1. Checks to see whether there is a WSDL port of element type <gwwsdl:address>. If this is found,
PolicyCenter ignores any other ports on the WSDL for this service.
2. If so, it looks for shortcuts of the syntax ${productNameShortcut}. For example: ${pc}
3. If that product name shortcut is in the suite-config.xml file, PolicyCenter substitutes the URL from the
XML file to replace the text ${productNameShortcut}. If the product name shortcut is not found, Gosu
throws an exception during WSDL parsing.
For web services that Guidewire applications publish, all WSDL documents have the <gwwsdl:address> port in
the WSDL. The Guidewire application automatically specifies the application that published it using the standard
two-letter application shortcut. For example, for PolicyCenter the abbreviation is pc.
uses gw.api.suite.GuidewireSuiteUtil
var x = GuidewireSuiteUtil.getProductInfo("cc")
print(x.Url)
For the earlier suite-config.xml example file, this code prints the following output.
http://localhost:8080/cc
uses gw.xsd.guidewire.soapheaders.TransactionId
uses gw.xml.ws.WsdlConfig
uses java.util.Date
uses wsi.local.gw.services.wsidbupdateservice.faults.DBAlreadyExecutedException
function callMyWebService {
service.Config.Guidewire.Authentication.Username = "su"
service.Config.Guidewire.Authentication.Password = "gw"
// Create a transaction ID that has an external system prefix and then a guaranteed unique ID.
// If you are using Guidewire messaging, you may want to use the Message.ID property in your ID.
transactionIDString = "MyExtSys1:" + getUniqueTransactionID() // Create your own unique ID.
// Set the transaction ID for the next method call and only the next method call to this service.
service.initializeExternalTransactionIdForNextUse(transactionIDString)
// Call a method on the service -- A transaction ID is set only for the next operation.
service.helloWorld()
// Call a method on the service -- A transaction ID is set only for the next operation.
service.helloWorldMethod3()
}
See also
• “Asynchronous method calls to web services” on page 95
92 chapter 4: Calling web services from Gosu
Guidewire PolicyCenter 9.0.6 Integration Guide
uses java.nio.charset.Charset
service.Config.XmlSerializationOptions.Encoding = Charset.forName("Big5")
This API sets the encoding on the outgoing request only. The SOAP server is not obligated to return the response
XML in the same character encoding.
If the web service is published from a Guidewire product, you can configure the character encoding for the response.
// Get a reference to the web service in the package namespace of the WSDL
var service = new example.gosu.wsi.myservice.SayBonjour()
For example, you might want to add additional layers of encryption, digital signatures, or other types of
authentication or security.
From the SOAP client side, the way to add advanced security layers to outgoing requests is to apply transformations
of the stream of data for the request. You can transform the data stream incrementally as you process bytes in the
stream. For example, you might implement encryption this way. Alternatively, some transformations might require
getting all the bytes in the stream before you can begin to output any transformed bytes. Digital signatures would be
an example of this approach. You may you use multiple types of transformations. Remember that the order of them
is important. For example, an encryption layer followed by a digital signature is a different output stream of bytes
than applying the digital signature and then the encryption.
Similarly, getting a response from a SOAP client request might require transformations to understand the response.
If the external system added a digital signature and then encrypted the XML response, you need to first decrypt the
response, and then validate the digital signature with your keystore.
The standard approach for implementing these additional security layers is the Java utility WSS4J, but you can use
other utilities as needed. The WSS4J utility includes support for the WSS security standard.
package gw.xml.ws
uses gw.xml.ws.annotation.WsiWebService
uses gw.xml.ws.annotation.WsiRequestTransform
uses java.io.ByteArrayInputStream
uses gw.util.StreamUtil
uses gw.xml.ws.annotation.WsiResponseTransform
uses gw.xml.ws.annotation.WsiAvailability
uses gw.xml.ws.annotation.WsiPermissions
uses java.io.InputStream
@WsiWebService
@WsiAvailability( NONE )
@WsiPermissions( {} )
@WsiRequestTransform( WsiTransformTestService._xorTransform )
@WsiResponseTransform( WsiTransformTestService._xorTransform )
class WsiTransformTestService {
// The following method declares a Gosu block that implements the transform
public static var _xorTransform( is : InputStream ) : InputStream = \ is ->{
var bytes = StreamUtil.getContent( is )
for ( b in bytes index idx ) {
bytes[ idx ] = ( b ^ 17 ) as byte // xor encryption
}
return new ByteArrayInputStream( bytes )
}
The following code connects to the web service and applies this transform on outgoing requests and the reply.
package gw.xml.ws
uses gw.testharness.TestBase
uses gw.testharness.RunLevel
uses org.xml.sax.SAXParseException
@RunLevel( NONE )
class WsiTransformTest extends TestBase {
function testTransform() {
var ws = new wsi.local.gw.xml.ws.wsitransformtestservice.WsiTransformTestService()
ws.Config.RequestTransform = WsiTransformTestService._xorTransform
ws.Config.ResponseTransform = WsiTransformTestService._xorTransform
ws.add( 3, 5 )
}
}
One‐way methods
A typical WS-I method invocation has two parts: the SOAP request, and the SOAP response. Additionally, WS-I
supports a concept called one-way methods. A one-way method is a method defined in the WSDL to provide no
SOAP response at all. The transport layer (HTTP) may send a response back to the client, however, but it contains
no SOAP response.
Gosu fully supports calling one-way methods. Your web service client code does not have to do anything special to
handle one-way methods. Gosu handles them automatically if the WSDL specifies a method this way.
Be careful not to confuse one-way methods with asynchronous methods.
This topic describes general-purpose web services, such as mapping typecodes general system tools.
PolicyCenter/build/xsd/pc_import.xsd
PolicyCenter/build/xsd/pc_entities.xsd
PolicyCenter/build/xsd/pc_typelists.xsd
Regenerate the XSD files by running the build tool with the following option.
gwb genImportAdminDataXsd
The xmlData argument contains the XML data to import. The argument cannot be null or contain an empty string.
The method returns an ImportResults object that contains information about the import operation, such as the
number of entities imported grouped by type. If an error occurred during import, the object’s isOk method returns
false. Descriptions of the errors can be retrieved by calling the object’s getErrorLog method which returns an
array of String objects.
General web services 97
Guidewire PolicyCenter 9.0.6 Integration Guide
The performance of the import operation can be improved by wrapping the XML data in CDATA tags.
<pre>
<![CDATA[
<SampleElement>Sample data</SampleElement>
]]>
</pre>
processID = maintenanceToolsAPI.startBatchProcess("memorymonitor");
The following code statement runs a batch process and passes arguments to it.
maintenanceToolsAPI.batchProcessStatusByName("memorymonitor")
maintenanceToolsAPI.batchProcessStatusByID(processID)
maintenanceToolsAPI.requestTerminationOfBatchProcessByName("memorymonitor")
maintenanceToolsAPI.requestTerminationOfBatchProcessByID(processID)
For work queues, the status methods returns the status only of the writer thread. The status methods do not check the
work queue table for remaining work items. The status of a writer reports as completed after the writer finishes
adding work items for a batch to the work queue. Meanwhile, many work items in the batch may remain
unprocessed.
For the batch process methods of the maintenance tools API, the batch processes apply only to PolicyCenter, not
additional Guidewire applications that you integrated with it.
Whenever you use the MaintenanceToolsAPI web service to run a batch process provided in the base configuration,
identify the batch process by its code as listed in the documentation. To run a custom batch process, identify the
process by the BatchProcessType typecode that you added for it. The typecode must include the APIRunnable
category to start your custom batch process with the MaintenanceToolsAPI web service.
import gw.webservice.pc.pc900.MaintenanceToolsAPI;
import gw.api.webservice.maintenanceTools.WorkQueueConfig;
The following code statement gets the work queue names for this instance of PolicyCenter.
The following code statements get the number of instances and the throttle interval for the specified work queue.
//Obtains the work queue, ActivityEsc, and assigns the object to a temporary work queue configuration
//object, wqConfig.
WorkQueueConfig wqConfig = maintenanceTools.getWorkQueueConfig("ActivityEsc");
//Obtains the number of instances and the throttle interval for wqConfig.
Integer numInstances = wqConfig.getInstances();
Long throttleInterval = wqConfig.getThrottleInterval();
The following code block sets the number of instances, the throttle interval, the batch size, and the maximum poll
interval before calling setWorkQueueConfig. Note that you must set all fields on a temporary work queue
configuration object before setting the configuration for the work queue.
//Sets all fields on the temporary work queue configuration object, wqConfig, before setting the
//configuration for the work queue.
wqConfig.setInstances(1);
wqConfig.setThrottleInterval(999);
wqConfig.setBatchSize(20);
wqConfig.setMaxPollInterval(60000);
//Sets the configuration values of the work queue, ActivityEsq, to the values established for the temporary
//work queue configuration object. This method invocation only sets the work queue configuration for the
//server that accepts the method call.
maintenanceTools.setWorkQueueConfig("ActivityEsc", wqConfig);
Worker instances that are running stop after they complete their current work item. Then, the server creates and
starts new worker instances as specified by the configuration object that you pass to the method.
The changes made using the batch process web service API are temporary. If the server starts or restarts at a later
time, the server rereads the values from work-queue.xml to define how to create and start workers.
General web services 99
Guidewire PolicyCenter 9.0.6 Integration Guide
For these APIs, the terms product and cluster apply to the current Guidewire product only as determined by the
SOAP API server requested.
<?xml version="1.0"?>
<typecodemapping>
<namespacelist>
<namespace name="ExtSys123"/>
<namespace name="ExtSysABC"/>
</namespacelist>
<typelist name="LossType">
<mapping typecode="PR" namespace="ExtSys123" alias="Prop"/>
<mapping typecode="PR" namespace="ExtSysABC" alias="CPL"/>
</typelist>
</typecodemapping>
As the example file demonstrates, each external system is assigned a unique namespace name. The name is
subsequently used to map a PolicyCenter typecode to the relevant external system code. The mapped PolicyCenter
typecode is specified in the typecode attribute, and the external system code is specified in the alias attribute.
The typecodemapping.xml file can define multiple typelist elements. The value of each name attribute must be
unique and cannot be an empty string.
A single PolicyCenter typecode can be mapped to multiple external system aliases. Conversely, a single external
alias can be mapped to multiple typecodes. To determine the appropriate mapped typecode or alias in a particular
situation, an external system can call the TypelistToolsAPI web service to retrieve an array of mapped typecodes
or aliases and select the desired item from the array. PolicyCenter configuration code can resolve the issue in a
similar manner by using the static TypecodeMapper object.
The typelist argument specifies a PolicyCenter typelist. If the typelist does not exist, the method throws an
IllegalArgumentException. The method returns an array of TypeKeyData objects that contain the typekeys
defined by the typelist. The typecode for a particular TypeKeyData object can be retrieved by calling its getCode
method.
Each argument references an attribute value assigned in the typecodemapping.xml file. The typelist argument
references a PolicyCenter typelist by specifying the value of the name attribute of the typelist element. The
namespace argument identifies the external system by specifying its unique name attribute value assigned in its
namespace element. The alias argument references the external system's code by specifying the alias attribute
value of the mapping element. None of the arguments can be null.
The methods return either a single TypeKeyData object or an array of TypeKeyData objects that are mapped to the
specified external system alias. The typecode for a particular TypeKeyData object can be retrieved by calling its
getCode method.
If getTypeKeyByAlias finds more than one typecode mapped to the specified code, it throws an
IllegalArgumentException.
Each argument references an attribute value assigned in the typecodemapping.xml file. The typelist argument
references a PolicyCenter typelist by specifying the value of the name attribute of the typelist element. The code
argument references the typelist's typecode by specifying the typecode attribute value of the mapping element. The
namespace argument identifies the external system by specifying its unique name attribute value assigned in its
namespace element. None of the arguments can be null.
The methods return either a single external system code or an array of codes that are mapped to the specified
typelist and code.
If getAliasByInternalCode finds more than one code mapped to the specified typelist/typecode, it throws an
IllegalArgumentException.
gw.api.util.TypecodeMapperUtil.getTypecodeMapper() : TypecodeMapper
The method accepts no arguments. It returns a TypecodeMapper object which implements the remaining methods
described in this section.
The typelist argument references a PolicyCenter typelist by specifying the value of the name attribute of the
typelist element defined in the typecodemapping.xml file. The specified typelist must exist in PolicyCenter or
the method throws an InvalidMappingFileException.
The method returns true if any mappings are defined for the specified typelist.
Each argument references an attribute value assigned in the typecodemapping.xml file. The typelist argument
references a PolicyCenter typelist by specifying the value of the name attribute of the typelist element. The code
argument references the typelist's typecode by specifying the typecode attribute value of the mapping element. The
namespace argument identifies the external system by specifying its unique name attribute value assigned in its
namespace element. None of the arguments can be null.
The methods return either a single external system code or an array of codes that are mapped to the specified
typelist and code. If no mapped code is found, getAliasByInternalCode returns null and
getAliasesByInternalCode returns an empty array.
If getAliasByInternalCode finds more than one code mapped to the specified typelist/typecode, it throws a
NonUniqueAliasException.
Each argument references an attribute value assigned in the typecodemapping.xml file. The typelist argument
references a PolicyCenter typelist by specifying the value of the name attribute of the typelist element. The
namespace argument identifies the external system by specifying its unique name attribute value assigned in its
namespace element. The alias argument references the external system's code by specifying the alias attribute
value of the mapping element. None of the arguments can be null.
102 chapter 5: General web services
Guidewire PolicyCenter 9.0.6 Integration Guide
The methods return either a single typecode or an array of typecodes that are mapped to the specified external
system alias. If no mapped typecode is found, getInternalCodeByAlias returns null and
getInternalCodesByAlias returns an empty array.
If getInternalCodeByAlias finds more than one typecode mapped to the specified external system code, it throws
a NonUniqueTypecodeException.
setEnableProfilerForBatchProcess(enable : boolean,
type : String,
hiResTime : boolean,
enableStackTracing : boolean,
enableQueryOptimizerTracing : boolean,
enableExtendedQueryTracing : boolean,
dbmsCounterThresholdMs : int,
diffDbmsCounters : boolean)
setEnableProfilerForWorkQueue(enable : boolean,
type : String,
hiResTime : boolean,
enableStackTracing : boolean,
enableQueryOptimizerTracing : boolean,
enableExtendedQueryTracing : boolean,
dbmsCounterThresholdMs : int,
diffDbmsCounters : boolean)
setEnableProfilerForBatchProcessAndWorkQueue(enable : boolean,
type : String,
hiResTime : boolean,
enableStackTracing : boolean,
enableQueryOptimizerTracing : boolean,
enableExtendedQueryTracing : boolean,
dbmsCounterThresholdMs : int,
diffDbmsCounters : boolean)
setEnableProfilerForMessageDestination(enable : boolean,
destinationID : int,
hiResTime : boolean,
enableStackTracing : boolean,
enableQueryOptimizerTracing : boolean,
enableExtendedQueryTracing : boolean,
dbmsCounterThresholdMs : int,
diffDbmsCounters : boolean)
The method accepts the same arguments as the setEnableProfilerForBatchProcess method, except for the
destinationID argument, which replaces the type argument. The destinationID argument specifies the unique
numeric ID of the message destination to enable or disable profiling for.
The method has no return value.
setEnableProfilerForStartablePlugin(enable : boolean,
pluginName : String,
hiResTime : boolean,
enableStackTracing : boolean,
enableQueryOptimizerTracing : boolean,
enableExtendedQueryTracing : boolean,
dbmsCounterThresholdMs : int,
diffDbmsCounters : boolean)
The method accepts the same arguments as the setEnableProfilerForBatchProcess method, except for the
pluginName argument, which replaces the type argument. The pluginName argument specifies the unique String
name of the startable plugin to enable or disable profiling for.
The method has no return value.
setEnableProfilerForWebService(enable : boolean,
serviceName : String,
operationName : String,
hiResTime : boolean,
enableStackTracing : boolean,
enableQueryOptimizerTracing : boolean,
enableExtendedQueryTracing : boolean,
dbmsCounterThresholdMs : int,
diffDbmsCounters : boolean)
The method accepts the same arguments as the setEnableProfilerForBatchProcess method, except for the
replacement of the type argument with the following arguments to specify a web service.
• serviceName - Specifies the web service name
• operationName - Specifies the web service operation
The method has no return value.
setEnableProfilerForSubsequentWebSessions(name : String,
enable : boolean,
hiResTime : boolean,
enableStackTracing : boolean,
enableQueryOptimizerTracing : boolean,
enableExtendedQueryTracing : boolean,
dbmsCounterThresholdMs : int,
diffDbmsCounters : boolean)
The method accepts the same arguments as the setEnableProfilerForBatchProcess method, except for the
replacement of the type argument with the name argument. The name argument specifies the String text to use to
identify the profiler. Any text can be used. Unlike the other methods in the ProfilerAPI web service, the name
argument precedes the enable argument.
The profiling of web sessions is intended for development environments and is not recommended for production
environments.
The method has no return value.
runlevelString = systemTools.getRunLevel().getValue();
systemTools.setRunLevel(SystemRunlevel.GW_MAINTENANCE);
Sometimes you want a more lightweight way than SOAP APIs to determine the run level of the server. During
development, you can check the run level by using your web browser.
To check the run level, call the ping URL on a PolicyCenter server using the following syntax.
http://server:port/pc/ping
http://PolicyCenter.mycompany.com:8180/pc/ping
If the server is running, the browser returns a short HTML result with a single ASCII character to indicate the run
level. If you are checking whether the server is running, any return value from the ping URL proves the server is
running. If the browser returns an HTTP or browser error, the server is not running.
To determine the current run level, examine the contents of the HTTP result for an ASCII character.
ASCII character 0. A null character result might not be returnable for some combinations of HTTP servers GW_STARTING
and clients.
Clustering tools
There are several related SystemToolsAPI web service methods for managing clusters of servers. Call these
methods from an external system to get information about the cluster and manage failure conditions.
The componentType argument references a ComponentType enumeration value. Supported values are WORK_QUEUE,
SYSTEM, BATCH_PROCESS, STARTABLE_PLUGIN, MESSAGE_DESTINATION, and MESSAGE_PREPROCESSOR.
The componentId argument specifies the component's unique String ID.
The method has no return value.
batchProcessStatusByID method. The method returns a ProcessStatus object. To check the progress of the batch
process, use the following boolean properties.
• Starting – The batch process is initializing.
• Executing – The batch process is running.
• Complete – The batch process has finished.
• Success – The batch process completed successfully.
The ProcessStatus object also provides more detailed information about the batch process. For example, the
following code checks the status of an integrity check batch process.
For staging table actions that you can request from remote systems, refer to the following table.
List templates
The following web service methods retrieve a list of templates on the server. The list can be used to sanity-check the
arguments to the web service's validation methods.
listDocumentTemplates() : String
listEmailTemplates() : String
listNoteTemplates() : String
Each method returns a human-readable string that describes the templates available on the server.
Validate templates
The following methods validate either a single or all templates. Each method processes a specific type of template.
General web services 109
Guidewire PolicyCenter 9.0.6 Integration Guide
Each method accepts a String file name that specifies the template to validate, such as ReservationRights.doc.
The email and note methods also accept an array of NameTypePair objects. Each NameTypePair object contains a
parameter name and its type. Each property is specified as a String. The two properties are used to validate the
template placeholder.
Each method returns a human-readable string that describes the operations performed, plus any errors, if they
occurred.
The following validation tests are performed.
• Checks all Gosu ContextObject and FormField expressions in the descriptor. ContextObject expressions must
be defined in terms of the available objects. FormField expressions must be defined in terms of either available
objects or ContextObjects.
• Checks that the permissionRequired attribute is valid, if specified.
• Checks that the default-security-type attribute is valid, if specified.
• Checks that the type attribute is a valid type code, if specified.
• Checks that the section attribute is a valid section type code, if specified.
Each validation method has a counterpart that accepts a locale.
importFormFields(contextObjectFileContents : String,
fieldGroupFileContents: String,
fieldFileContents : String,
descriptorFileContents : String) : TemplateImportResults
Workflow basics
You can invoke a workflow trigger remotely from an external system using the invokeTrigger method.
Any time the application detects a workflow error, the workflow sets itself to the state TC_ERROR. When this occurs,
you can remotely resume the workflow using these APIs.
Refer to the following table for workflow actions that you can request from remote systems.
PolicyCenter provides web services that enable you to accept changes to accounts and policies from external
systems.
construct(s : String)
If the constructor's useTimeZone argument is true, the constructed object inherits the time zone specified in the
Calendar object.
Conversely, a Gosu XSD-based date/time object can be converted to a java.util.Calendar object by calling the
object's toCalendar method. Calendar fields that are not included in the XSD-based object are set to default
values. Two method signatures are supported.
Account and policy web services 113
Guidewire PolicyCenter 9.0.6 Integration Guide
toCalendar() : Calendar
toCalendar(tzDefault : TimeZone) : Calendar
If the Gosu object does not specify a time zone value, calling the toCalendar method signature with no arguments
results in an IllegalStateException.
Find accounts
There are two ways to find accounts, either by account number or by complex criteria.
Use the findAccountPublicIdByAccountNumber method to find an account’s public ID given its account number.
It returns the public ID of the account, or null if there is no such account.
accountPublicID = accountAPI.findAccountPublicIdByAccountNumber("ABC-00001");
In contrast, the findAccounts method is more robust and allows you to search for multiple accounts that fit certain
criteria. For example, you could find accounts that match a certain account status or from a certain city. To use it,
create a new AccountSearchCriteria object, fill in properties that match what you want to search for, and pass it
to findAccounts.
Assign activities
You can remotely add and assign an activity for an account by using the addAndAutoAssignActivityForAccount
method. PolicyCenter generates an activity based on the activity type and the activity pattern code and then auto-
assigns the activity.
It takes a String account public ID, an ActivityType object, a String activity pattern code, a String activity
pattern code, and an array of activity properties of type ActivityField. The method has no return value.
Insert accounts
You can remotely insert an account by using the insertAccount method. The method accepts an ExternalAccount
entity, which is a parallel to the Account entity. The ExternalAccount entity contains a subset of the properties on
the internal non-SOAP Account entity due to the necessity to simplify the entity for serialization across the SOAP
protocol.
After importing the external account into PolicyCenter as an Account entity, PolicyCenter returns the resulting
String public ID of the new Account entity.
Merge accounts
You can remotely merge two accounts by using the mergeAccounts method. This task is available from this web
service but is not provided in the PolicyCenter reference implementation in the user interface. You must decide
which account is the merged account and which account to discard after the merge is complete.
The method takes two String account public IDs. The first public ID represents the source account to be copied
then discarded afterward. The second public ID represents the destination account to have the source destination
account merged with it. The method returns nothing.
See also
• To customize the operations that are performed after merging accounts, see “Account plugin details” on page
151.
Transfer policies
You can remotely transfer policies from one account to another by using the transferPolicies method. Provide an
array of String policy public IDs, the public ID of the source account, and the public ID of the destination account.
See also
• To customize the operations that are performed after transferring accounts, see “Account plugin details” on page
151.
not the AccountContact entity. AccountContactInfo simply encapsulates an Address entity in its
PrimaryAddress property. Populate an Address entity with the new information and set the PrimaryAddress
property on the AccountContactInfo entity.
PolicyCenter looks at the specified account and finds the contact with the provided display name. PolicyCenter then
updates the contact with the information in the AccountContactInfo.
There are other types of cancellations that the billing system or other integration systems initiate. For example,
cancellation for non-payment. If the billing system detects overdue invoices, the billing system starts a delinquency
process and tells PolicyCenter to cancel the policy.
There are two ways the billing system can tell PolicyCenter to cancel a policy.
• Cancel the policy as of a certain date – PolicyCenter sets the policy to pending cancellation within PolicyCenter
and cancels automatically on the given date unless the application receives a rescind command before that date.
• Cancel the policy as soon as possible – This is similar to the previous approach described but PolicyCenter uses
internal notification lead time logic to determine the actual cancellation date.
PolicyCenter supports both approaches based on the cancellation date you pass to the API.
See also
• For more information about circumstances in which PolicyCenter might trigger cancellation or reinstatement,
refer to “Policy period management” on page 502.
Begin a cancellation
An external system can begin a cancellation in PolicyCenter with the beginCancellation method on
CancellationAPI.
To begin cancellation, you must specify a reason in a ReasonCode enumeration to indicate fraud, eligibility issues,
and so on. Instead of passing the reason code directly, a CancellationSetup entity encapsulates this enumeration.
The method returns the public ID of the cancellation job.
The parameters are described below.
• Policy number, as a String
• Cancellation date, as a Calendar object
• Recalculate effective date (recalculateEffDate), as a boolean
• Cancellation source typecode, carrier (insurer initiated cancel) or insured (the insured initiated cancel)
• Reason code typecode, as a ReasonCode value
• Refund calculation method, as a CalculationMethod
• Description (notes) associated with this cancellation, as a String
• Transaction ID to associate with this change
If you set recalculateEffDate to false, starts a Cancellation job effective on the cancellation date. or the given
policy in PolicyCenter (this date will also be the effective date of the new cancellation policy period). In this case,
the caller must check for any legal requirements for the cancellation date. If recalculateEffDate is set to true,
PolicyCenter calculates the earliest date for the cancellation to meet all legal requirements. PolicyCenter uses that
date if it is after the cancellation date. In this case, the caller can set the cancellationDate to today to get the
policy period cancelled as soon as possible.
The following Java example cancels a policy.
Rescind a cancellation
Rescind a cancellation with the rescindCancellation method.
The method has two versions.
• One version rescinds a policy cancellation with a reason as a ReasonCode typecode and a cancellation source as a
CancellationSource typecode. The reason typecode indicates a payment-related reinstatement with the value
Account and policy web services 117
Guidewire PolicyCenter 9.0.6 Integration Guide
payment or another reason with the value other. The cancellation source typecode indicates that the insurer
initiated the cancellation with the value carrier or the insured initiated the cancellation with the value insured.
For example, the following sample code rescinds a cancellation with a reason code.
• The other version rescinds an in-progress policy cancellation with the job number of a cancellation. For example,
the following sample code rescinds a cancellation with a job number only.
void rescindCancellation("ABC:123")
Find a cancellation
In some cases, an external system wants to rescind a cancellation but does not have the job number for the
cancellation. In these cases, use the findCancellations method on the CancellationAPI web service to get the
job number. The method returns a list of job numbers for matching cancellations. You can use these results to decide
which cancellation you want to rescind. Next, call the separate rescindCancellation method and pass it the job
number of the cancellation job to rescind.
The findCancellations method takes the following arguments in the following order.
• Policy number, as a String
• Cancellation date, as a java.util.Calendar object. PolicyCenter finds cancellations effective on that date or
after that date.
• Cancellation source, as a CancellationSource typecode
◦ carrier – Cancellation initiated by insurer
◦ insured - Cancellation initiated by insured
• Reason code, as a ReasonCode typecode
◦ nonpayment – Payment not received
◦ fraud – Fraud
◦ flatrewrite – Policy rewritten or replaced (flat cancel)
◦ midtermrewrite – Policy rewritten (mid-term)
• Calculation method, as a CalculationMethod typecode
◦ flat – Flat
◦ prorata – Pro rata
◦ shortrate – Short rate
The following example code demonstrates how to call this method from Java.
Reinstate a policy
Use the ReinstatementAPI web service to start a reinstatement job for a policy that is canceled and that you want to
put it back in-force. The reinstatement effective date is always the cancellation date. To create a gap in coverage, a
user must start a policy rewrite job manually through the PolicyCenter interface.
118 chapter 6: Account and policy web services
Guidewire PolicyCenter 9.0.6 Integration Guide
The ReinstatementAPI web service has a single method called beginReinstatement. The method accepts the
following arguments.
• Policy number as a String
• Reinstatement code as a ReinstateCode typecode
The method returns a job number for the new reinstatement job.
The following example code demonstrates how to call this from Java.
Start a submission
The startDraftSubmission method create a submission and leaves it in a draft state.
gw.webservice.pc.pcVERSION.community.ProducerAPI
Instead, test changes on different instances of the development server. Ensure your product model changes are
correct before deploying to the production server.
To maintain business data integrity, PolicyCenter forbids some types of changes to product model entity properties
on production servers. Some product model changes are impossible to undo after you deploy the changes to a
production server. For example, a coverage term with the value 100 cannot change to the value 200 on a production
server. That would fundamentally change the meaning of any policies that used that coverage term. This is a
difference between working with a development server which has no customer data and a production server where
customer data is bound by legal and customer service implications.
The development server must have an identical PolicyCenter configuration as the production server, except for the
following configuration settings.
• On the production server, set the server environment property env to prod (production).
• On the development server, set the server environment property env to a value other than prod.
Fully test product model changes on a development server. PolicyCenter protects the business and legal integrity of
customer data in a special way for production servers. Deploying unacceptable property changes to existing product
model entities prevents PolicyCenter from starting in production environment.
If you call the ProductModelAPI web service on a server whose system environment variable env is set to the value
prod, the web service throws an exception.
Use this API in the following cases.
• If you need to revert the product model to the product model XML files stored on the server instead of the data
persisted in the database.
• If you change a development server’s local file resources in some other way during development due to source
control changes or hand-editing of files.
Use this API if you change a development server’s local file resources in some other way during development due to
source control changes or hand-editing of files.
Do not use this API if the file did not change since server startup.
The activityfields argument contains an Activity object, which is not the Guidewire entity. Instead, it is a XML
type defined using the Guidewire XML (GX) modeler.
Set the important properties for a new activity, such as the Subject and the Description properties. PolicyCenter
copies over non-null fields form the activityfields argument to the new activity.
The addActivityFromPatternAndAutoAssign method performs the following operations.
1. Try to generate an activity from the specified activity pattern.
2. Initialize the activity with the following fields from the activity pattern: Pattern, Type, Subject,
Description, Mandatory, Priority, Recurring, and Command.
3. Calculate the target date using the following properties from the pattern: TargetStartPoint, TargetDays,
TargetHours, and TargetIncludeDays.
4. Calculate the escalation date using the following properties from the pattern EscalationStartPt,
EscalationDays, EscalationHours, and EscalationInclDays. If the activity does not use those properties,
PolicyCenter does not set the target and/or escalation date. If the target date after the escalation date, then
PolicyCenter sets the target date to the escalation date.
5. PolicyCenter sets the activity policy ID to the specified policy ID. The previous user ID for the activity (the
previousUserId property) is set to the current user.
6. PolicyCenter assigns the newly created activity to a group and/or user using the Assignment Engine.
This step is the auto-assignment step.
7. PolicyCenter saves the activity in the database.
8. The method returns the ID of the newly created activity.
The method performs the same operations as the related addActivityFromPatternAndAutoAssign method, except
that it assigns the activity to the specified group and user.
The method performs the same operations as the related addActivityFromPatternAndAutoAssign method, except
that it assigns the activity to the specified queue.
The includeEBUR parameter interacts in a special way with the status of the policy as a reporting policy.
• If includeEBUR is true and the policy is not a reporting policy, the calcEarnedPremiumByPolicyNumber
method returns an error.
• If the policy is a reporting policy but final audit is complete, PolicyCenter treats the includeEBUR parameter as if
it were false even if you passed true.
gw.webservice.pc.pcVERSION.gxmodel.policyperiodmodel
The method returns an object of type QuoteResponse, which is a Gosu class that contains the following properties.
• JobNumber – Job number of the new job
• Errors – Any errors as an array of String objects
See also
• Application Guide
startRenewals(policyNumbers : String[])
The policyNumbers argument is an array of policy numbers that reference existing policies in PolicyCenter. If a
referenced policy does not exist in PolicyCenter, a BadIdentifierException is thrown and any subsequent policies
in the array are not processed.
The method has no return value.
The method starts a renewal job for each referenced policy. The entries in policyNumbers are processed in
sequence. When a successful renewal is created, it is committed to the database. No gap in coverage exists between
the original policy period and its renewal.
startConversionRenewal(accountNumber : String,
productCode : String,
producerCodeId : String,
policyNumber : String,
policyPeriodData : String,
changesToApply : String,
parseOptions : String,
basedOnEffectiveDate : String,
basedOnExpirationDate : String) : String
• policyNumber - The unique ID number to assign to the imported policy. If the argument is null or references an
existing PolicyCenter policy, the method generates a new and unique policy ID number.
• policyPeriodData - The policy period data to import. The String contents are parsed as XML that conforms to
the PolicyCenter PolicyPeriodModel GX model. Load the GX model in Studio to view its structure.
• changesToApply - Not used in the base configuration. Custom implementations can use the argument to
reference settings in the renewal policy period that differ from the legacy imported period.
• parseOptions - Not used in the base configuration. Custom implementations can use the argument for their own
purposes.
• basedOnEffectiveDate - The effective date of the legacy imported policy period.
• basedOnExpirationDate - The expiration date of the legacy imported policy period. This date is also used as the
effective date for the new imported renewal policy period. There is no gap in coverage between the legacy
imported policy period and the renewal period.
If the accountNumber, productCode, or producerCodeId do not exist in PolicyCenter, the policy is not imported.
The imported policyPeriodData does not support attaching Note or Document objects to the renewal policy period.
Note and Document objects can be attached to the renewal policy period after it has completed the renewal process.
The basedOnEffectiveDate value is passed to the Effective Time plugin's getConversionRenewalEffectiveTime
method for processing.
The basedOnExpirationDate value is passed to the Effective Time plugin's
getConversionRenewalExpirationTime method for processing.
The method creates a new policy on the specified account. Also, a new policy period is created and associated with
the new policy. Finally, a renewal job is started for the new policy period. The renewal is in draft mode and is not
bound. If the operation fails, the method throws a DataConversionException.
The method returns the renewal job's ID number as a String.
See also
• “Billing implications of renewals or rewrites” on page 489
notifyPaymentReceivedForRenewalOffer(offerID : String,
selectedPaymentPlanCode : String,
paymentAmount : MonetaryAmount,
transactionId : String) : String
See also
• “Archiving integration” on page 573
suspension of archiving. All three methods take a single argument, which is the policy number of the policy in
question. The methods implement the following operations.
• Suspend archiving – From an external system, call the ArchiveAPI method setDoNotArchive.
• Resume archiving – From an external system, call the ArchiveAPI method unsetDoNotArchive. If there are
terms that are already archived, resuming archiving does not restore any already-archived terms.
• Check a policy for suspended from archiving – From an external system, call the ArchiveAPI method
isDoNotArchive. The method returns true if the policy is currently suspended from archiving, false otherwise.
The return result does not indicate whether the policy has any archived terms, only whether the policy is
currently suspended from consideration of archiving.
See also
• Application Guide
Plugins
Guidewire PolicyCenter 9.0.6 Integration Guide
chapter 7
Overview of plugins
PolicyCenter plugins are software modules that PolicyCenter calls to perform an action or calculate a result.
PolicyCenter defines a set of plugin interfaces. You can write your own implementations of plugins in Gosu or Java.
The plugin itself might do most of the work or it might consult with other external systems. Many plugins typically
run while users wait for responses from the application user interface. Guidewire strongly recommends that you
carefully consider response time, including network response time, as you write your plugin implementations.
Features of each plugin implementation type Gosu plugin Java plugin OSGi plugin
(no OSGi) (Java with OSGi)
Choice of development environment
You can use PolicyCenter Studio to write and debug code. •
You can use the included application IntelliJ IDEA with OSGi editor to write code. • •
Usability
Native access to Gosu blocks, collection enhancements, Gosu classes. •
Entity and typecode APIs are the same as for Rules code and PCF code. •
Requires regenerating Java API libraries after data model changes. • •
Third‐party Java libraries
Your plugin code can use third‐party Java libraries. • • •
You can embed third‐party Java libraries within a OSGi bundle to reduce conflicts •
with other plugin code or PolicyCenter itself.
Dependencies on specific third‐party packages and classes are explicit in mani‐ •
fest files and validated at startup time.
Implement all public methods of the interface. PolicyCenter Studio and most professional Java IDEs can detect
when required methods are missing from a class. Studio provides a tool that can create stub versions of
unimplemented methods.
The @PluginParameter annotation
Plugin classes can describe their parameters with the @PluginParameter annotation. The annotation can specify
various properties of the parameter, such as its type and whether it is required.
@PluginParameter Description
The following Gosu code segment demonstrates how to use the @PluginParameter annotation.
For plugins written in Java, the Java API libraries must be regenerated whenever changes are performed on the data
model configuration.
Plugin parameters
In the Plugins Registry editor, you can add a list of parameters as name-value pairs. The plugin implementation can
use these values. For example, you might pass a server name, a port number, or other configuration information to
your plugin implementation code using a parameter. Using a plugin parameter in many cases is an alternative to
using hard-coded values in implementation code.
To use plugin parameters, a plugin implementation must implement the InitializablePlugin interface in addition
to the main plugin interface. If PolicyCenter detects that your plugin implementation implements
136 chapter 7: Overview of plugins
Guidewire PolicyCenter 9.0.6 Integration Guide
InitializablePlugin, PolicyCenter calls your plugin’s setParameters method. That method must have exactly
one argument, which is a java.util.Map object. In the map, the parameters names are keys in the map.
By default, all plugin parameters have the same name-value pairs for all values of the servers and environment
system variables. However, the Plugins registry allows optional configuration by server, by environment, or both.
For example, you could set a server name differently depending on whether you are running a development or
production configuration.
See also
• “Getting plugin parameters from the plugins registry editor” on page 139
Deploying Java files, including Java code called from Gosu plugins
To deploy any Java files or third-party Java libraries varies based on your plugin type, perform the following
operations.
• If your Gosu plugin implements the plugin interface but accesses third-party Java classes or libraries, you must
put these files in the right places in the configuration environment. It is important to note that the plugin directory
setting discussed in that section has the value Gosu for code called from Gosu.
• For Java plugins that do not use OSGi, first ensure you define a plugin directory.
• For Java plugin classes deployed as OSGi bundles, deployment of your plugin files and third party libraries is
very different from deploying non-OSGi Java code. PolicyCenter supports OSGi bundles only to implement a
PolicyCenter plugin interface and any of your related third-party libraries. It is unsupported to install OSGi
bundles for any other purpose.
See also
• “Deploying non-OSGi Java classes and JAR files” on page 661
• “Using IntelliJ IDEA with OSGi editor to deploy an OSGi plugin” on page 662
uses gw.api.util.DisplayableException
uses java.util.Map;
uses java.plugin;
// Note the empty constructor. If you provide an empty constructor, the application calls it
// as the plugin instantiates, which occurs before the application calls setParameters().
construct() {
}
trigger = CurrentUserUtil.getCurrentUser().getUser();
See also
See also
• For an implementation of a messaging plugin that uses parameters, see “Example Gosu plugin” on page 138.
Getting the local file path of the root and temp directories
For Gosu and Java plugins, the names of the plugin’s root and temporary directory paths can be retrieved by
accessing built-in properties from the Map. These properties are not available from OSGi plugins.
The root directory name is stored in the static variable InitializablePlugin.ROOT_DIR.
The temporary directory name is stored in the static variable InitializablePlugin.TEMP_DIR.
try{
plugin.retrieveContact("abc:123")
}catch(e){
e.printStackTrace()
throw new DisplayableException(e.Message)
}
Alternatively, you can request a plugin by the plugin name defined in the Plugins registry. This syntax is used when
there is more than one plugin implementation of the interface. For example, multiple implementations of an
interface are common in messaging plugins. In such cases, use the get method signature that takes a String for the
plugin name.
extension property on a Policy or other relevant entity (including custom entities) to store state-specific data for the
plugin. Be aware that storing data in an entity shares the data across servers in a PolicyCenter cluster. Additionally,
even standard instance variables (not just static variables) can be dangerous because there is only one instance of the
plugin.
If you are experienced with multi-threaded programming and you are certain that static variables are necessary, you
must ensure that you synchronize access to static variables. Synchronization refers to a feature of Java that locks
access between threads to shared resources, such as static variables.
// Define a synchronized method. Only one thread can run a syncced method at one time for this object
public synchronized void put1(int value) {
contents = value;
// do some other action here perhaps...
}
// Define a synchronized method. Only one thread can run a syncced method at one time for this object
public synchronized void put2(int value) {
contents = value;
// do some other action here perhaps...
}
}
Synchronization protects invocations of all synchronized methods on the object; it is not possible for invocations of
two different synchronized methods on the same object to interleave. For the earlier example, the Java virtual
machine does all of the following.
• Prevents two threads simultaneously running put1 at the same time
• Prevents put1 from running while put2 is still running
• Prevents put2 from running while put1 is still running.
This approach protects integrity of access to the shared data. However, you must still ensure that if multiple threads
or user sessions use the plugin, your code does something appropriate with this shared data. Always test your
business logic under multi-user and multi-thread situations.
PolicyCenter calls the plugin method initialization method setParameters exactly once, hence only by one thread,
so that method is automatically safe. The setParameters method is a special method that PolicyCenter calls during
plugin initialization. This method takes a Map with initialization parameters that you specify in the Plugins registry
in Studio.
On a related note, Java class constructors cannot be synchronized; using the Java keyword synchronized with a
constructor generates a syntax error. Synchronizing constructors does not make sense because only the thread that
creates an object has access to during the time Java is constructing it.
This finer granularity of locking reduces the frequency that one thread is waiting for another to complete some
action. Depending on the type of code and real-world use cases, this finer granularity could improve performance
greatly over using synchronized methods. This is particularly the case if there are many threads. However, you
might be able to refactor your code to convert blocks of synchronized statements into separate synchronized
methods.
Both approaches protects integrity of access to the shared data. However, you must plan to handle multiple threads
or user sessions to use your plugin, and do safely access any shared data. Also, test your business logic under
realistic heavy loads for multi-user and multi-thread situations.
The following code segment provides an example of creating a singleton using a class static variable.
private MySingleton() {
// construct object . . .
}
getEnv
Get runtime values for the environment for this cluster member.
getServerId
Get the runtime value for the server ID for this cluster member.
getServerRoles
Get the set of server roles for this cluster member.
Overview of plugins 143
Guidewire PolicyCenter 9.0.6 Integration Guide
To query general system properties, use the getProperty static method of java.lang.System and pass a property
name. For example:
java.lang.System.getProperty("gw.pc.env");
If this is the first time any code has requested a number in this sequence, the value is 10. If other code calls this
method again, the return value is 11, 12, and so on, depending on the number of times code has requested numbers
for this sequence key.
You can disable the sequence utility class by setting the config.xml parameter DisableSequenceUtil. Use this to
ensure that any sequences in your code use some alternative mechanism for sequenced identifiers.
DBAuthenticationPlugin Provides the ability to store the database username and password in a way other
than plain text in the config.xml file. For example, retrieve it from an external
system, decrypt the password, or read a file from the file system. The resulting
username and password substitutes into the database configuration for each in‐
stance of that ${username} or ${password} in the database parameters.
WebservicesAuthenticationPlugin For WS‐I web services only, configures custom authentication logic This plugin in‐
terface is documented with other WS‐I information. See “Web services authenti‐
cation plugin” on page 61.
Document content and metadata plugins
IDocumentContentSource Provides access to a remote document repository for storage and retrieval opera‐
tions.
The example IDocumentContentSource plugin provided in the base configuration
must be linked to a commercial document management system before being
used in a production environment.
IDocumentMetadataSource Stores metadata associated with a document, typically in a remote document
management system.
The example IDocumentMetadataSource plugin provided in the base configura‐
tion stores metadata locally and is not intended to be used in a production envi‐
ronment. For maximum data integrity and feature set, implement the plugin and
link it to a commercial document management system.
Document production plugins
IActivityEscalationPlugin Overrides the behavior of activity escalation instead of simply calling rule sets.
See “Exception and escalation plugins” on page 260.
IAddressAutocompletePlugin Configures how address automatic completion and fill‐in operate. See “Automat‐
ic address completion and fill‐in plugin” on page 264.
IStartablePlugin Creates new plugins that immediately instantiate and run on server startup. See
“Overview of startable plugins” on page 269.
You can register multiple implementation for this interface.
ITestingClock Used for testing complex behavior over a long span of time, such as multiple bill‐
ing cycles or timeouts that are multiple days or weeks later. This plugin is for de‐
velopment (non‐production) use only. It programmatically changes the system
time to accelerate passing of time in PolicyCenter.
See “Testing clock plugin (for non‐production servers only)” on page 266.
IUserExceptionPlugin Overrides the behavior of user exceptions instead of simply calling rule sets. See
“Exception and escalation plugins” on page 260.
IWorkItemPriorityPlugin Calculates a the processing priority of a work item. See “Work item priority plu‐
gin” on page 260.
ManagementPlugin The external management interface for PolicyCenter, which enables you to imple‐
ment management systems, such as JMX and SNMP. See “Management integra‐
tion” on page 253.
Plugins are software modules that PolicyCenter calls to perform an action or calculate a result. This topic details
plugins related mainly to PolicyCenter accounts, policies, and policy-related jobs.
See also
Is account editable?
Implement the isEditable method in this plugin to indicate whether an account is editable. It takes an Account
object and returns a boolean.
The default behavior is that an account is editable, but you can customize this behavior. For example, if
PolicyCenter is not the system of record for the account, you might choose to always make the account non-editable.
Transferring policies from one account to another is not enabled in the built-in PolicyCenter user interface, but you
can trigger it using the AccountAPI web service method transferPolicies.
See also
After a job starts, PolicyCenter calls this plugin to set the default effective and expiration times on the job’s
associated PolicyPeriod entity. The return value from each of this interface’s methods is a Date object with its time
component (HH:mm:ss) set to the desired time. The day component of the Date is ignored. As a convenience, you
can return null to set the time component to midnight.
The plugin is called at varying points during job setup, according to the type of job. The main reason for this
difference is to allow you to customize the user interface to allow effective/expiration time settings to be manually
overridden. The following table compares the types of jobs, at what time the application calls the plugin, and why.
Each method is responsible for determining either an effective time or expiration time for a date given the date and
the job type. The methods for determining expiration time also take an effectiveDateTime parameter, for cases in
which the expiration time depends on the period’s PeriodStart. Each method takes a PolicyPeriod entity
parameter. Use this parameter to access other information, such as state, line of business, or detecting other
contractual periods on this policy. Finally, each method has a strongly-typed job parameter, which can be used to
access information specific to the associated job type.
The following table lists the required methods and their purpose. Each method returns a java.util.Date object.
Method Description
getCancellationEffectiveTime Gets effective time for a cancellation job.
getConversionRenewalEffectiveTime Gets a renewal policy period's effective date for an imported legacy policy.
getConversionRenewalExpirationTime Gets a renewal policy period's expiration date for an imported legacy policy.
Includes an argument for the renewal policy period's effective date, as returned by
getConversionRenewalEffectiveDate.
Method Description
getRewriteNewAccountEffectiveTime Gets a policy period's effective date for a policy that was rewritten to a new
account.
getRewriteNewAccountExpirationTime Gets a policy period's expiration date for a policy that was rewritten to a new
account. Includes an argument for the policy period's effective date, as returned by
getRewriteNewAccountEffectiveTime.
PolicyCenter includes a built-in implementation of this interface with default behavior. The following table lists
effective times for a new job and the key values on the PolicyPeriod entity for that job after PolicyCenter calls this
plugin. The shaded cells are the effective times set explicitly by this plugin and the other cells indicate unchanged
values or dependence on other properties.
See also
• Product Model Guide
See also
• Configuration Guide
Location plugin
You can customize how PolicyCenter treats account locations and policy locations using the
AccountLocationPlugin location plugin. The base configuration of the plugin is implemented in the Gosu
AccountLocationPluginImpl class.
The basic tasks you can customize are described below.
• Customize how two location records are compared to see if they represent the same location or two different
locations.
• Customize how to copy your data model extension properties during cloning of a location entity.
If you want to add custom code after creating a primary location or before deleting a location, modify each policy
line’s methods called onPrimaryLocationCreation and preLocationDelete. Similarly, to define whether a
location is safe to delete, modify each policy line’s canSafelyDeleteLocation method.
Compare locations
Your areAccountLocationsEquivalent method must return true if two AccountLocation entities passed as
parameters are effectively equal.
The behavior in the built-in implementation returns true if and only if the following properties match:
AddressLine1, AddressLine2, AddressLine3, City, State, and PostalCode.
If you have data model extension properties on your locations that are important in the comparison, customize this
logic as needed.
It is critical that you not make any changes to the related PolicyPeriod entities, Account entities, or any other
entity within this method. PolicyCenter calls this method while binding a PolicyPeriod entity. If you modify any
entity other than the new location contact, the policy could become out of sync and create serious problems later on.
Only copy your data model extensions from the old account contact to the new one and do nothing else in this
method. In particular, this method must not make changes to a related PolicyPeriod, Account, or other entity or
else serious problems can occur.
The policyNumber argument specifies the relevant policy. The periodAsOfDate argument specifies an effective
date used to identify the desired policy period.
The method returns a LossFinancials object that contains financial information for the policy period in effect at
the specified periodAsOfDate.
The plugin method is invoked whenever PolicyCenter calls a PolicyPeriod entity's getLossFinancials method to
retrieve the period's financial information.
U.S., the information in this report usually comes from the Department of Motor Vehicles (DMV) for each
jurisdiction. The information in the report can vary by jurisdiction. In the U.S., most service providers provide MVR
data for all jurisdictions, so you need to integrate only with a single service provider.
See Also
• Application Guide
Method Description
orderMVR Sends an array of orders to the MVR service provider to request reports for specific drivers
getMVROrderResponse Sends an array of orders to the MVR service provider asking which reports are ready
getMVRDetails Sends an array of orders to the MVR service to obtain reports that are ready
Each methods accept an array of IMVRSubject instances as its sole input parameter.
Notification plugin
You can customize notification dates for a variety of types of notifications. Implement the INotificationPlugin
plugin or modify the built-in implementation of this plugin. This plugin is responsible for determining the minimum
lead time and maximum lead time for different types of notifications. The law frequently specifies these values, so
define and calculate these numbers carefully.
For the methods in this plugin, the effective date is a method parameter. It specifies the date at which the action
occurs. For example, suppose the lead time is 10 days if the effective date is prior to June 5, and 15 days if the
effective date is June 5 or later. The plugin must return the value 10 for effective dates prior to June 5 and 15 for
effective dates on or after June 5. This effective date argument is never null.
Another parameter is the line to jurisdictions mapping, using generics syntax this is Map<PolicyLinePattern,
State[]>. This maps from a line of business to an array of jurisdictions. For example, imagine a commercial
package policy with two lines: general liability and commercial property. The general liability line has only one
jurisdiction (California) and the commercial property line has two jurisdictions (California and Arizona). In this
case, the passed map contains two mappings.
• One mapping from general liability to an array containing the single value of California
• One mapping from commercial property to an array containing the values California and Arizona
Large commercial policies likely have much large mappings that could contain dozens of jurisdictions. This method
parameter is never null and never empty. None of the mappings contain empty arrays of jurisdictions.
Refer to the built-in implementation of this plugin for a general pattern to use. Also, the built-in implementation of
this plugin (gw.plugin.notification.impl.NotificationPlugin) has some utility functions that you can use to
simplify your code. Specifically, look at the code for the method forAllLinesAndJurisdictions.
The built-in implementation of this plugin calculates the results based on looking up the input values in the system
table NotificationConfig (controlled by the file notificationconfigs.xml).
If you write your own version of this plugin, you can use the notification system table or use completely different
logic to calculate the lead time dates.
Notice that one of the parameters is a java.util.Map that maps a policy line pattern to an array of states. Using
Gosu generics syntax, this is Map<PolicyLinePattern, State[]>. You must iterate across all the policy line
patterns and the matching list of states and calculate the minimum lead time for all combinations of line of business
and jurisdiction. Use the actionType typecode and effective date as appropriate. Your plugin method must return a
value that represents the minimum lead time as a number of number of days.
The action type is an NotificationActionType typecode to indicate the type of notification for which PolicyCenter
requests a date. A NotificationActionType includes typecodes such as those listed below.
• fraudcancel – Notification requirements in days for cancellation due to fraud
• rateincrease – Notification requirements in days for rate increases
160 chapter 8: Account and policy plugins
Guidewire PolicyCenter 9.0.6 Integration Guide
The list of typecodes in this list is extensive. Refer to the typelist in Studio or the “Data Dictionary” for the complete
list.
As you can see, it takes a notification category (NotificationCategory) instead of an action type.
The method uses the following notification category values in the built-in implementation.
• cancel – Cancellation notification configurations
• nonrenew – Non-renewal notification configurations
• renewal – Renewal notification configurations
The plugin must return the number of days lead time that represents the minimum value for the lead time column.
This must be the minimum value for all combinations of line of business and jurisdiction for the category and
effective date.
/*
* The URL to the deployed PolicyCenter application
The ScriptParameters.xml file contains the definition of the PolicyCenterURL script parameter.
The following table lists the configuration properties and their purpose.
Property Description
PaymentGatewayConnectionTimeoutInSeconds The length of time to wait for a response from the payment gateway, in sec‐
onds.
PaymentGatewayGetURL The URL for HTTP GET commands on the payment gateway. PolicyCenter re‐
directs the user to this address to take payment with a new instrument
when the RedirectToPaymentGateway property has a value of true.
PaymentGatewayPartner The payment gateway partner.
PaymentGatewayPassword The password to access the payment gateway.
PaymentGatewayPostConnectionPORT The connection port for HTTP POST commands on the payment gateway, for
example, 443.
PaymentGatewayPostURL The URL for HTTP POST commands on the payment gateway.
PaymentGatewayTransactionType The transaction type of the payment gateway command, as a
PaymentTransactionType typecode. PolicyCenter supports only the Sale
transaction type.
PaymentGatewayUser The user to access the payment gateway.
PaymentGatewayVendor The payment gateway vendor, also known as the merchant.
PolicyCenterURL The URL that the payment gateway uses to return information to
PolicyCenter, such as http://mygwpcserver:8180/pc.
RedirectToPaymentGateway Whether to redirect to the payment gateway for a payment that uses a new
payment instrument. If this property is false, PolicyCenter informs the user
that collection of electronic payment is not available.
See also
• “Implementing the payment gateway configuration plugin” on page 521
• Configuration Guide
Method Description
getCardDetails Gets a representation of the credit card as a payment instrument.
inquiryPaymentGatewayTransaction Returns a payment gateway response object that contains information
about the status of a transaction.
isApprovedTransaction Returns a boolean value, which has a value of true if the specified
transaction succeeded and false otherwise. This method uses the re‐
sponse object that inquiryPaymentGatewayTransaction returns to get
this information.
isVoidedTransaction Returns a boolean value, which has a value of true if the specified
transaction has been voided and false otherwise. This method uses
the response object that inquiryPaymentGatewayTransaction returns
to get this information.
mapSilentPostRequestToPaymentGatewayResponse Returns a payment gateway response object that maps the parameters
from an incoming HTTP servlet request to payment gateway response
properties. The servlet handles closure of the browser when the user is
accessing the payment gateway.
redirectToPaymentGateway Uses exit points to redirect from PolicyCenter to the supported pay‐
ment gateways.
refundFullAmountForTransaction Returns a payment gateway response object that contains information
about an attempt to refund a credit card transaction. PolicyCenter can
perform this action only before binding a job.
requestSecureToken Returns a payment gateway response object that contains a secure to‐
ken for communication with the payment gateway as part of the pay‐
ment gateway response. Implement code for each payment gateway
that you need to support.
submitAccountVerification Returns a payment gateway response object that contains information
about the status of a new credit card verification. If the payment gate‐
way does not require this verification, create a successful response
without calling the gateway.
takePaymentUsingPaymentInstrument Returns a payment gateway response object that contains information
about an attempt to use a payment instrument to make a payment.
See also
Before returning from this method, your method must add all relevant underwriting issues (UWIssue objects) on the
period. Additionally, the method must remove all orphaned underwriting issues.
One of the parameters is an underwriting issue checking set typecode defined in the UWIssueCheckingSet typelist.
The typecode describes a point at which PolicyCenter can evaluate a policy and generate an underwriting issue.
Each typecode contains a Priority property that indicates the order within the typelist. High priority checking set
are evaluated first.
Use the typecode value to raise new issues appropriate for the policy. Next, remove any orphaned issues.
If you choose to modify this plugin, Guidewire recommends that your implementation use the PolicyEvalContext
class to create and remove orphaned issues because these are complex and error-prone tasks. To add an issue, use the
addIssue method on the PolicyEvalContext object.
The addIssue method finds an existing UWIssue with this type and key or, if no such issue exists, creates a new
issue. If this method returns a pre-existing issue, this method marks it as touched by setting the HumanTouched
property to true. Because pre-existing issues are marked touched, the removeOrphanedIssues method (see later in
this topic) does not remove them.
For example, you can create a new issue with the following code.
Just as in the built-in implementation, you can use the PolicyEvalContext object to remove old issues using the
PolicyEvalContext.removeOrphanedIssues() method. That method removes or marks as inactive all issues for
which both of the following conditions are true.
• The issue existed at the time PolicyCenter created the context object.
• No previous call to the addIssue method on PolicyEvalContext affected this issue.
The method removes any issues that are open or marked no longer applicable. In contrast, for issues that are
approved or declined, this method marks them as inactive.
See also
• Configuration Guide
IPolicyHoldJobEvalPlugin exposes the methods that this batch process uses to find jobs that need to be
reevaluated and how to evaluate it. This plugin interface has two methods.
To find jobs that need to be evaluated against the policy holds blocking them, implement the following method.
In the base configuration, this plugin is implemented by PolicyHoldJobEvalPlugin and finds jobs that have any of
the following qualities.
• Open jobs
• Jobs with policy periods with a active blocking policy hold
• Jobs not evaluated since the last time the policy hold changed
To evaluate a job against a policy hold, implement the following method.
In the built-in plugin implementation, the evaluate method checks if the policy hold has been deleted or the hold
changed to cause the job to no longer match. If so, the method creates an activity and assigns to the producer.
The policyPeriod argument references the PolicyPeriod entity to generate a policy number for.
The method returns the generated policy number as a String.
The method is called as part of a Submission job when creating the first period of a policy and also when rewriting
or renewing a policy. If the user attempts to rewrite a policy, the PolicyCenter user interface provides a choice
between reusing the current policy number or generating a new one. Depending on the user's selection, the value of
the Rewrite.isChangePolicyNumber is set appropriately. If set to true, PolicyCenter calls the plugin to generate a
new number.
The base configuration implements the plugin in the PolicyNumGenPlugin class. This implementation is for
demonstration purposes and must be configured prior to being placed in a production environment. Its single public
method always generates a new and random policy number if the policyPeriod argument's Status field is set to
the typecode value of PolicyPeriodStatus.TC_LEGACYCONVERSION. Otherwise, the Job field of the policyPeriod
determines whether to generate a new policy number. If the Job is of type Submission, Rewrite, or
RewriteNewAccount, a new and random policy number is generated. For all other types of Job, such as Renewal,
the policyPeriod object's PolicyNumber field value is returned.
If you are implementing policy number generator code for the first time, you must configure the policy number field
validator so that it matches the format of your policy number. After you first implement a policy number generator
or later change the policy number format, coordinate changes to the field validators or user entry of policy numbers
fails.
If you need to examine the payment plan summary, the PaymentPlanSummary object has the following properties.
• BillingId
• Name
• PaymentCode
• Installment
• Total
• Notes
• PolicyPeriod – Foreign key reference to the policy period where the plan summary resides
To modify the plugin behavior for a particular line of business, put line-specific functionality in the
PolicyLineMethods implementation class. These classes have names with the LOB prefix with the pattern
LOBPolicyLineMethods. For example, the PolicyPeriodPlugin policy period plugin implementation has a
postApplyChangesFromBranch method. This method calls postApplyChangesFromBranch for each line in the
policy period.
To implement functionality for the workers’ compensation line of business, the gw.lob.wc.WCPolicyLineMethods
class implements the postApplyChangesFromBranch method.
sourcePeriod argument. This job is preempted by another job. The policyPeriod argument is the PolicyPeriod
created for the preempting job. PolicyCenter applies the changes to policyPeriod by adding the vehicle and two
coverages to the policyPeriod branch. Then PolicyCenter calls this plugin method.
For example, the WCPolicyLineMethod class has a postCreateDraftBranchInNewPeriod method. This method
updates workers’ compensation jurisdiction rating period start dates (RPSDs) after creating a draft in the new period.
Policy plugin
You can customize how PolicyCenter determines whether the application can start various jobs, based on dynamic
calculations on the policy. Define your own implementation of the IPolicyPlugin plugin to customize all jobs
except submission. There is a built-in implementation of this plugin with default behaviors.
The built-in implementation of this plugin requires the following conditions to exist.
• The policy is a monoline workers’ compensation policy.
• The user has permission to create and complete an audit job.
• The policy is issued.
• The current term is not archived.
For example, the first half-year term of a policy starts on August 30, 2018. The month of August has 31 days. Date
reconciliation ensures two half-year terms provide coverage for a full year.
The built-in plugin uses the policyPeriod parameter for date reconciliation. The calculatePeriodEnd method
uses the PolicyPeriod.Job.shouldPerformDateReconciliation flag to determine whether to reconcile the date.
By default, the flag is false. However, the SubmissionImpl and RenewalImpl classes set the flag to true.
Proration plugin
PolicyCenter has the following uses for the proration plugin.
• Generating transaction calculations
• Rating integration
• Calling the financialDaysBetween method to calculate a date range that rating uses
PolicyCenter standardizes proration calculations in the proration plugin. For example, the transaction calculator uses
the proration plugin rather than directly implementing its own proration.
The built-in implementation of the ProrationPlugin plugin implements the IProrationPlugin plugin interface. If
you need to customize proration, you can create your own class that implements this plugin interface. For example,
you can change how the plugin calculates the number of financial days between two dates.
Account and policy plugins 173
Guidewire PolicyCenter 9.0.6 Integration Guide
The Prorater class has a method called prorate that PolicyCenter rating code calls to prorate an amount. The
prorate method is public but is final, which means that you cannot override the method. The built-in implementation
of this method calls the method prorateFromStart and implements standard proration.
In the base configuration, the financialDaysBetween and findEndOfRatedTerm methods ignore a leap day if
either of the following conditions exists.
• The IgnoreLeapDays parameter on the plugin interface is true.
• The IgnoreLeapDays parameter is not specified, and the config.xml parameter
IgnoreLeapDayForEffDatedCalc parameter is true.
The financialDaysBetween and findEndOfRatedTerm methods are complementary. Therefore, a change in one
method often necessitates a corresponding change in the other method. For example, in the following code, the
values for newDate and date2 must be the same after running the code.
See also
• For the relationship between Cost and CostData, see “Overview of cost data objects” on page 362
The base configuration of PolicyCenter uses a built-in implementation of the plugin, PCPurgePlugin.gs. To edit the
registry for PurgePlugin, in Studio, navigate to configuration→config→Plugins→registry, and open the
PurgePlugin.gwp file.
See also
• Application Guide
• Configuration Guide
Create context
The createContext method takes as input a PurgeContext object and returns a new ExtendedContext object. The
ExtendedContext object is passed from the prepareForPurge method to the postPurge method. The
createContext method sets up the object before it is passed to the prepareForPurge method.
In the base configuration, the PCPurgePlugin class simply returns the input PurgeContext object in the
createContext method.
In your implementation of the PurgePlugin plugin interface, you can modify the ExtendedContext object. You can
also create subclasses of this object.
In your implementation, you can also modify the createContext method. For example, based on business logic you
can determine which subclass of the ExtendedContext object to return.
PurgeStatus Action
NoActionRequired This status indicates that no purging is necessary. The code simply returns null.
Pruned This status indicates that the job has no alternate versions to prune. This job is not in need of pruning,
but the job may be in need of purging. Therefore the code calculates and returns the purge recheck date.
Unknown This status indicates that the job purge status is not known. This job may be in need of pruning or purg‐
ing. Therefore the code calculates the prune and purge recheck dates. The code compares these two
dates and returns the earlier date.
The base configuration PCPurgePlugin plugin class performs the following operations in the getPurgeJobDate
method.
• Calculates the purge date for closed jobs.
• Calculates the purge date based on the number of days that must pass after the end of a job’s selected policy. This
is defined in the PurgeJobsPolicyTermDays parameter.
If PurgeJobsPolicyTermDaysCheckDisabled is true, then this date is null.
• Compares the two purge dates, and return the later date. The job can be purged on or after this date.
Property Description
Policy Contains one of the following items.
• The policy being purged
• The parent policy of the job being purged
• The parent policy of the policy period being purged
Job The job being purged or the parent job of the policy period being purged, if any.
PolicyPeriod The policy period being purged.
You can extend the PurgeContext object by adding additional properties. For an example, see the PurgePlugin
class which contains a static inner class ExtendedContext.
178 chapter 8: Account and policy plugins
Guidewire PolicyCenter 9.0.6 Integration Guide
If you extend the PurgeContext object, Guidewire recommends that these properties contain data values rather than
entity references. Never add a property with an entity reference belonging to the domain graph of the purged object
because the purged object does not exist after the purge.
Renewal plugin
To customize how PolicyCenter handles renewals, implement IPolicyRenewalPlugin. For example, this plugin
determines when to start a Renewal job for a PolicyPeriod. However, note that this plugin does not actually create
the Renewal job itself. Instead, the work queue called PolicyRenewalStart actually starts the renewal job. A work
queue is like a built-in batch process except that it automatically parallelizes the work across a PolicyCenter cluster.
The renewal work queue looks for policy renewals to start.
The most important method in the IPolicyRenewalPlugin plugin interface is the shouldStartRenewal method. It
determines whether to start the renewal job, as previously mentioned. Its only argument is a policy period and
returns true if and only if the policy period is ready for a new renewal.
The built-in implementation evaluates the date that the renewal normally starts. To do this it calls another method on
the plugin called getRenewalStartDate. If you write your own version of this plugin, refer to the built-in
implementation and copy the code from the getRenewalStartDate method if appropriate.
If you write your own version of this plugin, refer to the built-in implementation class
gw.plugin.job.impl.PolicyRenewalPlugin. Copy the getRenewalStartDate method as appropriate.
Account and policy plugins 179
Guidewire PolicyCenter 9.0.6 Integration Guide
The plugin implemented in the base configuration performs the following operations.
• If there are open conflicting jobs on the policy, it prevents renewal until the user handles these issues.
• If there are no conflicting jobs, this method returns true if getRenewalStartDate() returns a date in the past.
• If there are conflicting jobs, this method returns true if getRenewalStartDate() returns a date less than three
days in the past.
• All other cases return false.
Authentication integration
To authenticate PolicyCenter users, PolicyCenter by default uses the user names and passwords stored in the
PolicyCenter database. Integration developers can optionally authenticate users against a central directory such as a
corporate LDAP directory. Alternatively, use single sign-on systems to avoid repeated requests for passwords if
PolicyCenter is part of a larger collection of web-based applications. Using an external directory requires a
user authentication plugin.
To authenticate database connections, you might want PolicyCenter to connect to an enterprise database but need
flexible database authentication. Or you might be concerned about sending passwords as plaintext passwords openly
across the network. You can solve these problems with a database authentication plugin. This plugin abstracts
database authentication so you can implement it however necessary for your company.
Authentication
Get auth. credential Source Creator
(step 2) Plugin
API Guidewire
Client Login
Application
Request Authentication request
(step 3)
Web (step 1)
Browser Authentication Verify External Directory
Authentication Response Service Plugin Credentials LDAP, etc
(step 5) (step 4)
Note: by default, the built-in
Optional callback changes authentication service uses
the internal user database.
Application Server
3. The server requests authentication using an authentication service – PolicyCenter passes the authentication
source to the authentication service. The authentication service is responsible for determining whether or not
to permit the user to log in.
4. The authentication service checks the credentials – The built-in authentication service checks the provided
username and password against information stored in the PolicyCenter database. However, a custom
implementation of the plugin can check against external authentication directories such as a corporate LDAP
directory or other single sign-on system.
5. Authentication service responds to the request – The authentication service responds, indicating whether to
permit the login attempt. If allowed, PolicyCenter sets up the user session and give the user access to the
system. If rejected, PolicyCenter redirects the user to a login page to try again or return authentication errors to
the API client. This response can include connecting to the PolicyCenter callback handler, which allows the
authentication service to search for and update user information as part of the login process. Using the
callback handler allows user profile information and user roles to optionally be stored in an external repository
and updated each time a user logs in to PolicyCenter.
throw new DisplayableLoginException("The application shows this custom message to the user")
Optionally, you can subclass DisplayableLoginException to track specific different errors for logging or other
reasons.
• If that approach is insufficient for your login exception handling, you can create a custom exception type by
subclassing the Java base class javax.security.auth.login.LoginException.
See also
• “Create a custom exception type” on page 185
Procedure
1. Create a subclass of javax.security.auth.login.LoginException for your authentication source
processing exception.
2. To ensure the correct text displays for that class, create a subclass of gw.api.util.LoginForm.
3. In your LoginForm subclass, override the getSpecialLoginExceptionMessage(LoginException) method.
PolicyCenter only calls this method for exception types that are not built-in. Your version of the method must
return the String to display to the user for that exception type. Note that the only supported method of
LoginForm for you to override is getSpecialLoginExceptionMessage.
4. Modify the Login.pcf page, which controls the user interface for that form. That PCF page instantiates
gw.api.util.LoginForm. Change the PCF page to instantiate your LoginForm subclass instead of the default
LoginForm class.
The plugin interface provides a single method called createSourceFromHTTPRequest. The following example
demonstrates how to implement this method.
https//myserver:8080/pc/PolicyCenter.do?username=aapplegate&password=sheridan&objectID=12354
The following code block extracts the username and password parameter values from the URL.
package docexample
uses gw.plugin.security.AuthenticationSource
uses gw.plugin.security.AuthenticationSourceCreatorPlugin
uses gw.plugin.security.UserNamePasswordAuthenticationSource
uses javax.servlet.http.HttpServletRequest
return source
}
}
You can implement this authentication source creator interface and store more complex credentials. In such a case,
you must also implement an authentication service that knows how to handle these new sources. To do that,
implement an AuthenticationServicePlugin user authentication service plugin.
Initialization
All authentication plugins must initialize itself in the plugin’s init method.
Setting callbacks
A plugin can look up and modify user information as part of the authentication process using the plugin’s
setCallback method. This method provides the plugin with a call back handler of type CallbackHandler. Your
plugin must save the callback handler reference in a class variable to use it later to make any changes during
authentication.
Authentication
Authentication decisions from a username and password are performed in the authenticate method. The logic
in this method can be almost anything you want, but typically would consult a central authentication database.
The basic example included with the product uses the CallbackHandler to check for the user within
PolicyCenter. The JAAS example calls a JAAS provider to check credentials. Then it looks up the user’s public
ID in PolicyCenter by username using the CallbackHandler to determine which user authenticated.
Every AuthenticationServicePlugin must support the default UserNamePasswordAuthenticationSource. You
can create custom authentication sources with a custom authentication source creator plugin implementation. If you
do so, your AuthenticationServicePlugin implementation must support your new type of authentication sources.
Almost every authentication service plugin uses the CallbackHandler that is provided in the setCallback method.
The typical use of the callback is to look up the public ID of the user after verifying the credentials. Find the Javadoc
for this interface in the class AuthenticationServicePluginCallbackHandler. The utility class includes the
following methods.
• findUser – Looks up a user’s public ID based on login user name.
• modifyUser – After getting current user data and making changes, perhaps based on contact information stored
externally, the method allows the plugin to update the user’s information in PolicyCenter.
• verifyInternalCredential – Supports testing a username and password against the values stored in the main
user database. The method is used by the default authentication service.
examples/src/examples/pl/plugins/authenticationservice
The examples zip file and the authenticationservice folder contain the following examples.
GWAuthenticationServicePlugin Source code for the PolicyCenter default authentication service plugin implementation.
The code checks the username and password against information stored in the
PolicyCenter database. If the code finds a match in the database, it authenticates the
user.
JAASAuthenticationServicePlugin Illustrates how to create a plugin implementation to authenticate against an external
repository using JAAS. JAAS is an API that enables Java code to access authentication
services without being tied to those services.
LDAPAuthentcationServicePlugin Illustrates how to create a plugin implementation to authenticate against an LDAP di‐
rectory.
See also
• “Create a custom exception type” on page 185
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "LDAP://" + _serverName + ":" + _serverPort);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
String userName = uNameSource.getUsername();
if (StringUtils.isNotBlank(_domainName)) {
userName = _domainName + "\\" + userName;
}
/*
The latest revision of LDAPv3 discourages defaulting to unauthenticated
when no password is supplied so this should not need checking,
however this behavior depends upon the configuration of the LDAP server.
See RFC 4511 - inappropriateAuthentication (48) and C.1.12. Section 4.2 (Bind Operation)
*/
if (StringUtils.isBlank(uNameSource.getPassword()) {
throw new LoginException("No, or empty, password supplied");
}
env.put(Context.SECURITY_PRINCIPAL, userName);
env.put(Context.SECURITY_CREDENTIALS, uNameSource.getPassword());
try {
// Try to login.
new InitialDirContext(env);
/* Here would could get the result to the earlier
and modify the user in some way if you needed to
*/
} catch (NamingException e) {
throw new LoginException(e.getMessage());
}
return userPublicId;
}
The username and password that this method returns need not be a plain text username and password, and it
typically would not be plain text. A plugin like this one typically encodes, encrypts, hashes, or otherwise converts
the data into a secret format. The only requirement is that the receiver of the data knows how to authenticate against
the username and password.
The following example demonstrates this method by pulling the information from a file.
Guidewire PolicyCenter includes an example database authentication plugin that simply reads a username and
password from files specified in the usernamefile or passwordfile parameters that you define in Studio.
PolicyCenter replaces the ${username} and ${password} values in the jdbcURL parameter with values returned by
your plugin implementation. For this example, the values to use are the text of the two files: one for username, one
for password. For the source code, refer to the FileDBAuthPlugin sample code in the
examples.plugins.dbauthentication package.
Document management
PolicyCenter provides a user interface and integration APIs for creating documents, downloading documents, and
producing automated form letters. You can integrate the PolicyCenter document user interface with an external
document management system that stores documents and, optionally, the document metadata.
This topic discusses document management in general, as well as details of integrating with a document
management system.
In PolicyCenter, the production of policy forms for printing services are unrelated to document management as
described in this topic. There is a separate PolicyCenter forms API that is specific to the PolicyCenter product
model.
the ContactManager application supports document upload for vendor contact documents but does not support
document production.
For document storage, the ContactManager application includes an additional demonstration content storage system
implemented by a servlet. This servlet-based content storage system is unsupported for production systems.
ID ID ID
ID ID ID
Other
Web Guidewire external
Browser Application systems
Optionally external services can use web services to integration glue code
link documents to business objects
External Document Storage and Internal Metadata (Highest Performance Storage and Searching)
Use customer-written content source plugin implementation. Disable the document metadata source plugin.
ID ID ID
ID ID ID
Document
Web Guidewire Document Management
document Document content
Browser Application Content System (DMS)
content
Source
plugin
Optionally DMS uses web services to link documents integration glue code
to business objects
Document
document Metadata store metadata ID ID ID
ID
metadata Source
ID ID ID
plugin return metadata including doc UIDs
document Document
Web Guidewire Document document content Management
Browser Application content Content System (DMS)
optionally, Source
metadata
ID
plugin optionally set metadata for add/update
Optionally DMS uses web services to link documents integration glue code
to business objects
object as a parameter. Use the Document.DocUID property to identify the target document within the repository. If
the document with that document UID exists in the external DMS, return true. Otherwise return false.
The isDocument method must not modify the Document entity instance in any way.
PolicyCenter calls some methods in a IDocumentContentSource plugin twice for each document: isDocument and
getDocumentContentsInfo. Your plugin implementation must support this design.
The isDocument function is called before the rendering of the View button on the Documents page. If isDocument
returns false, then the View button does not call the document content source plugin to open the document.
Therefore, for all existing documents for which the end user wants the View button to display the document, the
isDocument implementation must return true.
Note that PolicyCenter does not require the document name to be unique in the DMS. If you cannot make the
document unique, there is an API that you can use or modify to adjust the name. In Studio, see the
adjustDocumentNameIfDuplicate method in the gw.document.DocumentEnhancement enhancement.
What happens for errors and validation issues after you send files to the DMS
Normally, PolicyCenter persists changes to the Document entity that you made in addDocument. For example, your
addDocument implementation must set Document.DocUID to a value that can be used to retrieve it from the DMS.
However, even if the addDocument method completes successfully without throwing exceptions, errors could still
occur in other code before the Document entity instance changes persist to the database. Even what appears to the
user as a validation warning (not error) would prevent the bundle from committing. Any recent changes to the
bundle including the Document entity are rolled back, which means to be restored to their original values in the
database.
During rollback, your changes to the Document.DocUID property and only that property are preserved. Before
rollback occurs, the application saves the Document.DocUID property value. Note that the Document.DocUID
property value can optionally contain a serialized set of multiple custom properties in one String value. Then, the
application restores the entity instance to its previous state in the database (this is the rollback). Finally, the
application sets the Document.DocUID property value to the previously saved value, which might include changes
that your code has made. However, no other properties are restored from the previous database transaction are
restored. The Document.DocUID property is preserved to reduce the chance of orphaned documents, which are to
documents sent to the DMS but have no persisted links from PolicyCenter objects.
You might want multiple custom fields on the Document entity instance to survive rollback after your code
completes its addDocument method. If so, it is best to remove the custom fields from the Document data model and
serialize that information collectively into the DocUID property. This technique provides some level of protection
during error conditions that cause a rollback because the DocUID property is specially preserved.
It is important to understand that after rollback, the Document entity instance is in PolicyCenter server memory but
not yet persisted. If the user fixes whatever errors caused the rollback (such as validation issues) and tries again, the
Document entity instance is persisted along with the rest of the bundle. However, if the bundle is never committed
due to repeated failure to commit the bundle, the document content is orphaned. Your code has sent the document
content to the DMS, but no metadata or PolicyCenter object links to that document content.
There is an additional optional configuration of Document rollback that might be useful in some cases. There is a
config.xml property called RecallDocumentContentSourceAfterRollback. By default it is set to false. If you
set it to true and errors occur after your addDocument method is called but before the bundle is committed, the
application calls addDocument again after rollback. However, for this circumstance, the input stream argument to
addDocument is null. The null value for the input stream indicates that you do not need to send document content
to the DMS because it succeeded already. However, your addDocument method has an opportunity to do additional
processing of the Document entity or communicate with the DMS after rollback, if it is useful to do so.
Retrieve documents
An implementation of the IDocumentContentSource plugin must fulfill requests to retrieve a document. The
following two plugin methods perform this task.
In typical cases when a document must be retrieved, the getDocumentContentsInfo method is called. In cases
where the retrieved document will be published externally, such as when it will be attached to an outgoing email, the
getDocumentContentsInfoForExternalUse method is called.
198 chapter 10: Document management
Guidewire PolicyCenter 9.0.6 Integration Guide
Arguments
Both retrieval methods accept a Document object argument. The DocUID property specifies the desired document.
The plugin methods can access the Document argument’s properties, but the properties must not be modified. To add
modifiable properties to the Document class, the recommended method is to serialize the additional data in the
DocUID property. This technique is preferred over the usual practice of adding properties by extending the Document
class.
The includeContents argument specifies whether to include the document contents in the returned object.
The getDocumentContentsInfo method can return a reference to the retrieved document in the following formats.
• As a URL address to a network store that can display the document contents
• As an input stream that contains the document contents as a stream of bytes
The getDocumentContentsInfoForExternalUse method always returns the retrieved document as an input stream
that contains the document contents.
Return value
Both retrieval methods return a DocumentContentsInfo object containing the response data. The following
properties of the object can be set.
• ResponseType – Specifies the format of the retrieved document contents. Note that the actual document contents
are returned only if the method’s includeContents argument is true. However, the ResponseType property is set
regardless of whether the document contents are returned. If the contents are not returned, the property specifies
the format the contents would have been returned in.
Supported response type values are DOCUMENT_CONTENTS, URL, and URL_DIRECT. Each value is referenced
through gw.document.DocumentContentsInfo.ContentResponseType, as shown in the example below.
returnedDocContentsInfo.ResponseType = gw.document.DocumentContentsInfo.ContentResponseType.URL
The method accepts an argument of the relevant Document. The DocUID property identifies the specific document.
Document management 199
Guidewire PolicyCenter 9.0.6 Integration Guide
The method calls the IDocumentContentSource plugin method getDocumentContentsInfo to retrieve the
document’s information, including its content disposition.
If either a problem occurs in the retrieval operation or the retrieved disposition value is DEFAULT, the method returns
the ContentDisposition value specified in the DocumentContentDispositionMode configuration parameter.
Otherwise, the method returns the document’s ContentDisposition value as specified in the
DocumentContentsInfo class ContentDispositionType property.
See also
• “Render a document” on page 201
Remove documents
A new document content source plugin must fulfill a request to remove a document. To remove a document,
PolicyCenter calls the plugin implementation’s removeDocument method. This method takes a Document object as a
parameter. Use the Document.DocUID property to identify the target document within the repository.
PolicyCenter calls this method to notify the document storage system that the document corresponding to the
Document object will soon be removed from metadata storage. Your IDocumentContentSource plugin
implementation can decide how to handle this notification. Choose carefully whether to delete the content, retire it,
archive it, or another action that is appropriate for your company. Other Document entities may still refer to the same
content with the same Document.DocUID value, so deletion may be inappropriate.
Be careful writing your document removal code. If the removeDocument implementation does not handle metadata
storage, then a server problem might cause removal of the metadata to fail even after successful removing document
contents.
If the removeDocument method removed document metadata from metadata storage and no further action is required
by the application, return true. Otherwise, return false. If you do not enable and implement the
IDocumentMetadataSource plugin, you must return true.
200 chapter 10: Document management
Guidewire PolicyCenter 9.0.6 Integration Guide
Render a document
The DocumentsUtilBase class provides various methods to assist the user interface in rendering the contents of a
retrieved document.
renderDocumentContentsWithDownloadDisposition(filename : String,
documentContentsInfo : DocumentContentsInfo)
renderDocumentContentsDirectly(filename : String,
documentContentsInfo : DocumentContentsInfo,
contentDisposition : ContentDisposition)
Both methods render a referenced document to a file which the client browser can process.
The filename argument specifies the file to render the document to. The documentContentsInfo argument
contains information about the retrieved document. Each method requires the document’s ContentDisposition
value. The disposition is passed to the renderDocumentContentsDirectly method in the contentDisposition
argument. The renderDocumentContentsWithDownloadDisposition method retrieves the disposition from the
Download attribute of the current user interface widget.
The DocumentsUtilBase class also provides methods that are intended to be used by a user interface Gosu action.
Each method marks a specified FileInput file widget so that the server executes a special render command during
processing of the response. The command instructs the client browser to download the contents of the relevant
document and immediately display the downloaded contents in the widget.
markFileInputForClientInitiatedDownload(fileWidgetId : String)
markFileInputForClientInitiatedDownload(fileWidgetId : String,
contentDisposition : ContentDisposition)
Each of the two signatures for the markFileInputForClientInitiatedDownload method accepts a fileWidgetId
argument that specifies the ID of a FileInput widget. Each signature requires a ContentDisposition value. One
signature accepts a contentDisposition argument, while the other signature always uses the disposition specified
in the DocumentContentDispositionMode configuration parameter.
As its slightly different name implies, the markFileInputsForClientInitiatedDownload method can mark
multiple FileInput widgets. The method accepts an array of objects where each object is one of the following
elements.
• A FileInput ID in the form of a String. The disposition specified in the DocumentContentDispositionMode
configuration parameter is used to process the document.
• A two-element array containing a FileInput ID and the ContentDisposition value to use to process the
document.
The following example code demonstrates the method’s Gosu syntax using various arguments.
markFileInputsForClientInitiatedDownload({
‘widgetID_001’, // Use DocumentContentDispositionMode config param
{‘widgetID_002’, gw.document.ContentDisposition.DEFAULT}, // Also uses the config parameter
{‘widgetID_003’, gw.document.ContentDisposition.INLINE},
{‘widgetID_004’, gw.document.ContentDisposition.ATTACHMENT}
})
With the IDocumentMetadataSource plugin enabled, asynchronous document storage is not supported.
Basic methods
Method: saveDocument
Implement the saveDocument method to persist document metadata from a Document object to your document
repository. The only argument is a Document entity. If document content source plugin methods addDocument or
updateDocument return false to indicate they did not handle metadata, PolicyCenter calls the document metadata
source plugin saveDocument method.
If the document or any child object does not already have a non-null PublicID property, the method must select and
set a unique PublicID value.
The method has no return value.
When using IDocumentMetadataSource plugin, messaging events never fire for document actions. If your
application logic requires to be notified about document change events, add any relevant logic to the relevant plugin
methods. The typical location to add this kind of logic is the IDocumentContentSource plugin implementation, not
the IDocumentMetadataSource plugin implementation.
Method: retrieveDocument
The retrieveDocument method retrieves a document’s metadata from a document management system.
The uniqueId argument specifies the document’s unique public ID. If an error occurs when communicating with the
document management system, the method throws a java.rmi.RemoteException.
The method returns a Document object containing the retrieved metadata. In addition to containing the retrieved
metadata, the internal properties of the Document object must be initialized by calling the following methods.
• DocumentsUtilBase.initOriginalValues – The method accepts the Document object as an argument.
• The Document object’s setRetrievedFromIDMS method – The method takes no arguments. It performs the
following operations.
◦ Marks the Document as having been initialized from the document management system.
◦ Initializes the Document entity’s internal flag indicating that the Document does not currently need to be
persisted.
The following example code demonstrates the required initialization for a retrieved Document object.
// ... Create Document object and initialize with the data retrieved from the DMS
Method: searchDocuments
Implement the searchDocuments method to return the set of documents in the repository that match the given set of
criteria. It is important to understand that it is the responsibility of your plugin implementation to properly filter and
order the results based on the arguments to the searchDocuments method.
One method argument is a DocumentSearchCriteria entity instance, which defines the search criteria to send to the
DMS. Refer to the “Data Dictionary” for details about the individual search criteria properties in an
DocumentSearchCriteria entity instance.
202 chapter 10: Document management
Guidewire PolicyCenter 9.0.6 Integration Guide
Another argument is a RemotableSearchResultSpec Java object. This object contains sorting and paging
information for the PCF list view infrastructure for the results.
• GetNumResultsOnly – A boolean value that specifies whether to return only the number of results
• SortColumns – An array of RemotableSortColumn objects that define the sort order
• StartRow – The start row, as an int value
• MaxResults – Maximum results to return at one time, as an int value
• IncludeTotal – A boolean value that specifies whether to return the number of search results in the
TotalResults property.
When a user searches for documents, PolicyCenter calls the searchDocuments plugin method twice. The first
invocation retrieves the number of results. The second invocation gets the results. The two invocations are
differentiated by the value in the GetNumResultsOnly argument.
Before returning from this method, you must call the new setRetrievedFromIDMS method on each Document entity
instance. The setRetrievedFromIDMS method performs the following actions.
• Sets the Document property PersistenceRequired to false.
• Marks the document as coming from the IDocumentMetadataSource plugin.
The searchDocuments method must return search results in a DocumentSearchResult entity instance. Create a new
entity instance. To add a search result, call the addToSummaries method on the DocumentSearchResult entity
instance and pass a Document entity instance. Depending on how your DMS implementation implements search, you
might directly create the Document entity instance or you might call your own IDocumentMetadataSource plugin
method retrieveDocument. You can optionally set the Summaries property on DocumentSearchResult to an array
of Document objects.
If the IncludeTotal or GetNumResultsOnly property is true on the RemotableSearchResultSpec object, the
method sets the number of results in the TotalResults property.
Method: removeDocument
Implement the removeDocument method to remove document metadata for a Document object from the document
repository. You do not need to actually delete a document in the DMS. Instead you can mark the document metadata
so that it does not appear if the Guidewire application searches for this document metadata.
The method returns nothing.
When using IDocumentMetadataSource plugin, messaging events never fire for document actions. If your
application logic requires to be notified about document change events, add any relevant logic to the relevant plugin
methods. The typical location to add this kind of logic is the IDocumentContentSource plugin implementation, not
the IDocumentMetadataSource plugin implementation.
Method: isOutboundAvailable
Implement the isOutboundAvailable method. From Gosu this is the OutboundAvailable property. Return true to
indicate that the external DMS is available for storing metadata. If this returns true, the following methods can be
called: isDocument and getDocumentContentsInfo.
Method: isInboundAvailable
Implement the isInboundAvailable method. From Gosu this is the InboundAvailable property. Return true to
indicate that the external DMS is available for retrieving metadata. If the method returns true, the following
methods can be called.
• addDocument
• updateDocument
• removeDocument
Linking methods
The IDocumentMetadataSource plugin includes methods that enable the creation of many-to-many links from a
Document object to various Guidewire entity types.
Document management 203
Guidewire PolicyCenter 9.0.6 Integration Guide
In ContactManager, a Document object can have many-to-many links only to instances of the ABContact entity type.
Method: linkDocumentToEntity
Implement the linkDocumentToEntity method to associate a document with a Guidewire entity. The arguments are
an entity instance and a Document entity instance.
The method has no return value.
Note that document actions do not trigger a messaging event. If your application logic requires that it receive
notification about document change events, add the necessary logic to the relevant plugin methods. However, in
most situations, this kind of logic is added to the IDocumentContentSource plugin implementation, not the
IDocumentMetadataSource plugin.
Method: getDocumentsLinkedToEntity
Implement the getDocumentsLinkedToEntity method to return all documents associated with a Guidewire entity.
The only argument is an entity instance. Return a DocumentSearchResult entity instance, which encapsulates a list
of documents. The DocumentSearchResult entity instance is the same type of object as returned by the
searchDocuments method.
This method must call the setRetrievedFromIDMS method on any new Document entity instance. The
setRetrievedFromIDMS method sets document.PersistenceRequired to false and marks the document as
coming from the IDocumentMetadataSource plugin.
Method: isDocumentLinkedToEntity
Implement the isDocumentLinkedToEntity method to check if a document is associated with a Guidewire entity
instance. Return true if the document is associated with a Guidewire entity instance. Otherwise, return false.
Method: unlinkDocumentFromEntity
Implement the unlinkDocumentFromEntity method to remove the association between a document and a
Guidewire entity.
The method has no return value.
Method: getLinkedEntities
The getLinkedEntities method is supported by ContactManager only.
Implement the getLinkedEntities method to get a list of public IDs for entity instances associated with a specific
document.
For document storage, the base configuration of ContactManager provides a content storage system implemented by
a servlet. This servlet-based content storage system is not supported for production systems.
Documents are partitioned into subdirectories by policy and by relationships within the policy. The following table
explains this directory structure.
Note: For all entities, the public ID is used. No other types of ID are used.
PolicyCenter stores documents by the name you choose in the user interface as you save and add the file. If you add
a file from the user interface that would result in a duplicate file name, PolicyCenter warns you. The new file does
not quietly overwrite the original file. If you create a document by using business rules, the system forces
uniqueness of the document name. The server appends an incrementing number in parentheses. For example, if the
file name is myfilename, the duplicates are called myfilename(2), myfilename(3), and so on.
The document metadata source plugin in the base configuration provides a unique document ID back to
PolicyCenter. That document ID identifies the file name and relative path in the repository to the document.
Following is an example repository’s relative path to a policy document:
/documents/policyABC:02154/myFile.doc
The Sync-first and Async-only configurations are incompatible with enabling the IDocumentMetadataSource
plugin. If you want to enable the IDocumentMetadataSource plugin, you must use the Sync-only configuration.
Also note that the document storage configuration that you choose affects whether PolicyCenter can enforce
limitations on final documents.
The following diagram contrasts the three options for document storage asynchronous configuration.
“Sync‐only”
Direct synchronous connection to the IDocumentContentSource plugin implementation that connects to the DMS
“Sync‐first”
Direct connection to the built-in asynchronous content document store, which initially tries to send
synchronously while the application waits. If errors occur, document is added to a queue for later sending
(3) If error or
Built‐in asynchronous document queue (4) Later on, a server with
timeout,
(implements MessageTranport) messaging server
add to queue
role sends the document
to the document content source
“Async‐only”
All content goes to the built-in asynchronous document content source, which always sends
asynchronously using another document content source to actually contact the DMS
(2) add to the document queue immediately, but the document does not send immediately
Document
Guidewire Management
Built‐in asynchronous document queue System (DMS)
Application (implements MessageTranport)
(3) Later on, a server with messaging server role sends the document
to the class in the SynchedContentSource plugin parameter in IDocumentContentSource.gwp
Procedure
1. Write a content source plugin as described earlier in this topic. Your plugin implementation must implement
the interface IDocumentContentSource and must send the document synchronously. However, do not register
it directly as the plugin implementation for the IDocumentContentSource plugin interface in the Plugins
editor in Guidewire Studio™.
2. In the Studio Project window, navigate to Configuration→config→Plugins→registry, and then open
IDocumentContentSource.gwp. Studio displays the Plugins Registry editor for the default implementation of
this plugin. In the default configuration, the Gosu class field has the value
gw.plugin.document.impl.AsyncDocumentContentSource. Do not change that field.
3. In the Parameters table, find the SynchedContentSource parameter. Set it to the fully-qualified class name of
the class that you wrote that implements IDocumentContentSource.
4. In the Parameters table, find the documents.path parameter. Set it to the local file path for temporary storage
of documents waiting to be sent to document storage. In a clustered environment, map the local path to this
temporary directory so that it references a server directory shared by all elements of the cluster. For example,
map this to an SMB server.
5. By default, PolicyCenter first attempts synchronous sending even when asynchronous sending is enabled. It is
only if that attempt fails that the document is added to the asynchronous queue. This configuration is called
sync-first.
Alternatively, you can force the application to always use asynchronous sending even with initial attempts.
This configuration is called async-only. To specify async-only configuration, perform the following steps.
a. In the Studio Project window, navigate to Configuration→config→Plugins→registry, and then open
IDocumentContentSource.gwp.
b. In the Parameters table, find the TrySynchedAddFirst parameter.
c. Set this parameter to false.
6. In the application config.xml file, set the FinalDocumentsNotEditable parameter to the value false. This
allows the document status final to be set on documents that were sent asynchronously. Without setting this
parameter to false, the DMS cannot add links or other meta to a final Document instance, which prevents
important connections between business data entities.
7. If you are not sure if messaging destination and plugins are enabled, perform the following steps.
a. In the Studio Project window, navigate to Configuration→config→Messaging, and then open messaging-
config.xml.
b. In the table, click the row for the messaging destination with name DocumentStore.
c. Clear the Disabled check box if it is set.
d. In the Studio Project window, navigate to Configuration→config→Plugins→registry, and then open
documentStoreTransport.gwp.
Document management 209
Guidewire PolicyCenter 9.0.6 Integration Guide
Procedure
1. In the Studio Project window, navigate to Configuration→config→Plugins→registry, and then open
IDocumentContentSource.gwp.
2. Set the class name to the fully-qualified class name of your own IDocumentContentSource implementation or
the built-in IDocumentContentSource implementation you want to use. The class name may already be in the
plugin parameter SynchedContentSourced. You can copy that value and remove the
SynchedContentSourced plugin parameter.
Be sure that the plugin registry does not set the class to be the internal class
gw.plugin.document.impl.AsyncDocumentContentSource. To disable asynchronous document content
storage, the Plugins registry for IDocumentContentSource.gwp must reference a IDocumentContentSource
implementation other than that class.
The default Plugins registry item is configured to a reference a Gosu class. If your IDocumentContentSource
implementation class was not implemented in Gosu, you must remove and then re-add the Plugins registry
item for that plugin interface. Click the red minus sign to remove the Gosu plugin configuration. If the plugin
implementation is in Java but without using OSGi, click the green plus sign and then click Java. If the plugin
implementation is an OSGi bundle, click the green plus sign and then click OSGi.
3. In the application config.xml file, set the FinalDocumentsNotEditable parameter to the value true. Setting
it to true enforces the document status final. The value true is incompatible with documents that were sent
asynchronously. When disabling asynchronous document content storage, it is best to restore enforcement of
the document status final.
4. Disable the messaging destination by performing the following steps.
a. In the Studio Project window, navigate to Configuration→config→Messaging, and then open messaging-
config.xml.
b. In the table, click the row for the messaging destination with name DocumentStore.
c. Select the Disabled checkbox.
d. In the Studio Project window, navigate to Configuration→config→Plugins→registry, and then open
documentStoreTransport.gwp.
e. Select the Disabled checkbox.
Final documents
PolicyCenter and ContactCenter have optional support for final documents, which are documents that are not
allowed to be modified after completion. Final document are implemented as documents whose Document.Status
property has the value DocumentStatusType.TC_FINAL.
The behavior and implementation details for final documents are different depending on whether you want to enable
the IDocumentMetadataSource plugin. If that plugin is enabled, the application stores document metadata in the
internal database rather than an external DMS.
In the default configuration, the config.xml file for ContactCenter sets FinalDocumentsNotEditable to false. In
contrast, PolicyCenter does not explicitly define the property, which has the effect of the default value true.
See also
• “Policy period web services” on page 124
Document production
PolicyCenter provides a user interface and APIs to create documents, download documents, and produce automated
form letters. This topic discusses creating new documents from templates.
In PolicyCenter, the production of policy forms for printing services are unrelated to document management as
described in this topic. There is a separate PolicyCenter forms APIs that is specific to the PolicyCenter product
model.
cases, you can create new document production types by writing an implementation of the IDocumentProduction
plugin.
Passage of time
Guidewire
Application
Prompt
user to Return the Prompt user for Request for
choose user’s chosen context objects document
template template such as recipients production
** descriptor
document creation
user interface Document Production Flow
see separate diagram
Request Return
template list template list
Black solid lines indicate primary Gray dotted lines indicate results or
direction of action or request other secondary actions
** for document production from activities, the activity defines the template in its DocumentTemplate property.
For document creation from Gosu business rules, you can specify the template explicitly.
Passage of time
Guidewire
Application
For
Document Production Implementation for One Document Type synchronous
A DocumentProduction class, but not registered in the Plugins Registry production,
send to DMS
be available in that user interface context. The template descriptor optionally can identify additional localized
versions of the template file for a user to select.
5. After you select a template, the document creation user interface returns the template descriptor information
for the chosen template to PolicyCenter.
6. PolicyCenter prompts you through the document creation user interface for other document production
information called context objects for the document merge. For example, choose the recipient of a letter or
other required or optional properties for the template. After you enter this data, the user interface returns the
context object data to PolicyCenter.
7. PolicyCenter requests document production from the document production (IDocumentProduction) plugin
implementation that is registered in the Plugins registry in Studio. The document production plugin gets a
template descriptor and a list of parameter data values. In the default implementation, the built-in document
production plugin implementation is merely a dispatch mechanism that maps from a MIME type to another
IDocumentProduction plugin implementation. Only the main document production (IDocumentProduction)
dispatcher is explicitly registered in the Plugins registry but other IDocumentProduction implementations do
the actual document production work.
8. The document production plugin appropriate for that MIME type uses the template descriptor to request the
actual template file from the template source. In the default configuration, the document source is a directory
on the server that holds the files. If the user requests a localized version of the template, the template source
returns the localized template.
9. The document production plugin is responsible for generating a new document, typically by merging a
template file with parameter data. PolicyCenter includes document production plugins that process Microsoft
Word files, Adobe Acrobat (PDF) files, Microsoft Excel files, and Gosu templates. You can also generate text
formats such as HTML and CSV using Gosu templates. If the document production request was triggered by
Gosu rules, the application populates any default values that are not explicitly provided.
The result of this step is a merged document.
10. After production, the document is added to the document management system. The details vary depending on
which APIs created the document, the application/code context, and how you configure the application.
• For synchronous document production from an activity or Gosu rules, the application automatically sends
the document to the document management system.
• For synchronous document production from the application user interface, the user must click the Update
button to save the document and send it to the document management system.
• For asynchronous document production APIs, you must modify the IDocumentProduction plugin to
support direct interaction with your document management system after production is complete.
• If document production happens on an external system, that system can add documents to the document
management system. Additionally the external system can link the document to PolicyCenter business
objects with PolicyCenter web services APIs.
The preceding steps describe the base implementation. You can configure many parts of the user interface and
underlying plugins to support your own business needs.
configure its dispatching algorithm. Modify the plugin parameters in the IDocumentProduction.gwp registry
item to map a MIME type to a IDocumentProduction plugin implementation class that can handle that MIME
type.
• Document production plugin implementations for a specific document type – Other IDocumentProduction
plugin implementations are called by the built-in dispatcher but are not registered in the Plugins Registry in
Studio as unique .gwp files. For example, there is a IDocumentProduction plugin implementation that can
handle Microsoft Word production. However, it is not independently registered as a separate item in the Plugins
registry. Instead, the plugin parameters in the IDocumentProduction.gwp registry item maps a MIME type to a
IDocumentProduction plugin implementation that is specific to a document type.
When the main document production plugin implementation gets a request for a new document, the main document
production plugin implementation dispatches the request to the appropriate IDocumentProduction plugin
implementation. The MIME type of the document determines which IDocumentProduction implementation to use.
PolicyCenter supports two types of document production. In synchronous production, the document contents are
returned immediately. In asynchronous production, the creation method returns immediately, but creation happens
later. Each type of document production has different integration requirements.
For synchronous production, PolicyCenter and its installed document storage plugins are responsible for persisting
the resulting document, including both the document metadata and document contents. In contrast, for asynchronous
document creation, the document production (IDocumentProduction) plugins are responsible for persisting the
data.
The IDocumentProduction plugin has two main methods.
• createDocumentSynchronously – Creates a document synchronously.
• createDocumentAsynchronously – Creates a document asynchronously.
There are additional interfaces that assist the IDocumentProduction plugin.
• Template source and template descriptor interfaces – The interfaces IDocumentTemplateDescriptor and
IDocumentTemplateSource encapsulate the basic interface for searching and retrieving the templates that
describe a document to create. The descriptive information includes the basic metadata (name, MIME type, and
so on) and a pointer to the template content on the file system. The IDocumentTemplateDescriptor
implementation describes the template that is used to create documents. The built-in IDocumentTemplateSource
implementation searches all available templates and retrieves document templates from the file system.
The built-in implementations of IDocumentTemplateSource and IDocumentTemplateDescriptor are sufficient
for nearly all requirements. Typically there is no need to re-implement these plugin interfaces. You can define
your template descriptors using the XML file format used by the built-in code that implements these plugin
interfaces.
• Interfaces for built-in production types – For the server-side production of PDF files, Microsoft Excel files, and
Microsoft Word files, PolicyCenter provides interfaces that define the core functionality. In the base
configuration, PolicyCenter provides implementations in proprietary code written in Java. You can replace the
built-in implementation with an entirely new implementation class, but the built-in implementations support most
requirements. If you write your own version, edit the appropriate plugin parameter for the
IDocumentProduction plugin interface in the Plugins Registry in Studio. Set the value for that MIME type to the
new implementation class. This parameter applies to the following interfaces.
◦ IPDFMergeHandler – Creates a merged PDF document.
◦ ServerSideWordDocumentProduction – Creates a merged Microsoft Word document.
◦ ServerSideExcelDocumentProduction – Creates a merged Microsoft Excel document.
returnedDocContentsInfo.ResponseType =
gw.document.DocumentContentsInfo.ContentResponseType.DOCUMENT_CONTENTS
See also
• “Implementing a document content source for external DMS” on page 196
newDocumentEntity = Policy.addDocument
In either case, immediately throw an exception if any part of your creation process fails.
See also
• “APIs to attach documents to business objects” on page 212
1. PolicyCenter searches the plugin parameters for a document template type value in the plugin parameter list
that matches the text in the documentProductionType property of the template. If a match is found,
PolicyCenter proceeds with document production using the specified IDocumentProduction implementation
class in that plugin parameter value.
2. If PolicyCenter does not find a match for the document production type, PolicyCenter searches the plugin
parameters for a MIME type that matches the mimeType property of the template. If a match is found,
PolicyCenter proceeds with document production using the specified IDocumentProduction implementation
class in that plugin parameter value.
3. If no match is found, document production fails. If this happens, review the configuration of the
IDocumentProduction plugin parameters and the MIME type configuration.
Procedure
1. In config.xml, add the new MIME type to the <mimetypemapping> section. The information for each
<mimetype> element contains the following attributes.
• name – The name of the MIME type. Use the same name as in the plugin registry, such as text/plain.
• extension – The file extensions to use for the MIME type.
If more than one extension applies, use a pipe symbol ("|") to separate them. PolicyCenter uses this
information to map between MIME types and file extensions. To map from a MIME type to a file extension,
PolicyCenter uses the first extension in the list. To map from file extension to MIME type, PolicyCenter
uses the first <mimetype> entry that contains the extension.
• icon – The image file for documents of this MIME type. At runtime, the image file must be in the SERVER/
webapps/pc/resources/images directory.
2. Add the MIME type to the configuration of the application server, if required. Ensure that the MIME type is
not in the list already before you try to add it. How you add a MIME type depends on the brand of application
server. Refer to your application server documentation for details. For Tomcat, configure MIME types in the
web.xml configuration file by using <mime-mapping> elements.
PolicyCenter/configuration/config/security/excel.lic
PolicyCenter/configuration/config/security/word.lic
Never remove or alter these license files. If changes are needed, replacements will be provided by Guidewire
Customer Support.
However, without a license key, the generated document will contain a large watermark that reads “DEMO” on each
page. To remove the watermark, obtain a BFO license key through Guidewire Customer Support.
Note that a BFO license key applies only to PDF document production. When generating a PDF from other sources,
such as when printing or exporting a ListView, the Apache Formatting Objects Processor (FOP) engine is used. The
Apache FOP engine is separate from the BFO engine and does not require a BFO license key. Consequently, PDF
files generated with the FOP engine never have a "DEMO" watermark.
Procedure
1. Receive an Authorization Form by contacting your Customer Support Partner or sending an email to
support@guidewire.com and request a PDF production license for PolicyCenter.
2. Fill out the Authorization Form.
3. Fax the filled-out form to Guidewire prior to issuing the license.
4. The Guidewire support engineer requests license keys from the appropriate departments.
5. Once the license keys are obtained, Guidewire emails the designated customer contact (per the information on
the form) with the license information. If you have additional questions about this process, email
support@guidewire.com.
6. In a clustered environment, set the license key value in the PDFMergeHandlerLicenseKey parameter in
config.xml for every server.
7. In the Project window, navigate to Configuration→config→Plugins→registry, and then open
IPDFMergeHandler.gwp. Although you must edit the Plugins registry in Studio, IPDFMergeHandler does not
correspond to a plugin interface that is intended for you to implement.
8. Ensure the implementation class is set to gw.plugin.document.impl.BFOMergeHandler.
9. In the list of plugin parameters set the plugin parameter LicenseKey value to your server key. The
LicenseKey value is empty in the default configuration. You must acquire your own BFO licenses from
customer support.
<FormField name="ClaimNumber">Claim.ClaimNumber</FormField>
</DocumentTemplateDescriptor>
id="SamplePage.gosu.htm"
name="Gosu Sample Web Page"
description="The initial contact reservation rights letter/template."
type="letter_sent"
lob="GLLine"
state="CA"
mime-type="text/html"
keywords="CA, reservation">
<FormFieldGroup name="main">
<DisplayValues>
<DateFormat>MMM dd, yyyy</DateFormat>
</DisplayValues>
<FormField name="ClaimNumber">Claim.ClaimNumber</FormField>
<FormField name="InsuredName">To.DisplayName</FormField>
<FormField name="InsuredAddress1">To.PrimaryAddress.AddressLine1</FormField>
<FormField name="InsuredCity">To.PrimaryAddress.City</FormField>
<FormField name="InsuredState">To.PrimaryAddress.State</FormField>
<FormField name="InsuredZip">To.PrimaryAddress.PostalCode</FormField>
<FormField name="CurrentDate">gw.api.util.DateUtil.currentDate()</FormField>
<FormField name="ClaimNoticeDate">Claim.LossDate</FormField>
<FormField name="AdjusterName">From.DisplayName</FormField>
<FormField name="AdjusterPhoneNumber">From.WorkPhone</FormField>
<FormField name="InsuranceCompanyName">Claim.Policy.UnderwritingCo</FormField>
<FormField name="InsuranceCompanyAddress">From.PrimaryAddress.AddressLine1</FormField>
<FormField name="InsuranceCompanyCity">From.PrimaryAddress.City</FormField>
<FormField name="InsuranceCompanyState">From.PrimaryAddress.State</FormField>
<FormField name="InsuranceCompanyZip">From.PrimaryAddress.PostalCode</FormField>
</FormFieldGroup>
</DocumentTemplateDescriptor>
keywords Required A set of keywords to search for within the template. Delimit keywords with the comma
character. Do not add space characters between keywords.
required- Optional The code of the SystemPermissionType value required for the user to see and use this
permission ** template. Templates for which the user does not have the appropriate permission do not
appear in the user interface. This setting does not prevent creation of a document by Gosu
(PCF files or rules).
** In the IDocumentTemplateDescriptor interface, this is the requiredPermission prop‐
erty.
<FormField name="PolicyInfo">Policy.CorePolicyNumber</FormField>
A form field can reference business data as objects referenced by symbols, which are programmatic labels for
objects such as entity instances. At run time, the list of symbols of this context is provided by the application. If you
trigger document creation in the user interface, the current PCF page defines the symbols. If you trigger document
creation from Gosu code such as from rule sets, the symbols and values are provided as a java.util.Map. For
example, form fields can reference a relevant policy by using the policy symbol. For example, get properties or call
methods with code such as policy.MyProperty or policy.myMethod().
<FormField> elements can contain any valid Gosu expression. If the logic is complex, you can call Gosu
enhancements or other APIs that encapsulate the logic. For example, you can create an Gosu enhancement method
Policy.getPolicyInfoSummary. Reference that function in a form field as follows.
<FormField name="PolicyInfoSummary">Policy.getPolicyInfoSummary()</FormField>
Typically, the Gosu in the <FormField> elements refer to a context object defined earlier in the file.
To add a prefix before the generated output from the Gosu expression, add the additional attribute prefix and set to
a simple text value. To add a suffix, use the suffix attribute. For example, to add the prefix “The policy information
is” and a period character as the suffix, specify the field as shown below.
<FormField name="MainContactName"
prefix="The policy information is "
suffix=".">
Policy.getPolicyInformation()
</FormField>
You must encapsulate your <FormField> elements in sets called field groups, even if there is only one field in the
group.
Field groups
In the XML file for a template descriptor, you must encapsulate your <FormField> elements in sets called field
groups, even if there is only one field in the group.
Form field groups are implemented as a <FormFieldGroup> element that contain the following elements.
• optional <DisplayValues> elements that customize the display of dates and other special values within this field
group.
• one or more <FormField> elements that represent form fields.
A descriptor file can have any number of <FormFieldGroup> elements. Define multiple field groups to define
common display attributes across only a specific subset of form fields. For example, perhaps only some fields share
the same a date string format or special handling of null, true, or false.
Display values
Define one or more <DisplayValues> elements within a <FormFieldGroup> element to customize display of date
values and other special values like the values null, true, or false. For example, you could use a
<DisplayValues> definition for a group to find the value null and instead output the text "No coverage". The
following table lists the elements you can insert inside a <DisplayValues> element. You can define more than one
of these child elements inside the <DisplayValues> element.
<NullDisplayValue> Customizes the display of null values. The content of the element is the value to substitute.
<FormFieldGroup name="default">
<DisplayValues>
<DateFormat>MMM dd, yyyy</DateFormat>
</DisplayValues>
<FormField name="CurrentDate">gw.api.util.DateUtil.currentDate()</FormField>
</FormFieldGroup>
The first three formats are the most commonly used because templates typically expire at the end of a particular day
rather than at a particular time.
For text elements, such as month names, PolicyCenter requires the text representations of the values to match the
current international locale settings of the server. For example, if the server is in the French locale, you must provide
the month April as "Avr", which is short for Avril, the French word for April.
When processing a document template with the template_tools command-line tool, the dates in the input files are
preserved, but the date format might change.
Context objects
In addition to the symbols provided by the API caller or the context of the user interface, a template descriptor can
define and reference a custom object called a "context object." A context object creates a new shorthand symbol that
can be referenced by FormField expressions. A template descriptor can define multiple context objects.
Without context objects, you would have access to only one or two high-level root objects, which would get
challenging. For example, suppose you want to address a policy acknowledgment letter to the main contact on the
policy. Without context objects, each FormField element would have to repeat a prefix many times.
<FormField name="ToName">Policy.MainAccountContact.DisplayName</FormField>
<FormField name="ToCity">Policy.MainAccountContact.PrimaryAddress.City</FormField>
<FormField name="ToState">Policy.MainAccountContact.PrimaryAddress.State</FormField>
This code is difficult to read because of its lengthy prefixes. Instead, you can simplify template code by defining a
ContextObject element that refers to the intended recipient. Each ContextObject must have the following required
attributes.
• name - Unique ID specified as a String, such as "To"
• type - Object type specified as a String, such as "Contact"
The ContextObject element can include the following optional attributes.
• display-name - Text to show in the user interface. Default value is the String assigned to the name attribute.
• allow-null - Boolean value indicating whether an object value is required. If false then the object is a required
field that must have a value assigned to it. Default is true.
Each ContextObject element must define a DefaultObjectValue element which specifies the element's default
value. The value can be a Gosu expression that returns the type specified in the ContextObject element's type
attribute. The DefaultObjectValue can reference another ContextObject by specifying the ContextObject
element's name. A ContextObject must been defined before it can be referenced.
A sample ContextObject is defined below.
The name attribute value of "To" defined in the sample ContextObject can be used to simplify the original
FormField elements.
228 chapter 11: Document production
Guidewire PolicyCenter 9.0.6 Integration Guide
<FormField name="ToName">To.DisplayName</FormField>
<FormField name="ToCity">To.PrimaryAddress.City</FormField>
<FormField name="ToState">To.PrimaryAddress.State</FormField>
The ContextObject also defines a list of possible values in a PossibleObjectValues element. The possible values
are specified as a Gosu expression that evaluates to an array. Typically the array contains entity instances, but that is
not a requirement.
Be aware that PolicyCenter does not verify and enforce that the type of the PossibleObjectValues matches the
type used by the DefaultObjectValue. While this makes it possible to have two different types for a single
ContextObject, Guidewire strongly recommends against this approach. If the specified types do not match, the
relevant FormField expressions must be written so they work correctly at run time with multiple types for the
ContextObject.
A sample ContextObject definition that specifies default and possible values is shown below.
Context objects have an additional purpose. In the user interface of the application, you can manually specify the
value of each context object within the user interface among multiple relevant possibilities. For example, the likely
recipient of an email can be set as a default, but the template can offer all contacts on the policy as alternatives.
If you select a document template from the chooser, PolicyCenter displays a series of choices, one for each context
object. The name of the context object appears as a label on the left, and the default value appears on the right. The
template defines the default value to use, but the user can override it by choosing from the list of possible object
values.
The type attribute on the ContextObject is used to indicate how the user interface presents the object in the
document creation user interface. Valid options include: String, text, Contact, User, Entity, Policy, or any other
PolicyCenter entity name or typekey type.
Document production 229
Guidewire PolicyCenter 9.0.6 Integration Guide
If the context object specifies type string, then the user would typically be given a single-line text entry box.
If the context object specifies type text, the user sees a larger text area. However, if the ContextObject definition
includes a PossibleObjectValues tag containing Gosu that returns a Collection or array of String objects, the
user interface displays a selection picker. For example, use this approach to offer a list of postal codes from which to
choose. If the object is of type Contact or User, in addition to the drop-down box, you see a picker button to search
for a particular contact or user. All other types (Entity is the default if none is specified) are presented as a drop-
down list of options. If the ContextObject is a typekey type, then the default value and possible values fields must
generate Gosu objects that resolve to TypeKey objects, not text versions of typecodes values.
There are a few instances in PolicyCenter system in which entity types and typekey types have the same name, such
as Contact. In this case, Gosu assumes you mean the entity type. If you want the typelist type, or want clearer code,
use the fully qualified name of the form entity.EntityName or typekey.TypeKeyName.
See also
• “Add custom attributes document template descriptor XML format” on page 232
<DisplayValues>
<NullDisplayValue>No Contact Found</NullDisplayValue>
<TrueDisplayValue>Yes</TrueDisplayValue>
<FalseDisplayValue>No</FalseDisplayValue>
</DisplayValues>
<FormField name="ClaimNumber">Claim.ClaimNumber</FormField>
</FormFieldGroup>
</DocumentTemplateDescriptor>
At run time, this XSD is referenced from a path relative to the module config/resources/doctemplates directory.
If you want to change this value, in the plugin registry for this plugin interface, in Studio in the Plugins editor, set
the DocumentTemplateDescriptorXSDLocation parameter. To use the default XSD in the default location, set that
parameter to the value "document-template.xsd" assuming you keep it in its original directory.
The attributes on the DocumentTemplateDescriptor element correspond to the properties on the
IDocumentTemplateDescriptor API.
<xsd:element name="DocumentTemplateDescriptor">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="ContextObject" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="HtmlTable" minOccurs="0" maxOccurs="unbounded" />
<xsd:element ref="FormFieldGroup" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string" use="required"/>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="identifier" type="xsd:string" use="optional"/>
<xsd:attribute name="scope" use="optional">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="all"/>
<xsd:enumeration value="gosu"/>
<xsd:enumeration value="ui"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="password" type="xsd:string" use="optional"/>
<xsd:attribute name="description" type="xsd:string" use="required"/>
<xsd:attribute name="type" type="xsd:string" use="required"/>
<xsd:attribute name="lob" type="xsd:string" use="required"/>
<xsd:attribute name="myattribute" type="xsd:string" use="optional"/>
<xsd:attribute name="section" type="xsd:string" use="optional"/>
<xsd:attribute name="state" type="xsd:string" use="required"/>
<xsd:attribute name="mime-type" type="xsd:string" use="required"/>
<xsd:attribute name="date-modified" type="xsd:string" use="optional"/>
<xsd:attribute name="date-effective" type="xsd:string" use="required"/>
<xsd:attribute name="date-expires" type="xsd:string" use="required"/>
<xsd:attribute name="keywords" type="xsd:string" use="required"/>
<xsd:attribute name="required-permission" type="xsd:string" use="optional"/>
<xsd:attribute name="default-security-type" type="xsd:string" use="optional"/>
</xsd:complexType>
</xsd:element>
Next, enable the user to search on the myattribute attribute and see the results. Add an item with the same name
(myattribute) to the PCF files for the document template search criteria and results.
Now the new myattribute property shows up in the template search dialog. The search criteria processing happens
in the IDocumentTemplateSource implementation. The default implementation, LocalDocumentTemplateSource,
232 chapter 11: Document production
Guidewire PolicyCenter 9.0.6 Integration Guide
automatically handles new attributes by attempting an exact match of the attribute value from the search criteria. If
the specified value in the descriptor XML file contains commas, it splits the value on the commas and tries to match
any of the resulting values.
For example, if the value in the XML is test, then only a search for "test" or a search that not specifying a value
for that attribute finds the template. If the value in the XML file is "test,hello,purple", then a search for any of
"test", "hello", or "purple" finds that template.
As PolicyCenter creates the merged document, the application tries to match attributes on the document template
with properties on the Document entity. For each matched property, PolicyCenter copies the value of the attribute in
the template descriptor to the newly created Document entity. The user can either accept the default or change it to
review the newly-created document.
Microsoft Word To use a Microsoft Word file for document production, you must set up the Word file to use form fields. For
example, suppose your template descriptor generates text for form fields called InsuredName and
PolicyNumber. Your Word file must contain form fields called InsuredName and PolicyNumber.
To set up form fields correctly, you need to create a temporary data source file that mimics the data that you
are going to import from PolicyCenter. The data source file could be a simple comma‐separated values (CSV)
file that you generate in Microsoft Excel, and save as CSV format.
Make the first line of the CSV file contain column headings that match your form fields. Continuing the earli‐
er example, the CSV file must have two columns with the first lines identifying columns called InsuredName
and PolicyNumber. To avoid Word errors caused by empty data source files, add one row of fake values for
each form field, as shown in the following example.
InsuredName,PolicyNumber
FakeName,FakePolicy
1. Start the Mail Merge wizard or chose Step by Step Merge Wizard.
2. When the wizard user interface asks about using an existing list, click Browse....
3. Select your CSV file.
4. If you see a dialog that asks for the delimiter, choose comma (,).
5. In any place in the document that you want to add a form field, click the Insert Merge Field button in the
Microsoft Word Ribbon user interface. From the dialog that appears, select the desired form field. For our
previous example, select InsuredName or PolicyNumber.
Microsoft Exel For Microsoft Excel files, form fields are implemented using what Excel calls named ranges.
1. Select a cell in the file.
2. Right‐click on it.
3. Choose Name.
4. Type the name of the form field as defined in your template descriptor file.
PolicyCenter/modules/configuration/config/resources/doctemplates
At run time, the document templates are typically in the following directory.
SERVER/webapps/pc/modules/configuration/config/resources/doctemplates
To set up a new form or letter, you must create a template file and a template descriptor file. Then, deploy them to
the templates directory on the web server.
To support localized templates, add extra descriptor files in subdirectories by locale code. For example, to add an
additional Japanese document template of the earlier example, add the descriptor to the following directory.
PolicyCenter/modules/configuration/config/resources/doctemplates/jp/Test.doc.descriptor
See also
• An external system can retrieve and validate document templates. For information, see “Template web service”
on page 109
Within Gosu rules, the Gosu class that handles document production is gw.document.DocumentProduction. It has
methods for synchronous or asynchronous creation, which call the respective synchronous or asynchronous methods
of the appropriate document production plugin, createDocumentSynchronously or
createDocumentAsynchronously. Additionally there is a method to store the document:
createAndStoreDocumentSynchronously. You can modify this Gosu class as needed.
If synchronous document creation fails, the DocumentProduction class throws an exception, which can be caught
and handled appropriately by the caller. If document storage errors happen later, such as for asynchronous document
storage, the document content storage plugin must handle errors appropriately. For example, the plugin could send
administrative e-mails or create new activities using SOAP APIs to investigate the issues. Or you could design a
system to track document creation errors and document management problems in a separate user interface for
administrators. In the latter case, the plugin could register any document creation errors with that system.
If the synchronous document creation succeeds, next your code must attach the document to the policy by setting
Document.Policy.
New documents always use the latest in-memory versions of entity instances at the time the rules run, not the
versions as persisted in the database.
Be careful creating documents within Pre-Update Gosu rules or in other cases where changes can be rolled back due
to errors (Gosu exceptions) or validation problems. If errors occur that roll back the database transaction even
though rules added a document an external document management system, the externally-stored document is
orphaned. The document exists in the external system but no PolicyCenter persisted data links to it.
uses gw.document.DocumentProduction
uses gw.plugin.Plugins
document in the external system is orphaned, and additional attempts to change PolicyCenter data regenerates a new,
duplicate version of the document.
For the common case of validation errors, PolicyCenter avoids this problem. If a validatable entity fails validation,
PolicyCenter saves the document UID in local memory. If the user fixes the validation error in that user session,
PolicyCenter adds the document information as expected so no externally-stored documents are orphaned.
However, if other errors occur that cause the transaction to roll back (such as uncaught Gosu exceptions), externally-
stored documents associated with the current transaction could be orphaned. The document is stored externally but
the PolicyCenter database contains no Document entity that references the document UID for it. Avoiding orphaned
documents is a good reason to ensure your Gosu rules properly catches exceptions and handles errors elegantly and
thoroughly. Write good error-handling code and logging code always, but particularly carefully in document
production code.
Procedure
1. Navigate to the Server Tools Guidewire Profiler Configuration screen.
The Profiler is accessible from the Server Tools screen. Special permission is required to access Server Tools.
2. Click Enable Web Profiling for this Session.
The application focus returns to the screen that was active before loading Server Tools.
3. Perform the desired document production operations.
4. Press ALT-SHIFT-P to return to the Guidewire Profiler.
5. Click Disable Web Profiling to end the profiling session.
6. Navigate to Guidewire Profiler Profiler Analysis. Select the Web screen.
7. Set the View Type to Chrono to view a chronological list of profiled events.
8. Expand the individual Stack Name entries to locate frames related to document production.
Document production frames are marked with the tag DocumentProduction.<event>, where <event> is a
particular operation. Example tags are DocumentProduction.GetValues and
DocumentProduction.Execute.
Guidewire PolicyCenter and Guidewire ContactManager provide an integration API for assigning a latitude and a
longitude to an address. These two decimal numbers identify a specific location in degrees north or south of the
equator and east or west of the prime meridian. The process of assigning these geographic coordinates to an address
is called geocoding. Additionally, ContactManager supports routing services, such as getting a map of an address
and getting driving directions between two addresses, provided that the addresses are geocoded already.
See also
Task Required
Assigning latitude and longitude coordinates •
Listing possible address matches
Returning driving directions
Finding an address from coordinates
Finding maps for arbitrary addresses
See also
• System Administration Guide
See also
• “Proxy servers” on page 645
See also
• System Administration Guide
See also
• System Administration Guide
A new Context object with a user culture and application key is created per request in BingMapsPluginRest. It is
possible to share Context objects across different requests. A Context object also has a RequestHandler, intended
to be used in the Context get or post methods (not implemented) to create the associated PendingResult object
from the request. Upon a PendingResult execute, the actual request to Bing Maps is performed, and the response
is then processed. This method can only be run once per request.
There is a RequestHandler and associated PendingResult implementation provided, which is being used in the
default Context constructor, HttpURLConnectionRequestHandler. The handlers have unimplemented handleGet
and handlePost methods that return an appropriate PendingResult object. Depending on the implementation, you
can set values for connection, read, and socket timeout on the handlers. You can also create custom handlers and
custom pending results.
A Config object can also be specified when constructing a request. This object specifies:
• REST API host name, with a default value of https://dev.virtualearth.net/REST/
• Version with a default value of v1
• Path, such as /Routes
• Resource path, such as Driving
• HTTP method for the request
Only GET is supported in the base configuration plugin implementation class for geocoding and routing.
There are default Config objects created if none are specified during request creation. In the plugin implementation
class, if the plugin parameters hostName or version have been set in the GeocodePlugin.gwp registry editor, the
Config objects for requests are overwritten with those values.
Procedure
1. Implement the plugin interface in Gosu.
If you want to use a geocoding service other than the one supported by the built-in GeocodePlugin
implementation, write your own implementation and register it in PolicyCenter Studio.
2. If your license for PolicyCenter includes use of Reinsurance Management and you want to support searching
for nearby locations, you must repeat the previous step in ContactManager Studio.
3. Register the plugin implementation in Studio:
a. In the Project window in Studio, navigate to Configuration→config→Plugins→registry, and then open
GeocodePlugin.gwp.
b. In the pane on the right, clear the Disabled checkbox.
c. In the Gosu Class text box, enter the name of the Gosu plugin implementation class that you want to use.
d. Edit the Parameters table to specify parameters and values that your plugin implementation requires, such
as security parameters for connecting to the external geocoding service, such as username and password.
4. Enable the user interface for geocoding features by configuring parameters in the config.xml file:
a. In the Project window in Studio, navigate to Configuration→config, and then open the config.xml file.
b. For PolicyCenter, modify the UseGeocodingInPrimaryApp parameter. This parameter specifies whether
PolicyCenter displays the user interface to search for nearby locations. For example:
See also
• System Administration Guide
240 chapter 12: Geographic data integration
Guidewire PolicyCenter 9.0.6 Integration Guide
Geocoding an address
The GeocodePlugin interface has one required method, geocodeAddressBestMatch. The method takes an Address
instance and returns a different Address instance. The address that the plugin returns has a GeocodeStatus value
that indicates whether the geocoding request succeeded and how precisely the geocode coordinates match the
incoming address. Valid values for GeocodeStatus include exact, failure, street, postalcode, or city. If the
status is anything other than failure, the Latitude and Longitude properties in the returned address are correct for
the returned address.
Your implementation of the geocodeAddressBestMatch method must not modify the incoming address instance for
any reason, such as using data returned from the geocoding service. Instead, use the clone method on the incoming
address to make a copy or create a new address instance by using the Gosu expression new Address().
Set the properties on the cloned or new address from the values returned by the geocoding service, and use that
address as the return value of your geocodeAddressBestMatch method.
The following example creates a new address and sets the geocoding status and the geocode coordinates.
a = new Address()
a.GeocodeStatus = GeocodeStatus.TC_EXACT
a.Latitude = 42.452389
a.Longitude = -71.375942
In a real implementation, your code assigns coordinate values obtained from the external geocoding service, not
from numeric literals as the example shows.
See also
• System Administration Guide
properties on the submitted address, set those properties on the address that your plugin returns to the values of the
modified properties.
To support address correction, override the geocodeAddressWithCorrections and pluginSupportsCorrections
methods. You must also implement a PCF file for the user interface to display a list of multiple addresses from
which the user selects the correct address.
Callers of the plugin must assume that blank properties in a returned address are intentionally blank. For example,
certain address properties in return data might be unknown or inappropriate if the geocoding status is other than
exact. If the geocode status represents the weighted center of a city, the street address might be blank because the
returned geocode coordinates do not represent a specific street address. PolicyCenter treats the set of properties that
the geocoding plugin returns as the full set of properties to show to the user or to log to the geocoding corrections
table.
Sometimes a geocoding service returns variations of an address. For example, the street address “123 Main Street”
might “123 North Main Street” and “123 South Main Street”, each with different geocode coordinates. The
geocoding service might return both results so that a user can select the appropriate one. Some variations might be
due to differences in abbreviations, such Street or St. Some services provide variants with and without suite,
apartment, and floor numbers from addresses, or provide variants that contain other kinds of adjustments. For the
geocodeAddressBestMatch method, return only the best match.
The getDrivingDirections method takes two Address entities. The method must send these addresses to a remote
driving directions service and return the results. If driving time and a map showing the route between the two
addresses are available, the method also returns these two values.
Address properties already include values for latitude and longitude before calling the plugin. Because some
services use only the latitude and longitude, driving directions can be to or from an inexact address such as a postal
code rather than exact addresses.
The plugin must return a DrivingDirections object that encapsulates the results. This class is in the
gw.api.contact package. To create a DrivingDirections object, you have two options.
• You can directly create a new driving directions object.
Error handling
If your plugin implementation fails to connect to the external geocoding service, throw the exception
java.rmi.RemoteException.
IMPORTANT The GeocodeStatus type list is final. You cannot extend it with type codes of your own.
Encryption integration
Encryption enables the protection of sensitive data, such as bank account information or personal data, by storing it
in a non-plaintext format. Guiidewire does not provide an encryption plugin in the base configuration. You must
create the plugin and provide your own implementation class if you want to encrypt data fields in PolicyCenter.
If the value of a user interface widget is set to a property expression and the property is encrypted, the widget
displays the data as visually masked for privacy. Note that the application does not display an input mask if the
expression is a method invocation rather than a property expression.
Denormalized columns
PolicyCenter prevents you from encrypting properties with a denormalized column. In other words, encryption is
prohibited on a property that creates a secondary column to support case-insensitive search. For example, the contact
property LastNameDenorm is a denormalized column added to mirror the LastName property. Therefore, the
LastName property cannot be encrypted.
Date columns
Date columns cannot be directly encrypted. If you store a date in the database as text, you can encrypt the field.
However, you would have to convert the text value to and from a Date object. Note that you would not be able to do
searches, have useful database indexes, or sort all records on that column. At a database level, that column is still
encrypted data.
If the downsides of this approach are acceptable, you can implement conversion to and from a Date object with a
Gosu enhancement. For example, suppose you add a date-of-birth column to the Contact entity type. Add the field
called dob_ext with type varchar with maximum 9 characters. Create a Gosu enhancement with a property setter
and getter for a new property called ContactDOB.
Update the date format String in the above example to match your preferred date format in the text field.
Restrictions
The query builder APIs restrict comparisons to encrypted values in the database to equality comparisons only. You
cannot use relative operators, such as “greater than” or “less than.” You can use the query builder APIs to make an
equality comparison of an encrypted column to one of the following items.
• A Gosu expression that evaluates to a String
• Another encrypted column
To uniquely identify your encryption algorithm, your plugin must return an encryption ID. Implement a
getEncryptionIdentifier method to return a unique identifier for your encryption algorithm. The identifier tracks
encryption-related change control and is exposed to Gosu as the property EncryptionIdentifier.
The encryption ID is very important and must be unique among all encryption plugins in your PolicyCenter
implementation. PolicyCenter decides whether to upgrade the encryption data with a new algorithm by comparing
the following encryption IDs.
• The encryption ID of the current encryption plugin
• The encryption ID associated with the database the last time the server ran
package Plugins
uses gw.plugin.util.IEncryption
uses java.lang.StringBuilder
During server startup, the upgrader checks the encryption ID of data in the main database. The server compares this
encryption ID with the encryption ID associated with the current encryption plugin. If the encryption IDs are
different, the upgrader decrypts encrypted fields with the old encryption plugin, found by its encryption ID. Next,
the server encrypts the fields to be encrypted with the new encryption plugin, found by its plugin name as specified
by the parameter CurrentEncryptionPlugin.
The following requirements are important to remember whenever you change encryption algorithms.
• All encryption plugins must return their appropriate encryption IDs correctly.
• All encryption plugins must implement getEncryptedLength correctly.
• You must set CurrentEncryptionPlugin to the correct plugin name.
The server uses an internal lookup table to map all previously used encryption IDs to an incrementing integer value.
This value is stored with database data. Internally, the upgrader manages this lookup table to determine whether data
needs to be upgraded to the latest encryption algorithm. Do not attempt to manage this table directly. Instead, ensure
every encryption plugin returns its appropriate encryption ID, and ensure CurrentEncryptionPlugin specifies the
correct plugin name.
Be careful not to confuse the encryption ID of a plugin implementation with its plugin name or class name. The
server relies on the encryption ID saved with the database and the encryption ID of the current encryption plugin to
identify whether the encryption algorithm changed.
Procedure
1. Shut down your server.
2. Register a new plugin implementation of the IEncryption plugin for your new algorithm. When you add an
implementation of the plugin in Studio, it prompts you for a plugin name for your new implementation. Name
it appropriately to match the algorithm. For example, "encryptDES3."
3. Be sure your plugin returns an appropriate and unique encryption ID. Name it appropriately to match the
algorithm. For example, "encryptDES3."
4. Set the config.xml configuration parameter CurrentEncryptionPlugin to the plugin name of your new
encryption plugin.
5. Start the server. The upgrader uses the old encryption plugin to decrypt your data and then encrypts it with the
new algorithm.
Management integration
The management integration API enables external applications to trigger PolicyCenter actions or retrieve
PolicyCenter data.
gwb genJavaApi
Extract the files in the archive file. The source files for the example plugins will be located in the following
PolicyCenter directory.
java-api/examples/src/examples/pl/plugins/management
Initialization methods
The ManagementPlugin interface provides methods to start and stop the communication channel used to receive and
respond to API calls.
function start()
function stop()
The JMXManagementPlugin example plugin implements these methods to set up and close the JMX communication
channel it uses to receive and respond to API requests. The AWSManagementPlugin start method gains access to
AWS Cloudwatch and schedules a daemon thread to intermittently perform the metric publishing operation. Its stop
method kills the thread.
The GWMBean arguments reference Guidewire management beans which are PolicyCenter resources, such as current
users, running batch processes, and configuration parameters. Each GWMBean contains information about itself,
including its name, description, attribute values, notifications, and operations it can perform.
The JMXManagementPlugin methods register and unregister the received bean argument. The
AWSManagementPlugin does not need a data repository, so its example methods log notification messages when they
are called.
Notification method
The ManagementPlugin interface defines a method to have a particular GWMBean generate a notification. A
notification can signal that its state has changed or an event or problem has occurred.
The notification argument references a Notification object containing information, including the name of the
relevant GWMBean. The Gosu Notification class is similar to the javax.management.Notification class. The
plugin can utilize the Java Notification framework if desired, but it is not mandatory.
254 chapter 14: Management integration
Guidewire PolicyCenter 9.0.6 Integration Guide
The JMXManagementPlugin sendNotification method demonstrates how to utilize the Java Notification
framework to have the relevant GWMBean send a notification. If the referenced GWMBean exists, the properties of the
method’s notification argument are passed to the javax.management.Notification constructor. The
AWSManagementPlugin does not support notifications and so its implementation of the sendNotification method
is empty.
The JMXManagementPlugin implementation saves the handler argument in a local variable and passes it to the
JMXRMIConnector constructor when the JMX communication channel is create. The callback method is ultimately
referenced by the JMXAuthenticatorImpl class which calls its hasManagementPermission method to authenticate
the user. For details concerning the JMXAuthenticator class and related management classes and methods, refer to
the javax.management.remote documentation.
package com.mycompany.xx.integration.jmx;
import java.util.HashMap;
import java.util.Map;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;
try {
// *** Start an RMI connector for the JMX server
// Note: An RMI connector is optional. If not desired, specify a negative RMI port
// number in the RMI URL so the connector will not be started.
// Note: The RMI connector does not work on JBoss 6.1.1. For JBoss 6.1.1, it is
// recommended that the rmiPort be set to a negative number so the connector will not
// be started.
// The environment may contain the user's credentials and desired other information
Map environment = new HashMap();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.rmi.registry.RegistryContextFactory");
environment.put(Context.PROVIDER_URL, "rmi://localhost:1099");
String[] credentials = new String[]{"su", "cc"};
environment.put(JMXConnector.CREDENTIALS, credentials);
Plugins are software modules that PolicyCenter calls to perform an action or calculate a result. This topic describes
plugin interfaces that are not discussed in detail elsewhere in this documentation.
Credentials plugin
The CredentialsPlugin provides a secure way to retrieve the user name and password for user authentication to
gain access to an external system.
This plugin is located at configuration→config→Plugins→registry→CredentialsPlugin.
The CredentialsPlugin is called by the static getCredentialsFromPlugin method in the CredentialsUtil
class.
The key argument references the relevant user name and password credentials.
The plugin provides a retrieveUsernameAndPassword method.
The method returns a UsernamePasswordPairBase object that contains the retrieved user’s name in its Username
field and the password in the Password field.
<?xml version="1.0"?>
<tns:CredentialsArray xmlns:tns="http://guidewire.com/credentials">
<tns:CredentialsElem key="AcmeWebService">
<username>John Doe</username>
<password>JohnsSecurePassword</password>
</tns:CredentialsElem>
<tns:CredentialsElem key="AcmeFinanceIntegration">
<username>Jane Doe</username>
<password>JanesSecurePassword</password>
</tns:CredentialsElem>
</tns:CredentialsArray>
The base configuration includes an implementation of the Encryption plugin that demonstrates techniques for
processing encrypted credentials files. The Gosu PBEEncryptionPlugin class implements the IEncryption
interface and demonstrates the processing of a credentials file encrypted by the group of javax.crypto.spec.PBE*
classes.
In Gosu code, the PreUpdateContext object includes properties that contain lists of added, modified, and deleted
objects in the current bundle.
InsertedBeans
An unordered list of added objects
UpdatedBeans
An unordered list of modified objects
RemovedBeans
An unordered list of deleted objects
In Java code, the argument's list properties can be retrieved by calling the methods getInsertedBeans,
getUpdatedBeans, and getRemovedBeans.
The executePreUpdate method has no return value.
The method accepts a bean argument that references the object to be processed by the existing preupdate rule set.
The object must be a valid instance of an entity. If no preupdate rule exists for the object, the object remains
unchanged.
The executePreUpdateRules method can be called at any time. Its use is not restricted to the IPreUpdateHandler
plugin.
The method has no return value.
Validation plugin
The Validation plugin enables validation operations to be performed on a Validatable object. The plugin is
typically called to run a validation rule set.
The gw.plugin.validation.IValidationPlugin interface defines the following single method for the plugin.
validate(bean : Validatable)
The bean argument specifies the object to validate. The method has no return value.
The base configuration does not implement the Validation plugin. You can provide custom code to implement the
plugin and then register it by using the standard procedure.
Other plugin interfaces 259
Guidewire PolicyCenter 9.0.6 Integration Guide
Sending emails
To send emails, define an email message destination and configure the emailMessageTransport plugin.
Parameter Description
CredentialsPlugin.Key Optional. String key value stored in the Credentials plugin. If this parameter is specified and the
Credentials plugin is enabled, the user name and password values to use in an SSL authenticat‐
ed login are retrieved from the plugin. The plugin's properties can be encrypted, which enables
secure user and password strings.
Default: EmailMessageTransport
Debug Optional. Boolean value to enable debugging output from the email host.
Default: false
defaultSenderAddress Default From email address to use for outbound email. For example, jdoe@mymail.com.
The defaultSenderAddress and defaultSenderName parameter values are used if both the
Sender and Sender.EmailAddress properties are not specified in the Email object.
defaultSenderName Default sender's name to use for outbound email. For example, John Doe.
mail.* Optional. Specifies various mail.* properties.
Properties recognized in the base configuration are listed below. Additional mail.* properties
can be recognized by writing configuration code.
mail.smtp.host
The SMTP email application that sends emails.
mail.smtp.port
The SMTP port number.
mail.transport.protocol
The required protocol. The default value is "smtp".
If any mail.* parameters are specified, the values specified in the smtpHost and smtpPort pa‐
rameters are ignored.
If no mail.* parameters are specified and a password is specified, either in the Password param‐
eter or retrieved from the Credentials plugin, the following properties and values are defined.
mail.smtp.auth
Set to true.
mail.smtp.ssl.enable
Set to true.
To support the TLS security standard, set the following mail.* parameters:
mail.smtp.auth
Set to true.
mail.smtp.starttls.enable
Set to true.
mail.smtp.host
The SMTP email application that sends emails
mail.smtp.port
The SMTP port number
Also set the Username, Password, defaultSenderName, and defaultSenderAddress to appropri‐
ate values for your TLS requirements.
Password Optional. Login password.
The Password parameter is plain text and not secure. It is recommended to specify user name
and password values in encrypted properties in the Credentials plugin. See the
CredentialsPlugin.Key parameter.
Default: Not specified
smtpHost Name of the SMTP email application that sends emails.
If any mail.* parameters are specified, the smtpHost parameter is ignored.
smtpPort SMTP email port.
If any mail.* parameters are specified, the smtpPort parameter is ignored.
Default: 25 for non‐authenticated logins; 465 for authenticated logins. See the Password param‐
eter.
useDefaultAsSender Optional. Boolean value indicating whether to use the defaultSenderName and
defaultSenderAddress parameters to identify the email sender. If true, the parameter values
are used even if the email explicitly specifies a sender and address.
Parameter Description
Default: false
useMessageCreatorAsUser Optional. Boolean value to specify on whose behalf to retrieve a document attached to the
email. Possible personas are either the user who generated the email (true) or the system user
(false).
Default: false
Username Optional. Login user name.
The Username parameter is plain text and not secure. It is recommended to specify user name
and password values in encrypted properties in the Credentials plugin. See the
CredentialsPlugin.Key parameter.
Default: Not specified
IEmailTemplateSource plugin
The IEmailTemplateSource plugin template enables PolicyCenter to retrieve one or more email templates. To see
the plugin registry, navigate in the Project window to
configuration→config→Plugins→registry→IEmailTemplateSource.gwp.
The base configuration provides a demonstration plugin implementation class,
gw.plugin.email.impl.LocalEmailTemplateSource, that is registered in IEmailTemplateSource.gwp. The
LocalEmailTemplateSource class constructs an email template from files stored on the local file system. As a
result, the sample implementation is for demonstration purposes and is unsuitable for use in a clustered environment.
The class's getEmailTemplates method searches for an email template.
Parameter Description
locale Locale to search for. The argument can be null.
If locale is not null, the search is performed in the resource→emailtemplates folder for a subdirectory whose
name matches the specified locale value. A match is tested in the following order.
• Language + Country + Variant
• Language + Country
• Language
• Default language as specified in the config.xml configuration parameter
DefaultApplicationLanguage.
valuesToMatch Keys to match include topic, name, keywords, and availablesymbols. The availablesymbols key is
matched against the template's requiredsymbols.
The method returns an array of zero or more IEmailTemplateDescriptor objects that match the locale and
specified values to match. If no matches are found, the returned array is empty.
The load balancer would not typically parse the HTML enough to know about this problem, so the base URL at the
user starts with http instead of https. This breaks image loading and display because the browser tries to load the
images relative to the http URL. The load balancer rejects the requests because they are insecure because they do
not use HTTPS/SSL.
Avoid this problem by writing a custom IBaseURLBuilder base URL builder plugin and registering it with the
system.
You can base your implementation on the built-in example implementation found at the following path.
PolicyCenter/java-api/examples/src/examples/plugins/baseurlbuilder
To handle the load balancer case mentioned earlier, the base URL builder plugin can look at the HTTP request’s
header. If a property that you designate exists to indicate that the request came from the load balancer, return a base
URL with the prefix https instead of http.
The built-in plugin implementation provides a parameter FqdnForUrlRewrite which is not set by default. If you
enable browser-side integration features, you must specify this parameter to rewrite the URL for the external fully
qualified domain name (FQDN). The JavaScript security model prevents access across different domains. Therefore,
if PolicyCenter and other third-party applications are installed on different hosts, the URLs must contain fully
qualified domain names. The fully qualified domain name must be in the same domain. If the FqdnForUrlRewrite
parameter is not set, the end user is responsible for entering a URL with a fully qualified domain name.
There is another parameter called auto which tries to auto-configure the domain name. This setting is not
recommended for clustering environments. For example, do not use this if the web server and application server are
not on the same machine, or if multiple virtual hosts live in the same machine. In these cases, it is unlikely for the
plugin to figure out the fully qualified domain name automatically.
In Project window in Studio, navigate to configuration→config→Plugins→registry and the open IBaseURLBuilder. Add the
parameter FqdnForUrlRewrite with the value of your domain name, such as "mycompany.com". The domain name
must specify the Fully Qualified Domain Name to be enforced in the URL. If the value is set to "auto", the default
plugin implementation makes the best effort to calculate the server FQDN from the underlying configuration.
If PolicyCenter generates HTML pages, it typically generates a base URL for the HTML page using a tag such as
<base href="..."> at the top of the page. In almost all cases, PolicyCenter generates the most appropriate base
URL, based on settings in config.xml.
In some cases, this behavior is inappropriate. For example, suppose you hide PolicyCenter behind a load balancing
router that handles Secure Socket Layer (SSL) communication. In such a case, the external URL would include the
prefix https://. The load balancer handles security and forwards a non-secure HTTP request to PolicyCenter with
a URL prefix http://. The default implementation of the base URL includes the URL prefix http://.
The load balancer would not typically parse the HTML enough to know about this problem, so the base URL starts
with http instead of https. This breaks image loading and image display because the browser tries to load the
images relative to the http URL. The load balancer rejects the insecure requests because they do not use HTTPS/
SSL.
This situation can be avoided by writing a custom plugin that creates an appropriate base URL. Requests that
originate from the load balancer can then be forced to return a base URL with a scheme of https instead of http.
The custom plugin implements the IBaseURLBuilder interface and is enabled by registering it with PolicyCenter.
The custom plugin must implement the IBaseURLBuilder methods described in the following sections.
Method: getApplicationBaseURL
The request argument must specify the desired scheme, server port, server name, and context path for the web
application. The scheme is a String, typically http or https. If the scheme is not specified, http is used by
default. The server name can be either a name or IP address of the server. The port can be omitted if either of the
following conditions exists.
• The scheme is http and the port is 80.
• The scheme is https and the port is 443.
Other plugin interfaces 263
Guidewire PolicyCenter 9.0.6 Integration Guide
The method uses the request argument fields to construct and return a String containing the base URL of the web
application, such as http://servername:8080/webapp.
Method: getPageBaseURL
The request argument must specify the desired scheme, server port, server name, and request URI for the HTML
page. The scheme, server port, and server name fields are processed in the same manner as in the
getApplicationBaseURL method.
The method uses the request argument fields to construct and return a String containing the base URI of the
relevant HTML page, such as http://servername:8080/webapp/path/SomePage.jsp.
An example implementation of the IBaseURLBuilder plugin is provided in the source file shown below. The source
file is created as part of the operation of generating the Java API libraries and then unzipping the resulting
PolicyCenter/java-api/java-examples.zip file.
PolicyCenter/java-api/examples/src/examples/pl/plugins/baseurlbuilder/ExampleBaseURLBuilder.java
To enable the custom plugin, it must be registered with PolicyCenter. In the Studio Project window, navigate to
configuration→config→plugin→registry. Right-click registry and select New→Plugin.
IMPORTANT If you change the value of parsingExtensionLength and you are using Solr, also set
the parsingExtensionLength field on the phone number analyzer defined in the Solr schema.xml
file, as described in the following code sample.
For example, in Guidewire Studio, navigate in the Project window to configuration→config→solr→policy and open
schema.xml. If you set parsingExtensionLength to 10 for IPhoneNormalizerPlugin, set
parsingExtensionLength as follows in the solr.TextField field type named gw_phone:
</analyzer>
</fieldType>
See also
•
var d = gw.api.util.DateUtil.CurrentDate
For Gosu configuration code to be compatible with the testing clock, it must always get the date with
gw.api.util.DateUtil.CurrentDate rather than other APIs. For example, the standard Java class
java.util.Date method will return the actual server time and not the PolicyCenter time.
Certain areas in PolicyCenter are not affected by the modified time.
• The time shown in the next scheduled run for batch processes
• Today’s date on the Calendar user interface
266 chapter 15: Other plugin interfaces
Guidewire PolicyCenter 9.0.6 Integration Guide
com.guidewire.pl.plugin.system.internal.OffsetTestingClock
4. To advance the clock using a picker, type Alt+Shift+T, and then click the Internal Tools tab. In the sidebar,
click Testing System Clock. Set the clock as needed by clicking one of the Add buttons or entering a specific date
and time. Finally, click Change Date.
5. Start up the other servers.
2. Advance the testing clock. If you wrote your own implementation, do whatever is necessary to work with your
own private implementation. For example, you might make SQL modifications of some parameter or adjust
some offset encoded in a configuration file.
3. Restart all servers in the cluster.
Startable plugins
A startable plugin is custom code that begins executing when a particular server run level is reached during server
startup.
A Singleton startable plugin must explicitly specify its server run level in an @Availability annotation. A
Singleton startable plugin can begin executing at either the DAEMONS or MULTIUSER server run levels.
The following example code defines a Singleton startable plugin that begins executing at the MULTIUSER run level.
uses gw.api.server.Availability
uses gw.api.server.AvailabilityLevel
@Availability(AvailabilityLevel.MULTIUSER)
class HelloWorldStartablePlugin implements IStartablePlugin {
...
}
Whenever a Singleton plugin is started on a server that is not clustered, the plugin is started synchronously when the
relevant server run level is reached. A Singleton plugin on a clustered server is started asynchronously, which results
in the possibility that the plugin will start slightly after the relevant server run level is reached.
For a startable plugin running on a clustered server, certain events, such as a load balancing request or a failure, can
cause it to be spontaneously moved around the cluster. During this time, the plugin can become temporarily
unavailable.
See also
• For information on using a web service to start and stop startable plugins, see “Stopping startable plugins using
web services” on page 100.
270 chapter 16: Startable plugins
Guidewire PolicyCenter 9.0.6 Integration Guide
// private variables...
var _state = StartablePluginState.Stopped;
...
Alternatively, combine the variable definition with the shortcut keyword to simplify your code. You can combine
the property definition with the variable definition in a single code statement.
The plugin includes a constructor which is called on system startup. However, locate the service code in the plugin’s
start method, not its constructor.
The start method must initialize the plugin’s State property by using an internal variable defined in the plugin.
The variable’s value must be one of the supported values of the StartablePluginState class, such as Started or
Stopped.
The start method can also start any desired listener code or threads, such as a JMS queue listener.
The start method accepts an argument that references a callback handler of type
StartablePluginCallbackHandler. This callback is important if the startable plugin modifies any entity data,
which most startable plugins do.
Any plugin code that affects entity data must be run within a method called execute. The execute method accepts
an argument of a special type of in-line function called a Gosu block, which is described in the Gosu Reference
Guide. The Gosu block itself accepts no arguments. The execute method is then passed to the callback handler.
If you do not need a user context, use the simplest version of the callback handler method execute, whose one
argument is the Gosu block.
You do not need to create a separate bundle. If you create new entities to the current bundle, they are in the correct
default database transaction the application sets up for you. Use the code returned by the Transaction.getCurrent
method to get the current bundle if you need a reference to the current writable bundle.
The Java language does not directly support blocks. If you implement your plugin in Java, you cannot use a Gosu
block but you can use an anonymous class to do the same thing.
The plugin’s start method also includes a boolean variable that indicates whether the server is starting. If true, the
server is starting up. If false, the start request comes from the Startable Services user interface.
The following shows a simple Gosu block that changes entity data. This example assumes your listener defined a
variable messageBody with information from your remote system. If you get entities from a database query,
remember to add them to the current bundle.
The following example queries all User entities and sets a property on results of the query.
...
for (e in q.select()) {
// add entity instance to writable bundle, then save and only modify that result
var writable_object = bundle.add(e)
})
//Note: You do not need to commit the bundle here. The execute method commits after your block runs.
}
Note that to make an entity instance writable, save and use the return result of the bundle add method.
Just like your start method must set your internal variable that sets its state to started, your stop method must set
your internal state variable to StartablePluginState.Stopped. Additionally, stop whatever background processes
or listeners you started in your start method. For example, if your start method creates a new JMS queue listener,
your stop method destroys the listener. Similar to the start method’s isStartingUp parameter, the stop method
includes a boolean variable that indicates whether the server is shutting down now. If true, the server is shutting
down. If false, the stop request comes from the Startable Services user interface.
For the second method argument to runWithNewBundle, pass either a User entity or a String that is the user name.
package gw.api.startableplugin
uses gw.api.startable.IStartablePlugin
uses gw.api.startable.StartablePluginCallbackHandler
uses gw.api.startable.StartablePluginState
uses gw.api.server.Availability
uses gw.api.server.AvailabilityLevel
@Availability(AvailabilityLevel.MULTIUSER)
class HelloWorldStartablePlugin implements IStartablePlugin
{
var _state = StartablePluginState.Stopped;
var _callback : StartablePluginCallbackHandler;
construct()
{
}
package gw.api.startableplugin
uses gw.api.startable.IStartablePlugin
uses gw.api.startable.StartablePluginCallbackHandler
uses gw.api.startable.StartablePluginState
uses gw.transaction.Transaction
uses java.lang.Thread
@Distributed
class HelloWorldDistributedStartablePlugin implements IStartablePlugin {
var _state : StartablePluginState
var _startedHowManyTimes = 0
var _callback : StartablePluginCallbackHandler
var _thread : Thread
// Is server starting?
if (serverStartup) {
// Plugin is starting, too
_state = _callback.getState(Started)
// Log event
if (_state == Started) {
_callback.logStart("HelloWorldDistributedStartablePlugin:Started")
} else {
_callback.logStart("HelloWorldDistributedStartablePlugin:Stopped")
}
} else {
// Plugin start/stop state has changed
_state = Started
if (_callback.State != Started) {
changeState(Started) // Update saved start/stop state
}
_callback.logStart("HelloWorldDistributedStartablePlugin")
}
if (_callback != null) {
if (serverStopping) {
if (_state == Started) {
_callback.logStop("HelloWorldDistributedStartablePlugin:Started")
} else {
_callback.logStop("HelloWorldDistributedStartablePlugin:Stopped")
}
_callback = null
} else {
if (_callback.State != Stopped) {
changeState(Stopped) // Update saved start/stop state
}
_callback.logStop("HelloWorldDistributedStartablePlugin")
}
}
_state = Stopped
// Internal function to set the database state. If an exception occurs, retries 5 times.
private function changeState(newState : StartablePluginState) {
var tryCount = 0
while (_callback.State != newState && tryCount < 5) {
try {
Transaction.runWithNewBundle(\ bundle -> { _callback.setState(bundle, newState)},
User.util.UnrestrictedUser)
}
catch (e : java.lang.Exception) {
tryCount++
_callback.log(this.IntrinsicType.Name + " on attempt " + tryCount +
" caught " + (typeof e).Name + ": " + e.Message)
}
}
}
}
However, the Java language does not directly support blocks. If you implement your plugin in Java, you cannot use
a Gosu block. However, instead you can use an anonymous class.
From Java, the method signatures for the execute methods (there are multiple variants) take a GWRunnable for the
block argument. GWRunnable is a simple interface that contains a single method, called run. Instead of using a block,
you can define an in-line anonymous Java class that implements the run method. This is analogous to the standard
Java design pattern for creating an anonymous class to use the standard class java.lang.Runnable.
_callbackHandler.execute(myBlock);
PolicyCenter provides a plugin interface that supports high performance multi-threaded processing of inbound
requests. PolicyCenter includes default implementations for the most common usages: reading text file data and
receiving JMS messages.
You might not need to write your own implementation of these main plugin interfaces. PolicyCenter includes plugin
implementations that are supported for production servers that support common use cases. Both are provided in
variants for message reply and startable plugin use.
You can implement your plugin code using either Gosu, Java with no OSGi, or Java as an OSGi bundle. If you use
Java or if you require third-party libraries, Guidewire recommends implementing your code as an OSGi plugin.
In all cases, you must register and configure plugin implementations in the Studio Plugins Registry. See each topic
for more information about which implementation classes to register. Additionally, for file and JMS integrations,
you write handler classes.
When registering a plugin implementation in the Plugins Registry, you must add a plugin parameter called
integrationservice. That integrationservice parameter defines how PolicyCenter finds configuration
information within the inbound integration configuration XML file.
If you use either the file or the JMS variant of the startable plugin, your class must implement the
InboundIntegrationHandlerPlugin interface. This interface specifies only the process method.
If you use either the file or the JMS variant of the message reply plugin, your class must implement the
InboundIntegrationMessageReplyHandler interface, which is a subinterface of
InboundIntegrationHandlerPlugin. Implement the process method and all methods of the MessageReply
plugin, which are initTools, suspend, shutdown, resume, and setDestinationID. Save the parameters to your
initTools method into private variables. Use those private variables during your process method to find and
acknowledge the original Message object.
See also
• “Custom inbound integrations” on page 287
• “Registering a plugin implementation class” on page 136
See also
• “Thread pool configuration” on page 279
• “Inbound integration XML elements” on page 280
• “Registering a plugin implementation class” on page 136
The name attribute is a symbolic name that is used later in the XML file to refer uniquely to this thread pool.
The disabled attribute is a Boolean value that defines whether to disable that thread pool. If set to true, the thread
pool is disabled.
The <threadpool> element supports the following element types for setting thread pool parameters.
• <gwthreadpooltype> – The thread pool type with the following supported values.
◦ Set to FORKJOIN for a self-managing default thread pool.
◦ Set to COMMONJ for running WebSphere or WebLogic and defining the JNDI name of the thread pool. If you set
this value, you must also set the <workmanagerjndi> parameter.
• <workmanagerjndi> – JNDI name of the thread pool. This parameter is required if the thread pool type is set to
COMMONJ.
The base configuration provides definitions for WebSphere or WebLogic thread pools that use default attribute
values. These definitions are for development use only and must not be used in a production environment. For best
performance, create your own custom thread pool with a unique name and tune that thread pool for the specific work
you need, such as your JMS work. Then, update the <threadpool> settings to include the JNDI name for your new
thread pool.
<file-integration>
File inbound integration
<jms-integration>
JMS inbound integration
<custom-integration>
Custom inbound integration, directly implementing the InboundIntegrationStartablePlugin or
InboundIntegrationMessageReply interface
280 chapter 17: Multi‐threaded inbound integration
Guidewire PolicyCenter 9.0.6 Integration Guide
disabled boolean false Determines whether to disable this inbound integration. Set to true to disable the
inbound integration.
env string Sets a configuration that is valid only for a specific server environment.
The abstract inbound integration XML element has the following subelements, in the order shown.
processing string • The full path of the configured processing events directory.
error string • The full path of the configured error events directory.
done string • The full path of the configured done events directory.
charset string UTF‐8 The character set that the inbound file uses.
createdirectories string false If true, PolicyCenter creates the incoming, processing, error, and done di‐
rectories if they do not already exist. If errors that prevent creation of any
directories, the server does not start.
If false, PolicyCenter requires that all of these directories must already ex‐
ist. If any directories do not already exist, the server does not start.
For better security, set to false.
messagereceivetimeout string 15 The maximum time in seconds to wait for an individual JMS message.
3. The inbound file integration code moves all found files to the processing directory, which stores inbound files
in progress.
4. The inbound file integration code opens each new file using a specified character set. The default is UTF-8,
but it is configurable.
5. The inbound file integration code reads one unit of work (one chunk of data) and dispatches it to your handler
code. The processingmode parameter in the inbound-integration-config.xml file defines the type of data
processed in one unit of work. If that parameter has the value line, PolicyCenter sends one line at a time to
the handler as a String object. If that parameter has the value file, PolicyCenter sends the entire file to the
handler as a java.nio.file.Path object.
If an exception occurs during processing, the plugin code moves the file to the error directory. The value of the
stoponerror parameter does not affect this behavior. The file name is changed to add a prefix that includes
the time of the error, as expressed in milliseconds as returned from the Java time utilities. For example, if the
file name ABC.txt has an error, it is renamed in the error directory with a name similar to
1864733246512.error.ABC.txt.
To retry a failed inbound file, the inbound file integration code moves the file from the error directory back
into the incoming directory for reprocessing.
6. After successfully reading and processing the complete file, the inbound file integration code moves the file to
the done directory.
7. If there were any other files detected in this polling interval in Step 2, the inbound file integration code repeats
the process at Step 4. Optionally, you can set the integration to operate on the most recent batch of files in
parallel. For related information, see the ordered parameter, mentioned later in this section.
8. The inbound file integration waits until the next polling interval, and repeats this process starting at Step 3.
Procedure
1. In the Project window, navigate to configuration→config→integration, and open the file inbound-integration-
config.xml.
2. Configure the thread pools.
3. In the list of integrations, create one <integration> element of type <file-integration>. Follow the
pattern in the file to set the XML element namespace. In the base configuration, type the element name as
<cii:file-integration>.
4. Set configuration parameter subelements.
5. In Studio, within the Plugins registry, add a new .gwp file.
6. Studio prompts for a plugin name and plugin interface. For the plugin name, use a name that represents the
purpose of this specific inbound integration. For the Interface field, enter one of the following values.
• For a message reply plugin, type InboundIntegrationMessageReply.
• For a startable plugin for non-messaging use, type InboundIntegrationStartablePlugin.
7. Click the plus (+) symbol to add a plugin implementation and choose Add Java plugin.
8. In the Java class field, enter one of the following plugin types.
• For a message reply plugin, type
com.guidewire.pl.integration.inbound.file.DefaultFileInboundIntegrationMessageReply.
• For a startable plugin for non-messaging use, type
com.guidewire.pl.integration.inbound.file.DefaultFileInboundIntegrationPlugin.
9. Add a plugin parameter with the key integrationservice. For the value, type the unique name for your
integration that you used in inbound-integration-config.xml for this integration.
284 chapter 17: Multi‐threaded inbound integration
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• “Inbound integration handlers for file and JMS integrations” on page 278
• “Inbound integration XML elements” on page 280
The following example implements a SimpleFileIntegration handler class to print the lines in the file.
package mycompany.integration
uses gw.plugin.integration.inbound.InboundIntegrationHandlerPlugin
The example has two plugin implementations registered in the Plugins registry.
• InboundFileIntegrationStartable.gwp – Registers an implementation of
InboundIntegrationStartablePlugin with the Java class
com.guidewire.pl.integration.inbound.file.DefaultFileInboundIntegrationPlugin. The
integrationservice plugin parameter is set to exampleFileIntegration.
• InboundFileIntegrationHandler.gwp – Registers an implementation of InboundIntegrationHandlerPlugin
with the Gosu class SimpleFileIntegration. The integrationservice plugin parameter is set to
exampleFileIntegration.
When you start up the server, you will see the log line in the console for start up.
Add files to the /tmp/incoming directory. You will see additional lines for each processed line.
See also
• “Using the inbound integration polling and throttle intervals” on page 283
Procedure
1. In the Project window, navigate to configuration→config→integration, and then open the inbound-integration-
config.xml file.
2. Configure the thread pools.
3. In the list of integrations, create one <integration> element of type <jms-integration>. Follow the pattern
in the file to set the XML element namespace. In the base configuration, type the element name as <cii:jms-
integration>.
4. Set configuration parameter subelements.
286 chapter 17: Multi‐threaded inbound integration
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• “Inbound integration handlers for file and JMS integrations” on page 278
• “Inbound integration XML elements” on page 280
You use the following classes to find and prepare work during each polling interval.
A work set WorkSetProcessor in package An object that knows how to acquire and divide resour‐
processor gw.api.integration.inbound.work ces. Instantiates your class that implements the interface
If your plugin supports the optional feature of being Inbound.
transactional, implement the subinterface The main method for processing one unit of work within a
TransactionalWorkSetProcessor WorkData object is the process method within this object.
Inbound Inbound in package A class that knows how to find work in its findWork meth‐
gw.api.integration.inbound.work od and return new work data sets. Instantiates your class
that implements the interface WorkDataSet.
The java.util.Map object that is the method argument is the set of plugin parameters from the Studio Plugins
Editor for your plugin implementation.
Implement the teardown method to release resources acquired in the start method. PolicyCenter calls the
teardown method before the stop method.
import gw.api.integration.inbound.CustomWorkAgent;
import gw.api.server.Availability;
import gw.api.server.AvailabilityLevel;
import gw.api.startable.IStartablePlugin;
import gw.api.startable.StartablePluginCallbackHandler;
import gw.api.startable.StartablePluginState;
@Availability(AvailabilityLevel.MULTIUSER)
public class CustomStartableInboundIntegration implements IStartablePlugin {
private String _name = "exampleCustomIntegration";
...
must implement to begin work, commit work, and roll back transactional changes to partially finished work. To
specify that your work agent is transactional, return true from the transactional method. Otherwise, return
false.
If your work agent is transactional, your implementation of the Factory.createWorkUnit method must return an
instance of TransactionalWorkSetProcessor instead of WorkSetProcessor. The
TransactionalWorkSetProcessor interface extends WorkSetProcessor.
See also
• “Using the inbound integration polling and throttle intervals” on page 283
Procedure
1. In the Project window, navigate to configuration→config→integration, and open the file inbound-integration-
config.xml.
2. Configure the thread pools.
3. In the list of integrations, create one <integration> element of type <custom-integration>. Follow the
pattern in the file to set the XML element namespace. In the base configuration, type the element name as
<cii:custom-integration>.
4. Set configuration parameter subelements.
5. In Studio, within the Plugins registry, add a new .gwp file.
6. Studio prompts for a plugin name and plugin interface. For the name, use a name that represents the purpose
of this specific inbound integration. For the Interface field, enter one of the following values.
• For a message reply plugin, type InboundIntegrationMessageReply.
• For a startable plugin for non-messaging use, type InboundIntegrationStartablePlugin.
7. Click the plus (+) symbol to add a plugin implementation and choose Add Gosu plugin or Add Java plugin.
8. In the Java class field, type the fully-qualified name of your plugin implementation.
9. Add a plugin parameter with the key integrationservice. For the value, type the unique name for your
integration that you used in inbound-integration-config.xml for this integration.
10. Start the server and test your new inbound integration. Add logging code as appropriate to confirm the
integration.
See also
• “Inbound integration XML elements” on page 280
Messaging
Guidewire PolicyCenter 9.0.6 Integration Guide
chapter 18
You can send messages to external systems after something changes in PolicyCenter, such as a changed policy. The
changes trigger events, which trigger your code that sends messages to external systems. For example, if you submit
a new policy, your messaging code notifies a billing system about the new policy.
PolicyCenter defines a large number of events of potential interest to external systems. In response to events of
interest, rules can be written to generate messages intended for external systems. PolicyCenter queues the messages
and then dispatches them to the appropriate external systems.
This topic explains how PolicyCenter generates messages in response to events and how to connect external systems
to receive those messages.
Overview of messaging
The following topics summarize important messaging concepts.
Event
An event is an abstract notification of a change in PolicyCenter that might be interesting to an external system. An
event most often represents a user action to application data, or an API that changed application data. Entity types
defined with the <events> tag trigger an event if a user action or API adds, changes, or removes data associated
with an instance of the entity. Each event is identified by a String name.
For example, in PolicyCenter a new policy submission triggers an event. The event name is "IssueSubmitted".
A single user action or API call might trigger multiple events for different objects in a single database transaction.
When an event is triggered, a call is made to the Event Fired rule set for each message destination registered to
process the event. The rule set performs the operations necessary to process the event, which can include sending a
message to an external system.
Message
A message is information to send to an external system in response to an event. Messages are created while
executing the Event Fired rule set that is called in response to the triggering of a particular event. PolicyCenter can
ignore the event or send one or more messages to each external system that cares about that event. Each message
includes a message payload that contains the content of the message. The message payload is a String stored in the
Message.Payload property.
Messaging and events 295
Guidewire PolicyCenter 9.0.6 Integration Guide
Message history
After a message is sent, the application converts a Message object to a MessageHistory object. MessageHistory
objects are saved in a database table. The database table can be used to detect duplicate messages and also to track
and understand the messaging history of external systems.
Messaging destinations
A messaging destination is an external system to send messages to.
Generally speaking, a messaging destination represents a single external system. Register a destination for each
external system, even if the system is used for multiple types of data.
Messaging destinations are registered in Studio.
Each destination can register a list of event names for which it wishes to receive notifications. The Event Fired rule
set runs once for every combination of an event and a destination interested in that event. An Event Fired rule can
determine the destination for a particular triggered event by examining the DestinationID property of the message
context object.
Root object
A root object for an event is the entity instance that is most associated with the event. This might be the primary
entity that is the top of a hierarchy of objects, or it might a small subobject.
Separate from the concept of a root object for an event, each message has a root object. By default, the message’s
root object is the same as the root object for the event that triggered the Event Fired rules within which you created
the message. This default makes sense in most cases. You can override this default for a message if desired.
Acknowledgment
An acknowledgment is a formal response from an external system to PolicyCenter that declares whether the system
successfully processed the message.
• A positive ACK acknowledgment means the external system processed the message successfully.
• A negative NAK acknowledgment means the external system failed to handle the message for some reason.
PolicyCenter distinguishes between the following types of errors.
• An error that throws an exception during the initial sending of the message. Such an error typically indicates a
network problem or other retryable issue. PolicyCenter will try multiple times to resend the message.
• A NAK error reported from the external system. PolicyCenter does not resend a message that receives a NAK
error.
Safe ordering
Safe ordering is a messaging feature with the following characteristics.
• For each messaging destination, messages are grouped based on their associated primary object.
• In each group, the message’s sending order is determined by its time of creation—from the oldest message to the
most recent.
• A single message from a group is sent and acknowledged before sending the group’s next ordered message.
For example, the default primary entity in PolicyCenter is the Account. Accordingly, messages are grouped based
on their associated Account object. However, if a messaging destination sets Contact as its alternative primary
entity, then the messages for the destination are grouped based on their associated Contact object. A destination’s
alternative primary object is set in the Messaging editor.
Messages associated with objects other that the primary object are processed as non-safe-ordered messages. In the
Messaging editor, non-safe-ordered messages are referred to as Messages Without Primary. The logic of how and when
to send non-safe-ordered messages differs from that of safe-ordered messages. The behavior can also vary based on
the destination’s Strict Mode setting.
Transport neutrality
PolicyCenter does not assume any specific type of transport or message formatting.
Destinations deliver the message any way they want, including but not limited to the following methods.
• Submit the message by using remote API calls – Use a SOAP web service interface or a Java-specific interface to
send a message to an external system.
• Submit the message to a guaranteed-delivery messaging system, such as a message queue.
• Save to special files in the file system – For large-scale batch handling, you could send a message by
implementing writing data to local text files that are read by nightly batch processes. If you do this, remember to
make your plugins thread-safe when writing to the files.
• Send e-mails – The destination might send e-mails, which might not guarantee delivery or order, depending on
the type of mail system. This approach is acceptable for simple administrative notifications but is inappropriate
for systems that rely on guaranteed delivery and message order, which includes most real-world installations.
3. Event Fired rule set is executed – PolicyCenter runs the appropriate Event Fired rule set for each message
destination defined for the event. triggers. A rule set can choose to generate new messages. Messages have a
text-based message payload.
For example, you might write rules that check if the event name is IssueSubmission. When such an event is
identified, the rules might generate a message with an XML payload that describes information about the
submission.
4. PolicyCenter sends message to a destination – Messages are put in a queue and handed one-by-one to the
messaging destination.
In PolicyCenter, a message destination representing an external policy management system might take the
XML payload and submit the message to a message queue. The message might notify the external system
about a submission.
5. PolicyCenter waits for an acknowledgment – The external system replies with an acknowledgment to the
destination after it processes the message, and the destination’s messaging plugins process this information. If
the message was successfully sent, the messaging plugins submit an ACK, and PolicyCenter sends the next
message.
Messaging integration code is contained in Event Fired rule sets and MessageTransport plugin implementations.
After a messaging plugin implementation class is written, it is registered in Studio. Register the messaging plugin
implementation first in the Plugins editor and then in the Messaging editor. For plugin interfaces that can have
multiple implementations, such as all messaging plugin interfaces, Studio asks you to name the plugin
implementation when registering the plugin class. Use the plugin implementation’s class name when configuring the
messaging destination in the Messaging editor.
Messaging Overview
Application starts
You can use a technique called late binding to include parameters in a message payload at message creation
time, but evaluate them immediately before sending.
5. New messages are added to the send queue.
After all rules run, PolicyCenter adds any new messages to the send queue in the database. Atomically, the
submission of messages to the send queue is part of the same database transaction that triggered the event.
• If all related messages successfully enter the send queue, the transaction succeeds.
• If any operation in the transaction fails, the entire transaction rolls back, including all messages added
during the transaction.
The Message Creation phase ends after all messages for the event have been added to the send queue. At this
point, the Message Send phase begins.
The length of time that a message might wait in the send queue is dependent on the state of acknowledgments
and the status of safe ordering of other message.
6. On servers with the messaging server role, PolicyCenter dispatches messages to messaging destinations.
PolicyCenter retrieves messages from the send queue and dispatches messages to messaging plugins for each
destination.
To send a message, PolicyCenter finds the messaging destination’s transport plugin and calls its send method.
The message transport plugin sends the message in whatever native transport layer is appropriate.
If the send method throws an exception, PolicyCenter automatically retries the message.
7. Acknowledging messages.
Some destination implementations detect success or failure immediately during sending. For example, a
messaging transport plugin might call a synchronous remote procedure call on a destination system before
returning from its send method.
In contrast, a messaging destination might need to wait for an asynchronous, time-delayed reply from the
destination to confirm that it processed the message successfully. For example, it might need to wait for an
incoming message on an external messaging queue that confirms the system processed the message.
In either case, the messaging destination code or the external system must confirm that the message arrived
safely by submitting an acknowledgment (ACK) to PolicyCenter. Alternatively, it can submit an error, also
called a negative acknowledgment (NAK).
You can submit an ACK or NAK in several places.
• For synchronous sending, submit it in your MesssageTransport plugin during the send method.
• For asynchronous sending, submit it in your MessageReply plugin. For asynchronous sending, an external
system could optionally use a SOAP API to submit an acknowledgment or error.
If using messaging plugins to submit the ACK, you can also make limited changes to data during the ACK,
such as updating properties on entities. Also, where appropriate, you could advance a workflow.
8. After an ACK or NAK for a safe-ordered message, PolicyCenter dispatches the next related message.
An ACK for a safe-ordered message affects what messages are now sendable. If there are other messages for
that destination in the send queue for the same primary object, PolicyCenter soon sends the next message for
that primary object.
The Message Send phase of the messaging process ends after all messages for an event have been dispatched
and processed.
Each destination specifies a list of events for which it requires notifications and various other configuration
information. Additionally, a destination encapsulates a list of your plugins that perform its main destination
functions. The following table compares the types of plugin interfaces that you can configure for a messaging
destination.
After you write code that implements a messaging plugin, you must register it in multiple ways. First, register the
plugin implementation in Guidewire Studio in the Plugins editor. Go to configuration→config→Plugins→registry, and
then right-click and choose Plugin. Studio prompts you for a plugin name and a plugin interface. The plugin name is
a short name that uniquely identifies this plugin implementation.
You must first register every plugin implementation in the Plugins editor before using the Messaging editor to
specify a messaging plugins. To specify a plugin implementation in the Messaging editor, specify the short plugin
name, not the fully-qualified class name.
An implementation of a messaging plugin can be assigned only to a single messaging destination. Do not assign a
particular messaging plugin to multiple destinations. This restriction applies to all messaging plugin types, such as
MessageTransport and MessageRequest. Sharing a messaging plugin between multiple destinations can create
issues, especially if the plugin overrides the execution methods of the MessagePlugin interface, such as suspend,
resume, and shutdown.
See also
• “Implementing messaging plugins” on page 330
• Reply Plugin – Optional. The plugin name for an implementation of the MessageReply plugin interface.
• Alternative Primary Entity – Optional. An alternative primary entity.
• Chunk Size – The maximum number of messages for a query to retrieve from the send queue. Default value
is 100,000.
• Number Sender Threads – Size of the destination's shared thread pool. To send messages, PolicyCenter can create
multiple sender threads to distribute the destination's workload. These threads call the messaging plugins that
send the messages. The size of the thread pool has a significant effect on messaging performance. Default value
is one.
• Poll Interval – The amount of time in milliseconds to elapse between the initiations of consecutive message-
processing cycles. A message-processing cycle includes retrieving a group of messages from the send queue and
processing and sending the messages. Default value is 10,000 (ten seconds).
• Shutdown Timeout – Messaging plugins have methods to handle the administrative commands suspend, resume,
and preparing for the messaging system to shutdown. The shutdown timeout value is the length of time to wait
before attempting to shutdown the messaging subsystem. Default value is 30,000.
• Max Retries – The number of automatic retries (maxretries) to attempt before suspending the messaging
destination. Default value is three.
• Initial Retry Interval – The amount of time in milliseconds (initialretryinterval) after a retryable error to retry
a sending a message. Default value is 1000.
• Retry Backoff Multiplier – The amount to increase the time between retries, specified as a multiplier of the time
previously attempted. For example, if the last retry time attempted was five minutes, and the multiplier
(retrybackoffmultiplier) is set to two, PolicyCenter attempts the next retry in ten minutes. Default value is
two.
• Message Without Primary – Configure the processing of non-safe-ordered messages.
◦ Multi Thread – Send non-safe-ordered messages asynchronously in a non-deterministic order in multiple threads.
◦ Single Thread - Send non-safe-ordered messages asynchronously in a strict order in a single thread. Default
setting.
◦ Strict Mode – Send non-safe-ordered messages synchronously in a strict order in a single thread.
• Distributed Request Processing – Optional. Distributes the before-send processing across multiple servers in the
cluster. The before-send processing is handled by the plugin specified by name in the Request Plugin or
Before Send Plugin field. If you select this checkbox, you can edit the following related fields.
◦ Server – Optional. The server on which to run the destination’s before-send operations. A destination’s before-
send operations can be executed on a different server than its other messaging operations. The ability to specify
different servers to run a destination’s before-send operations and its other messaging operations enables server
load to be allocated in many different configurations.
The server can be specified by either Host Name or Role. Only a single host name or server role can be specified.
If a server is not specified then the destination’s before-send operations are run on the same server as its other
messaging operations.
◦ Chunk Size – The number of messages that each processing node retrieves from the database each time it queries
for messages. Default value is 200.
◦ Request Processing Nodes – The number of cluster nodes to provide this service. Default value is one.
◦ Request Processing Threads – The number of threads on each worker node to use for message request processing.
Default value is one.
◦ Persist Transformed Payload– Permanently sets and persists the Message.Payload property with the return value
of beforeSend. By default, the checkbox is selected which enables the described behavior. If the checkbox is
unselected, the destination ignores the return value of the beforeSend method, in which case you must persist
the result on other Message properties.
◦ Always Call Before Send – If checked, force the Before Send plugin to be called even on retries where the
message has already been bound. Forcing a call to the Before Send plugin is desired if an update to the
message payload is necessary before retrying to send the message. Default value is unchecked or false.
◦ Before Send Plugin – Optional. The name of a plugin implementation that handles before-send processing. This
class must implement either the MessageBeforeSend or MessageRequest interface.
304 chapter 18: Messaging and events
Guidewire PolicyCenter 9.0.6 Integration Guide
• Events – Optional. A list of event names that correspond to the events relevant to this destination. For example,
the UserChanged and UserAdded events might be of interest to this external system. Each event triggers the
Event Fired rule set for that destination. One user action could trigger multiple events. If one action creates more
than one event that the destination listens for, PolicyCenter runs the Event Fired rules for every combination of
event name and destination. For testing and debugging only, you can specify all events with "(\w)*".
See also
• “Message processing cycle” on page 307
Handling acknowledgments
Due to differences in external systems and transports, there are two basic approaches for handling replies.
PolicyCenter supports synchronous and asynchronous acknowledgments, although in different ways.
• Synchronous acknowledgment at the transport layer
For some transports and message types, acknowledging that a message was successfully sent can happen
synchronously. For example, some systems can accept messages through an HTTP request or web service API
call. For such a situation, use the synchronous acknowledgment approach. The synchronous approach requires
that your transport plugin send method actually send the message and immediately submit the acknowledgment
with the message method reportAck.
To handle errors in general, including most network errors, throw an exception in the send method. This triggers
automatic retries of the message sending using the default schedule for that messaging destination.
For other errors or flagging duplicate messages, call the reportError or reportDuplicate methods.
• Asynchronous acknowledgment
Some transports might finish an initial process such as submitting a message on an external message queue.
However in some cases, the transport must wait for a delayed reply before it can determine if the external system
successfully processed the message. The transport can wait using polling or through some other type of callback.
Finally, submit the acknowledgment as successful or an error. External systems that send status messages back
through a message reply queue fit this category. There are several ways to handle asynchronous
acknowledgments, as described later.
For asynchronous acknowledgment, the messaging system and code path is much more complex. In this case, the
message transport plugin does not acknowledge the message during its main send method.
The typical way to handle asynchronous replies is through a separate plugin called the message reply plugin. The
message reply plugin uses a callback function that acknowledges the message at a later time. For example, suppose
the destination needed to wait for a message on a special incoming messaging queue to confirm receipt of the
message. The destination’s message reply plugin registers with the queue. After it receives the remote
acknowledgment, the destination reports to PolicyCenter that the message successfully sent.
One important step in asynchronous acknowledgment with a message reply plugin is setting up the callback
routine’s database transaction information appropriately. Your code must retrieve message objects safely and commit
any updated objects, such as the ACK itself and additional property updates, to the PolicyCenter database.
Messaging and events 305
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• “Reporting acknowledgments and errors” on page 340
Rule sets must never call message methods for ACK, error, or skip
From within rule set code, you must never call any message acknowledgment or skipping methods such as the
Message methods reportAck, reportError, or skip. Use those Message methods only within messaging plugins.
This prohibition also applies to Event Fired rules.
retried or Message.Bound is false, the application runs the before-send processing before attempting to send the
message. The before-send processing runs in a separate database transaction from the send and after-send
processing.
• PolicyCenter runs both send and afterSend methods in a single database transaction and commits the changes,
assuming that no exceptions occurred.
• PolicyCenter calls the MessageTransport plugin method send and then runs the after-send processing.
• The after-send processing is the afterSend method in an instance of either MessageRequest or
MessageAfterSend plugin interfaces.
The following rules apply to message reply processing for asynchronous replies.
• The MessageReply plugin, which optionally handles asynchronous acknowledgments to messages, does its work
in a separate database transaction and commits changes, assuming that no exceptions occurred.
• In the default configuration, this work is performed only on the single cluster member with a lease for this
messaging destination. The server that handles this messaging destination might be different at message reply
time, which might be long after the message was sent.
The Single thread and Multi thread options exhibit the following behaviors.
• The application does not wait for a message acknowledgment before sending subsequent messages.
• With the Single thread option, non-safe-ordered messages are sent in the order of their Event Fired creation time
among the other messages in a database commit.
• With the Multi thread option, the precise order in which messages are sent is non-deterministic.
• Message-sending errors do not block the sending of subsequent messages. The message destination must be able
to handle such situations. For example, if a create-object message fails, a subsequent message that assumes the
existence of the object might cause a problem unless the destination can handle the situation.
The Strict Mode option exhibits the following behaviors.
• The application waits for a message acknowledgment before sending subsequent messages.
• Non-safe-ordered messages are sent in the order of their Event Fired creation time among the other messages in a
database commit.
• Message-sending errors block the sending of subsequent messages until an administrator resolves the problem.
For example, an administrator might resync the failed message.
Guidewire Application
message before send message transport message after send message reply
plugin** plugin plugin*** plugin
External system
*By default, before‐send actions run on the one server in the cluster with the lease to handle that destination. If you enable
Distributed Request Processing for the destination, these actions run on multiple servers.
The send and after‐send phases run in a different thread on the server that has the lease for that destination. If you enable
Distributed Request Processing for the destination, these actions potentially run on an entirely different server from the before‐
send actions.
The reply phase happens on the server with the lease for that destination. This happens in a separate thread. This reply might
come significantly later, and potentially on a different server if the cluster lease assignments have changed.
KEY
Guidewire code
Sometimes an event root object is a higher-level object such as policy. In other cases, the event is on a subobject,
and your Event Fired rules must do some work to determine what high-level object it is about. For example, the
Address subobject is common and changing it is common. However, what larger object contains this address? You
might need this additional context to do something useful with the event.
For example, was the address a policy’s producer’s address? Was it an insured’s address?
In PolicyCenter, most subobjects in an account have properties that you can use to access related objects. For
example, most account objects have an Account property that points to the account. Most policy period subobjects
have a PolicyPeriod property that points to the PolicyPeriod that includes this object. Also, remember that every
policy belongs to exactly one account.
PolicyCenter triggers events for many objects if an entity is added, removed (or retired), or if a property changes on
the object. For example, selecting a different policy type on any policy generates a changed event on the policy.
The changes are about the change to that database row itself, not on subobjects. For example, PolicyCenter reports a
change to an object if a foreign key reference to a subobject changes but not if properties on the subobject changes.
There are exceptions to this rule.
For example, switching to a different policy contact on a policy is a change to the policy. A change on the policy
contact is a policy contact property change, but not a policy change.
The following table describes the events that PolicyCenter raises. In this table, standard events refer to the added,
changed, and removed events for entities that generate events. For example, the Policy entity would generate events
whenever code adds, changes, or removes entities of that type in the database. In those cases, the Event Fired
business rules would see PolicyAdded, PolicyChanged, and ClaimRemoved events if one or more destinations
registered for those event names.
Document DocumentAdded Standard events for root entity Document. Some implemen‐
DocumentChanged tations do not let users remove documents once they have
DocumentRemoved been added, so the remove event may not be called.
Job JobAdded Jobs entities only exist as subtypes of Job, such as Audit.
JobChanged Those subtypes generate standard events for root entity
JobRemoved Job.
Policy PolicyAdded Standard events for root entity Policy. Most events are
PolicyChanged not on the policy entity but on an individual policy period
PolicyRemoved entity.
ProcessHistory ProcessHistoryAdded Some integrations can be done as a batch process. For ex‐
ProcessHistoryChanged ample, use the event/messaging system to write records to
ProcessHistoryRemoved a batch file (or rows to a database table) as each transac‐
tion processes. If all transactions process, submit the batch
data to some downstream system. Write a batch process
that starts manually or on a timer. To coordinate your soft‐
ware modules, use the ProcessHistory entity. If a batch
process starts, a ProcessHistoryAdded event triggers. If
you listen for the ProcessHistoryChanged event, check
the processHistory.CompletionTime property for the da‐
testamp in a datetime object.
SoapCallHistory SoapCallHistoryAdded Standard events for SoapCallHistory entities. The appli‐
SoapCallHistoryChanged cation creates one for each incoming web service call.
SoapCallHistoryRemoved
Administration events
Group GroupAdded Standard events for root entity Group.
GroupChanged
GroupRemoved
messagingToolsAPI.ackMessage(myAcknowledgement);
See also
• “Using web services to submit ACKs and errors from external systems” on page 342
or updated using this interface. Be very careful about using this interface for loading important business data where
events might be expected for integration purposes. You must use some other system to ensure your external systems
are up to date with this newly-loaded data.
See also
• “Restrictions on entity data in messaging rules and messaging plugins” on page 325
At the next level in the rules hierarchy, it determines for what root object an event triggered.
Finally, at the third level there is a rule for handling each event of interest.
messageContext.EventName == "PolicyChanged"
In this way, it is easy to organize the rules and keep the logic for handling any single event separate. Of course, if
you have shared logic that would be useful to processing multiple events, create a Gosu class that encapsulates that
logic. Your messaging code can call the shared logic from each rule that needs it.
Once the Rule Engine recognizes the root object as a Policy, it allows you to access properties and methods on the
policy to parameterize the payload of your message.
Next, create a message with a String payload.
You can also use loops or queries as needed. For example, suppose that if a policy-related event occurs, you want to
send a message for the policy and then a message for each note on the policy. The rule might look like the following
code statements.
This creates one message for the policy and also one message for each note on the claim.
If you create multiple messages for one event like this, you can share information easily across all of the messages.
For example, you could determine the username of the person who made the change, store that in a variable, and
then include it in the message payload for all messages.
Remember that if multiple destinations requested notification for a specific event name, your Event Fired rule set
runs once for each destination, varying only in the messageContext.DestID.
committed to the database. There are additional functions similar to isFieldChanged and getOriginalValue that
are useful for array properties and other situations.
For example, the following Event Fired rule code checks if a desired property changed and also checks its original
value.
if (policy.isFieldChanged("LossCause")) {
msg = msg + " old value is " + (policy.getOriginalValue("LossCause") as LossCause).Code)
}
}
Rule sets must never call message methods for ACK, error, or skip
From within rule sets, you must never call any message acknowledgment or skipping methods such as the Message
methods reportAck, reportError, or skip. Use those Message methods only within messaging plugins. This
prohibition also applies to Event Fired rules.
Later, to retrieve stored information from the HashMap, your code would look like the following statements.
// Get the subject line from the "temporary map" stored earlier!
var subject = session.getFromTempMap("related_activity_subject") as String
If you need to add an entity instance to the bundle, explicitly add it to the bundle. Get the correct bundle using the
Gosu expression messageContext.Bundle. Add entities to the bundle before adding it to the hash map.
Messaging and events 321
Guidewire PolicyCenter 9.0.6 Integration Guide
You can use this API to ensure that important Event Fired code not get run twice. Set data in the map, and later your
code can check data in your map to see if it already ran.
The code assumes the template supports parameter passing. For example, as in the following invocations.
It is important to note that the primary object of a message is different from the message root, however. It is actually
the primary object of a message that defines the message ordering algorithm.
Unlike the message root, there is not a single property that implements the primary object data for a message.
Instead, there are multiple properties on a Message object that correspond to each type of data that could be a
primary object for that application. Each application can define a default primary entity. Each messaging destination
can choose from a small set of primary entities. The properties on the Message object for primary entity are strongly
typed to the type of the primary entity. In other words, there is a different property on Message for each primary
entity type.
In PolicyCenter, there are multiple properties on Message for the primary entity.
Property Description
message.Account The account, if any, associated with this Message object.
Additionally, there is a message.PolicyPeriod property. However, PolicyPeriod is not a primary entity for
PolicyCenter messaging.
If you set the message.MessageRoot property, the following behavior occurs automatically as a side-effect of
setting this property from Gosu or Java.
You only need to set the primary entity properties manually if the automatic behaviors described in this topic did not
set them already. Note that you do not need to set unused primary entity properties to null. The only primary entity
property used in the Message object is the one that matches the primary entity for the destination.
To configure the behavior of the message ordering system for safe ordering, perform the following actions.
1. Set the alternative primary entity in the messaging destination.
2. Set the root object to an entity from which you can determine the primary entity. For example, PolicyCenter
can extract an Account from a PolicyPeriod entity, as well as other types of entities.
Alternatively, you can set the column associated with that entity directly. Each candidate primary entity has a foreign
key, indexed, column in the Message entity. If it is not possible to determine the appropriate entity object from the
root object, you can explicitly set the appropriate foreign key column to the desired primary key object.
Be careful with setting message properties that store a reference to a primary object. PolicyCenter uses that
information to implement safe ordering of messages by primary object.
See also
• “Message processing cycle” on page 307
external systems. You could also write web services that take XML data payloads from an external system or return
XML as the result.
msg.putEntityByName("note1", note)
These methods are especially helpful for handling special actions in acknowledgments. For example, to update
properties on an entity, use these methods to authoritatively find the original entity. These methods work even if
public IDs or other properties on the entity change. This approach is particularly useful if public ID values could
change between the time Event Fired rules create the message and the time you messaging plugins acknowledge the
message. The getEntityByName method always returns the correct reference to the original entity.
See also
• “Message processing cycle” on page 307
• Never call business logic APIs that might change entity data, even in edge cases.
• From messaging plugin code, entity instance changes do not trigger concurrent data exceptions except in special
rare cases. To avoid data integrity issues with concurrent changes, avoid changing data in these code locations.
• In some cases, consider adding or advancing a workflow as an alternative to direct data modifications from
messaging code. The workflow can asynchronously perform code changes in a separate bundle outside your
messaging-specific code.
• If you must update messaging-specific data, consider how absence of detecting concurrent data changes from
messaging plugins might affect your extensions to the data model. For example, suppose you intend to modify an
entity type to add a property with simple data. Instead, you could add a property with a foreign key to an instance
of a custom entity type. First, create the instance of your custom entity type at an early part of the lifecycle of
your main objects before the messaging code runs. As mentioned earlier, it is unsupported to create an entity
instance in Event Fired rules or in messaging plugins. This restriction applies to all entity types, including custom
entity types. In Event Fired rules or in messaging plugins, modify the messaging-specific entity instance. With
this design, there is less chance of concurrent data change conflicts from a simple change on the main business
entity instance from within the user interface.
There also exists an optional feature to lock related objects during messaging actions. With locked data—usually the
primary entity instance or the message—any attempt to access the locked data causes the accessing code to wait
until the data is unlocked. For maximum data integrity, enable entity locking during messaging. For maximum
performance, disable entity locking during messaging.
Messaging plugins must not call SOAP APIs on the same server
In general, avoid calling locally-hosted SOAP APIs from within a plugin or the rules engine. There are various
problems if you call SOAP APIs that modify entities that are currently in use, including but not limited to APIs that
might change the message root entity. Be careful about any SOAP calls to the same server. If the SOAP API hosted
locally modifies entity data and commits the bundle, the current transaction does not always detect and reload local
data.
326 chapter 18: Messaging and events
Guidewire PolicyCenter 9.0.6 Integration Guide
Instead, refactor your code to avoid this case. For example, write a Gosu class that performs a similar function as the
web service but that does not commit the bundle. This type of refactoring also results in higher server performance.
This is true for all types of local loop-back SOAP calls to the same server.
Those limitations are true for all plugin code. In addition, there are messaging-specific limitations with this
approach. Specifically, PolicyCenter locks the root entity for the message in the database. Any attempts to modify
this entity from outside your messaging plugin (and SOAP APIs are included) result in concurrent data exceptions.
Similarly, if you did not want to send events for a note before its associated policy is valid, you could write a
rule condition such as the following.
It is important to understand that you define your own standards for event filtering and processing. PolicyCenter
does not enforce any requirements about validation levels. The EntitynameAdded events and EntitynameChanged
events trigger independent of the object’s validation level.
Generally speaking, PolicyCenter does not use the validation levels. You can define rules that set or get the
validation level for some purpose. Your messaging rules might send a message to an external system because of an
event, but ignore the event in some cases due to the validation rules.
There is one rule set that governs validation checking, called Policy Validation Rules. You can set validation levels
in these rules that are checked later within the Event Fired rule set.
PolicyCenter itself does not actually use the validation level for any purpose.
Messaging and events 327
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• “Implement late binding” on page 328
Procedure
1. At message creation time in Event Fired rules, add your own marker text within the message. A simple
example would be the arbitrary token <AAAAAA>.
2. Decide whether to implement late binding at before-send time or message-send time.
• To minimize the latency time between message creation time, implement late binding at before-send time
and enable Distributed Request Processing for that destination. The before-send processing happens as a
distributed background task across potentially multiple nodes in your cluster even for a single destination.
If you enable Distributed Request Processing for the destination, message order for before-send processing
is non-deterministic. Do not rely on a specific order for messages in your beforeSend code. For some use
328 chapter 18: Messaging and events
Guidewire PolicyCenter 9.0.6 Integration Guide
cases, this is an acceptable trade-off for performance. In other use cases, a late binding transformation
cannot occur until all other messages for that primary object are already processed.
• To ensure strict ordering with larger latency between message creation time and message send time, there
are two choices. You can implement late binding at before-send time and do not enable Distributed Request
Processing. If you need to enable Distributed Request Processing for other reasons, you can implement late
binding in your MessageTransport plugin, although that is not generally recommended.
3. Add new code in the right location.
• To implement late binding at before-send time, there are potentially two choices depending on how you
configured your destination. You can implement a MessageRequest plugin, which also handles after send
processing. Alternatively, implement a MessageBeforeSend plugin, which handles only before-send
processing but requires that you enable Distributed Request Processing. In either case, your plugin
implementation must have a beforeSend method that takes a Message object and returns a String object
that is the transformed payload.
• To implement late binding at send time, add code to your MessageTransport plugin implementation in the
send method.
4. In your new late binding code, find the special token and then substitute or transform it. Depending on the
context, you might need to get objects from the Message to check the current value. For example, perhaps you
might get the Message.MessageRoot object and cast it to a Policy. Get whatever properties you need from it.
The current value of the property is a late bound value. Replace the marker with the new value.
For example, a simple Gosu implementation of the MessageRequest or MessageBeforeSend plugin interface
might use the following code in the beforeSend method. In this example, the transport assumes the message
root object is a Policy and replaces the special marker in the payload with the value of extension property
SomeProperty. This example assumes that the message contains the string <AAAAAA> as a special marker in
the message text.
For more complex substitutions, there are APIs that can search for tokens with special delimiters around them.
You can provide a class that map any input token to a different output token.
See also
• “Map message payloads by using tokens” on page 338
• “Implementing messaging plugins” on page 330
Saving this name is convenient because, in some cases, the external system’s name for the object in the response is
known in advance. You do not need to store the object type and public ID in the message to refer back to the object
in the acknowledgment.
To conform to the new interface, add a setParameters method with the following signature.
// access values in the MAP to get parameters defined in plugin registry in Studio
By default, this task runs only on the server that handles this messaging destination. If you enable Distributed
Request Processing for the destination, the task is distributed across multiple servers in the cluster. In the Messaging
editor, enable this feature by selecting the Distributed Request Processing checkbox.
If your beforeSend method throws exceptions, the schedule for retrying is handled at send time by the standard
destination settings for errors, such as the Retry Backoff Multiplier. This is true even if Distributed Request
Processing is enabled.
The Message property called Bound is a boolean flag that specifies whether the message request processing is
complete. You can optionally set Bound to true after message creation if you know that the message does not need
processing. After the server performs the before-send processing by calling the appropriate beforeSend method, the
server sets Message.Bound to true.
In message retry, the application will call your beforeSend method again. To correctly handle message retry, your
beforeSend method must check Message.Bound and behave accordingly because the message may have the Bound
property already set to true.
You must ensure that your beforeSend implementation is idempotent, which means that it could be called multiple
times and have the same effect. Your code must ensure that repeated calls cause the same results on the Message
entity instance and the return value of the method. This warning applies to beforeSend methods implemented in
either MessageRequest or MessageBeforeSend plugin interfaces. This warning applies independent of whether you
use Distributed Request Processing. If the application attempts to retry sending a message, the application calls your
beforeSend implementation more than once.
If you want your plugin to get parameters from the plugin registry, implement the InitializablePlugin interface
in the class definition. Next, add a setParameters method that gets the parameters as a java.util.Map object.
The following example demonstrates a minimal message transport in Gosu for testing.
uses java.util.Map;
uses java.plugin;
// access values in the MAP to get parameters defined in plugin registry in Studio
// NEXT, define all your other methods required by the MAIN interface you are implementing...
function suspend() {}
function shutdown() {}
function setDestinationID(id:int) {}
function resume() {}
message reply synchronously by calling methods on the Message, it does not affect whether afterSend is called on
your plugin implementation.
@Distributed
public class MyMsgReplyPlugin implements MessageReply { ... }
The MessageReply plugin interface defines a single method called initTools. The method is called by the
messaging infrastructure to initialize the plugin.
The handler argument provides a transaction context for executing the plugin code. The transaction context
executes as the system user and includes a bundle for committing any changes performed by the plugin code.
The msgFinder argument can be used by the plugin code to look up the relevant message. The MessageFinder
object provides methods such as findById and findByRefId, which accept a messageID or senderRefID,
respectively, and return the specified Message object.
The initTools method must save its arguments in private variables for subsequent use. The method has no return
value.
Implement a PluginCallbackHandler
The plugin code that is executed in the context of a transaction is of type PluginCallbackHandler.Block. The
Block is an interface that defines a single method called run.
run()
The PluginCallbackHandler interface also defines a method called execute which executes the code block passed
to it.
execute(block : Block)
A MessageReply plugin method creates a new instance of the PluginCallbackHandler.Block interface that
implements the run method. It then passes the Block to the execute method of the PluginCallbackHandler that
was saved in the initTools method.
Alternatively, the plugin code can be contained in a Gosu anonymous function block that is passed directly to the
execute method.
The PluginCallbackHandler interface also defines an add method to add an object to the transaction’s bundle.
The bean argument references the object to add to the transaction’s bundle. Changes to the object are committed to
the database when the transaction completes.
334 chapter 18: Messaging and events
Guidewire PolicyCenter 9.0.6 Integration Guide
The method returns a clone of the bean argument. All subsequent references to the object must be to this returned
clone. All changes must also be performed on the clone. The original bean argument passed to the add method can
be discarded.
The add method can be called only from within the Block interface’s run method or its alternative implementation
as a Gosu block. If the method is called from anywhere else, an exception is thrown.
In the following implementation of a simple MessageReply plugin method called skip, the method skips processing
the message that triggered the plugin code. A Message object provides additional methods, including acknowledging
the message (reportAck method), re-sending the message (retry method), and reporting an error (reportError
method). The example MessageReply plugin can be expanded to perform these operations by adding methods
similar to the skip method.
The example code demonstrates the preferred manner of implementing a MessageReply plugin method. First, the
plugin operations are exposed in their own interface. In the example code, the skip method is defined in the
IMyMessageReplyPlugin interface.
Then the exposed methods, plus the initTools method, are implemented in the plugin class. The example code
implements the plugin in the MyMessageReplyPlugin class.
The MessageReply interface extends the MessagePlugin interface, which defines methods to control the messaging
lifecycle, such as suspend and resume. The required MessagePlugin methods are implemented in the example code
as empty methods.
Finally, the skip method demonstrates the two techniques for implementing and executing plugin code by defining
either a Gosu block or a Block.run method.
* _callbackHandler.execute(myBlock)
*/
}
}
The following statements show how custom configuration code can call the skip plugin method.
See also
The suspend and resume operations are typically enacted through the PolicyCenterAdministration tab by an
administrator who is managing messaging destinations. The operations can also be performed by an external system
that calls web services provided by PolicyCenter.
A destination is shut down whenever its server is either physically shut down or its server/system run level is
changed. When the server/system run level is changed, the server is symbolically shut down and immediately
restarted at the new run level. As part of the shut-down process, the existing messaging plugin instances are not
destroyed. When the sending of messages resumes under the new run level, PolicyCenter continues to use the
original plugin instances.
The following sample code overrides a plugin's suspend method to implement simple logging.
if(_logger.isDebugEnabled()) {
_logger.debug("Message transport plugin: Suspending")
}
}
A plugin's suspend, resume, and shutdown methods must not call the PolicyCenter MessagingToolsAPI web
services that suspend or resume the messaging destination. Such circular application logic is not supported.
Messaging and events 337
Guidewire PolicyCenter 9.0.6 Integration Guide
Procedure
1. Choose start and end delimiters for the text to replace.
For example, you can use the 2-character string “**” as the start delimiter and end delimiter. For production
code, you might want to use multiple special characters in a sequence that is forbidden n a real field.
2. Put these delimiters around the original text that you need to map and replace.
For example, a Gosu template that generates the payload might include "Injury=**$
{exposure.InjuryCode}**". This delimited text might generate text such as "Injury=**A1**" in the
message payload.
3. Implement a class that implements the inner interface StringSubstitution.Exchanger.
This exchanger class must translate exactly one token, not the entire String object for the payload. This class
might use its own look-up table, a java.util.Map object, or look in a properties file. The Exchanger interface
has one method called exchange that translates the token. This method takes a String object (the token) and
translates it and returns a new String object. If the input token requires no substitution, you must decide
whether to quietly return the original String, or throw an exception.
4. Instantiate your class that implements Exchanger, and then instantiate the StringSubstitution class with
the constructor arguments as follows:
a. Start delimiter
b. End delimiter
c. Your Exchanger instance
5. On the new StringSubstitution instance, call the substitute method to convert the message payload.
Example
The following example demonstrates this process. You can paste the following code into the Gosu Scratchpad in
Studio.
uses gw.pl.util.StringSubstitution
var origString = "wolf cat **cat** dog dog **dog** llama llama **llama**"
var myExchanger = new TestExchanger()
var mySub = new StringSubstitution("**", "**", myExchanger)
var output = mySub.substitute(origString)
Some static properties on the MessageStatus class contain arrays of message status values. You can use them to
check values with more easily read code.
The class also has static methods that take a status (state) value and return true if the status is in a list of relevant
values. For example, to test if a message was ever acknowledged (including error values), enter the following Gosu
code:
gw.pl.messaging.MessageStatus.isAcked(Message.Status)
The following table lists additional MessageStatus static properties and the static methods.
and destination during that retry delay. After the delay reaches the wait limit, the retryable error becomes a non-
automatic-retry error.
• Errors during send for which you do not want automatic retry.
If the destination has an error that is not expected to be temporary, do not throw an exception. Throwing an
exception triggers automatic retry. Instead, call the message’s reportError method with no arguments.
The destination suspends sending for all messages for that destination until one of the following is true.
◦ An administrator retries the sending manually, and it succeeds this time.
◦ An administrator removes the message.
◦ It is a safe-ordered PolicyCenter message and an administrator resynchronizes the account.
The following error conditions can occur later in the messaging process:
• A negative acknowledgment (NAK)
A destination might get an error reported from the external system (database error, file system error, or delivery
failure), and human intervention might be necessary. For safe-ordered messages, PolicyCenter stops sending
messages for this combination of primary object and destination until the error clears through the administration
console or automated tools.
• No acknowledgment for a long period
PolicyCenter does not automatically time out and resend the message because of delays. If the transport layer
guarantees delivery, delay is acceptable. Considering that resending results in message duplicates, the external
system might not be able to properly detect and handle duplicates.
For safe-ordered messages, PolicyCenter does not send more messages for the combination of primary object and
destination until it receives an acknowledgment (ACK) or some sort of error (NAK).
To report an acknowledgment
To report an error
To report a duplicate
Using web services to submit ACKs and errors from external systems
If you want to acknowledge a message directly from an external system, use the web service method
MessagingToolsAPI.ackMessage.
First, create an Acknowledgement SOAP object to pass as the ack parameter of the method.
There is an ackCode that is written to the MessageHistory record.
You might have added object names when creating the message in the rules, such as
message.putEntityByName(“account”, account). If so, you can change the property values by using
FieldChanges with that entity name and FieldChangeValue entries with the property name and new serialized
value. Alternatively, you can raise events on the object by adding CustomEvents objects with the entity name and
the events to raise.
If there are no problems with the message (it is successful), pass the object as is.
If you detect errors with the message, set the following properties.
• Error – Set the Acknowledgement.Error property to true.
• Retryable – For all errors other than duplicates, set the Acknowledgement.Retryable property to true and
Acknowledgement.Error to true. Set this property to the default value false if there is no error.
• Duplicate – If you detect that the message is a duplicate, set the Duplicate and Error properties to true.
See also
• “Acknowledging messages” on page 348
• “Saving attributes of a message” on page 324
• “Custom events from SOAP acknowledgments” on page 318
See also
• “Retrying messages” on page 348
Pending Send
The message has not been sent yet.
• If the message is related to an account, this message is safe-ordered. The messaging destination might be
waiting for an acknowledgment on the previous message for that same account.
• The destination might be suspended, which means that it is not processing messages.
• The destination might not be fast enough to keep up with how quickly the application generates messages.
PolicyCenter can generate messages very quickly.
Messaging and events 343
Guidewire PolicyCenter 9.0.6 Integration Guide
Pending ACK
PolicyCenter waits for an acknowledgment for a message it sent. If errors occur, such as the external system not
receiving or properly acknowledging the message, PolicyCenter waits indefinitely.
If the message has a related primary object for that destination, it is safe-ordered. This type of error blocks
sending other messages for that primary object for that destination.
In this case, you can intervene to skip the in-flight message or retry sending it. Be very careful about issuing retry
or skip instructions. A retry could cause the destination to receive a message twice. A skip could cause the
destination to never get the intended information. In general, you must determine the actual status of the
destination to make an informed decision about which correction to make.
To skip or retry sending a message, click the relevant in-flight message link to view the message details screen.
Click the Retry or Skip button.
Error
The destination indicates that the message did not process successfully. The error blocks sending subsequent
messages. In some cases, the error message indicates that the error condition might be temporary and the error is
retryable. In other cases, the message indicates that the message itself is in error (for example, bad data) and
resending does not work. In either case, PolicyCenter does not automatically try to send again.
ACK
The message was successfully processed. The message stays in the system until an administrator purges it.
Note: Since the number of these messages is likely to become very large, Guidewire recommends
that you purge completed messages on a periodic basis.
Retryable Error
Message sending for the message failed at the external system, not because of a network error. Either the message
had an error or was a duplicate.
If PolicyCenter retries a failed message, it marks the original message as failed or retried and creates a copy of the
message with a new message ID. A new ID is assigned to the retry message because message destinations can track
received messages and ignore duplicate messages. However, if PolicyCenter retries an in-flight message because it
never got an ACK, then it sends the original message again with the same ID. If the destination never got the
message, then there is no problem with duplicate message IDs. If the destination received the message but
PolicyCenter never got an acknowledgment, then this prevents processing the message twice. The destination can
either send back another acknowledgment or refuse to accept the duplicate message and send back an error.
If PolicyCenter receives an error, it holds up subsequent messages until the error clears. If the destination sends back
duplicate errors, you can filter out duplicates and warn the administrator about them. However, you can choose to
simply issue a positive acknowledgment back to PolicyCenter.
PolicyCenter could become sufficiently out of sync with an external system to make skipping or retrying an
individual message insufficient to get both systems in sync. In such cases, you might need administrative
intervention and problem solving. You can review your sever logs to determine the root cause of the problem.
PolicyCenter makes every attempt to avoid this problem. However, it provides a mechanism called resynchronizing
to handle this case. All related pending and failed messages are dropped and resent.
344 chapter 18: Messaging and events
Guidewire PolicyCenter 9.0.6 Integration Guide
payload
A string containing the text-based message body of the message.
Messaging and events 345
Guidewire PolicyCenter 9.0.6 Integration Guide
user
The user who created the message. If you create the message without cloning the old message, the user by default
is the user who triggered the resync. If you create the message by cloning a pending message, the new message
inherits the original user who created the original message. In either case, you can choose to set the user property
to override the default behavior. However, in general Guidewire recommends setting the user to the original user.
For financial transactions, set the user to the user who created the transaction.
There are also read-only properties in pending messages returned from messageContext.PendingMessages.
EventName
A string that contains the event that triggered this message. For example, "PolicyAdded".
Status
The message status as an enumeration. Only some values are valid during resync. The utility class
gw.pl.messaging.MessageStatus provides static properties and static methods that you can use for your code.
ErrorDescription
A string that contains the description of errors, if any. It might not be present. This value is set by a negative
acknowledgment (NAK).
SenderRefID
A sender reference ID set by the destination to uniquely identify the message. Your destination can optionally set
the message.senderRefID field in any of your messaging plugins during original sending of the message. Only
the first pending message has this value set due to safe ordering. You need to use the sender reference ID only if
it is useful for that external system.
The SenderRefID property is read-only from resync rules. This value is null unless this message is the first
pending message and it was already sent or Pending Send, and it did not yet successfully send. As long as the
message.status property does not indicate that it is Pending Send, the message could have the sender reference
the ID property populated by the destination.
See also
messageContext.createMessage(message)
This alternative method signature (in contrast to passing a String) is an API to copy a message into a new message
and returns the new message. If desired, modify the new message’s properties within your resync rules. All new
messages (whether standard or cloned) submit together to the send queue as part of one database transaction after
the resync rules complete.
The cloned message is identical to the original message, with the following exceptions.
• The new message has a different message ID.
• The new message has status of pending send (status = PENDING_SEND).
• The new message has cleared properties for ACK count and code (ackCount = 0; ackCode = null).
• The new message has cleared property for retry count (retryCount = 0).
• The new message has cleared property for sender reference ID (senderRefID = null).
• The new message has cleared property for error description (errorDescription = null).
346 chapter 18: Messaging and events
Guidewire PolicyCenter 9.0.6 Integration Guide
PolicyCenter marks all pending messages as skipped (no longer queued) after the resync rules complete. Because of
this, resync rules must either send new messages that include that information, or manually clone new messages
from pending messages, as discussed earlier.
Resync in ContactManager
If you license Guidewire ContactManager for use with PolicyCenter, be aware that ContactManager supports resync
features for the ABContact entity.
To detect resynchronization of an ABContact entity, set your destination to listen for the ABContactResync event.
Your Event Fired rules can detect that event firing and then resend any important messages. Your rules generate
messages to external systems for this entity that synchronize ContactManager with the external system.
Monitoring messages
PolicyCenter provides a simple user interface to view the event messaging status for policies. This helps
administrators understand what is happening, and might give some insight to integration problems and the source of
differences between PolicyCenter and a downstream system.
For example, if you add one policy in PolicyCenter but it does not appear in the external system, you need to know
the following information.
• As far as PolicyCenter knows, have all messages been processed? (“Green light”) If the systems are out of sync,
then there is a problem in the integration logic, not an error in any specific message.
• Are messages pending, so you simply need to wait for the update to occur. (“Yellow light”)
• Is there an error that needs to be corrected? (“Red light”) If it is a retryable error, you can request a retry. This
might make sense if the external system caused the temporary error. For example, perhaps a user in the external
system temporarily locked the policy by viewing it on that system’s screen. In many cases, you can simply note
the error and report it to an administrator.
This status screen is available from the policy screen by selecting Account Actions:Account Status from the Account
menu.
The PolicyCenter Administration tab provides administrators with access to messages sent across the system.
Selecting Monitoring→Message Queues shows a list of message destinations. Multiple levels of detail are provided for
viewing events and messaging status.
See also
• “messaging_tools command” in the System Administration Guide
Messaging and events 347
Guidewire PolicyCenter 9.0.6 Integration Guide
Acknowledging messages
To acknowledge a message, use the following method:
ackMessage(ack : Acknowledgement)
The Acknowledgement parameter is a SOAP object that passes information about the status of the message.
The method returns true if the message is found and acknowledged. If not, the method returns false.
The method can throw the following exceptions:
• If the ACK is invalid, the method throws IllegalArgumentException.
• If there are permission or authentication issues, the method throws WsiAuthenticationException.
• If the Acknowledgement object is not valid, the method throws SOAPSenderException.
• If the ACK could not be committed to the database, the method throws SOAPException.
See also
• “Using web services to submit ACKs and errors from external systems” on page 342
• “Messaging tools web service” on page 347
If there are multiple messages that match, this method returns the message ID from the first match. If no message is
found with the specified senderRefID and messageID, the method returns -1.
To get a message ID for a message sent to a specific message destination, call the following method:
If there are multiple messages that match, this method throws an exception. If no message is found, the method
returns null.
These methods can throw the following exceptions:
• If there are permission or authentication issues, the method throws WsiAuthtenicationException.
• If the destination ID is invalid, the method throws IllegalArgumentException.
See also
• “Message status code reference” on page 339
• “Messaging tools web service” on page 347
Retrying messages
You can retry sending messages. There are several variations of retry methods that you can call.
retryMessage(messageID : long)
The method returns a Boolean value that indicates whether or not the message was successfully submitted for
another attempt.
• If the message with this messageID does not exist, the method returns false.
• Returning true means that the message was retried. It does not indicate whether the retry was successful.
If there are permission or authentication issues, the method throws WsiAuthenticationException.
retryRetryableErrorMessages(destID : int)
The method returns a Boolean value that indicates whether or not the message was successfully submitted for
another attempt.
The method throws the following exceptions:
• If there are permission or authentication issues, the method throws WsiAuthenticationException.
• If the destination ID is invalid, the method throws IllegalArgumentException.
The method returns a Boolean value that indicates whether or not the message was successfully submitted for
another attempt.
The method throws the following exceptions:
• If there are permission or authentication issues, the method throws WsiAuthenticationException.
• If the ACK is invalid, the method throws IllegalArgumentException.
Retrying messages for a given destination with Retryable error state and a retry limit
You can retry all messages for a given destination that are in Retryable error state and have been retried fewer times
than a specified retry limit. Each message maintains a retry count. Each attempt to retry a message increments its
retry count. A message with a retry count that is greater than the retry limit specified in the method call is not
retried, unless the retry limit is 0.
Call the following method:
Note: Specifying a retryLimit of 0 retries all retryable error messages and is identical to
retryRetryableErrorMessages(int destID).
The method returns a Boolean value that indicates if all messages were successfully submitted for another attempt.
If any messages to be retried exceeded the retry limit, the method returns false.
The method throws the following exceptions:
• If there are permission or authentication issues, the method throws WsiAuthenticationException.
• If the ACK is invalid, the method throws IllegalArgumentException.
See also
• “Messaging tools web service” on page 347
• “Message error handling” on page 343
Messaging and events 349
Guidewire PolicyCenter 9.0.6 Integration Guide
Skipping a message
To skip a message, effectively removing an active message from the message queue, call the following method:
skipMessage(messageID : long)
The method returns a Boolean value indicating whether the message was successfully skipped:
• If the method returns true, the message was successfully skipped.
• If the method returns false, there can be multiple reasons:
◦ The message with this messageID does not exist.
◦ The message is not in one of the following active states: Pending Send, Inflight, Error, Retryable Error, or
Pending Retry.
If there are permission or authentication issues, the method throws WsiAuthenticationException.
See also
• “Messaging tools web service” on page 347
• “Message error handling” on page 343
See also
• “Resynchronizing messages for a primary object” on page 345
• “Messaging tools web service” on page 347
purgeCompletedMessages(cutoff : Date)
The cutoff argument is expected to be a date prior to the current date, and it cannot be null. A completed message
is purged if its send time occurred before the date specified in the cutoff parameter.
350 chapter 18: Messaging and events
Guidewire PolicyCenter 9.0.6 Integration Guide
Note: If the cutoff argument is in the future, a date after the current date, the entire MessageHistory
table is purged and no exception is thrown.
The method can throw the following exceptions:
• If the cutoff parameter is null, the method throws IllegalArgumentException.
• If there are permission or authentication issues, the method throws WsiAuthenticationException.
See also
Suspending a destination
Suspending a destination typically means that PolicyCenter stops sending messages to a destination, although you
can stop inbound message processing as well. You can use this method to shut down the destination system and halt
sending during processing of a daily batch file. PolicyCenter suspends the destination so that it can also release any
resources such as a local batch file.
When outbound processing is suspended, the request and transport plugins are suspended, along with message
sending. When inbound processing is suspended, the reply plugin is suspended.
To see if a destination is suspended, call the following method:
The direction parameter can have the MessageProcessingDirection values inbound, outbound, or both.
The method returns true if processing for the specified destination and direction is suspended. It returns false
otherwise.
The method can throw the following exceptions:
• If there are permission or authentication issues, the method throws WsiAuthenticationException.
• If the ACK is invalid, the method throws IllegalArgumentException.
To suspend both inbound and outbound messages for a destination, call the following method:
suspendDestinationBothDirections(destID : int)
The direction parameter can have the MessageProcessingDirection values inbound, outbound, or both.
The method returns true if processing was previously active and is now suspended. It returns false if processing
was already suspended.
The method can throw the following exceptions:
• If the direction parameter is not a valid value, the method throws SOAPSenderException.
• If there are permission or authentication issues, the method throws WsiAuthenticationException.
• If ACK is invalid, the method throws IllegalArgumentException.
• If processing was in error, the method throws SOAPException.
Messaging and events 351
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• “Overview of message destinations” on page 301
• “Message error handling” on page 343
Resuming a destination
Resuming a destination generally means that PolicyCenter starts trying to send messages to the destination again.
Resuming outbound processing resumes the request and transport plugins and resumes message sending. Resuming
inbound processing resumes the reply plugin.
If a previous suspend action released any resources, resuming the destination reclaims those resources. For example,
the destination might reconnect to a message queue.
To resume both inbound and outbound messages for a destination, call the following method:
resumeDestinationBothDirections(destID : int)
The direction parameter can have the MessageProcessingDirection values inbound, outbound, or both.
The method returns true if processing was previously suspended and is now resumed. It returns false if processing
was already active.
The method can throw the following exceptions:
• If the direction parameter is not a valid value, the method throws SOAPSenderException.
• If there are permission or authentication issues, the method throws WsiAuthenticationException.
• If ACK is invalid, the method throws IllegalArgumentException.
• If processing was in error, the method throws SOAPException.
See also
• “Overview of message destinations” on page 301
• “Message error handling” on page 343
getTotalStatistics(destID : int)
To get statistics for a safe ordered message, call the following method:
getMessageStatisticsForSafeOrderedObject(
destID : int,
safeOrderedObjectId : String)
See also
• “Message status code reference” on page 339
• “Messaging tools web service” on page 347
getDestinationStatus(destID : int)
See also
• “Message status code reference” on page 339
• “Messaging tools web service” on page 347
getConfiguration(destID : int)
This information is read from files on disk during server startup, however can be modified by web services and
command-prompt tools.
The getConfiguration method takes a single argument that specifies the destination ID.
The method returns an ExternalDestinationConfig object, which contains properties matching the parameters for
the configureDestination method, such as the polling interval and the chunk size.
The method can throw the following exceptions:
• If there are permission or authentication issues, the method throws WsiAuthenticationException.
• If the destination ID is invalid, the method throws IllegalArgumentException.
Messaging and events 353
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
configureDestination(
destID : int,
timeToWaitInSec : int,
maxretries : Integer,
initialretryinterval : Long,
retrybackoffmultiplier : Integer,
pollinterval : Integer,
numsenderthreads : Integer,
chunksize : Integer )
Calling this method restarts the destination with the change to the configuration settings. The command waits for the
specified time for the destination to shut down. The method has no return value.
The method’s arguments are:
destID
Destination ID of the destination to suspend.
timeToWaitInSec
Number of seconds to wait for the shutdown before forcing it.
maxretries
The number of automatic retries to attempt before suspending the messaging destination.
initialretryinterval
The amount of time in milliseconds after a retryable error to wait before retrying sending a message.
retrybackoffmultiplier
Amount to increase the time between retries, specified as a multiplier of the time previously attempted. For
example, if the last retry time attempted was 5 minutes, and backoff is set to 2, ClaimCenter attempts the next
retry in 10 minutes.
pollinterval
The required minimum interval between polls from the start of the previous poll to the start of the next poll.
Each messaging destination pulls messages from the database (from the send queue) in batches of messages
on the batch server. The application does not query again until pollinterval amount of time passes. After
the current round of sending, the messaging destination sleeps for the reminder of the poll interval. If the
current round of sending takes longer than the poll interval, then the thread does not sleep at all and continues
to the next round of querying and sending. If your performance issues primarily relate to many messages for
each primary object for each destination, then the polling interval is the most important messaging
performance setting.
numsenderthreads
Number of sender threads for multithreaded sends of safe-ordered messages. To send messages associated
with a primary object, PolicyCenter can create multiple sender threads for each messaging destination to
distribute the workload. These threads actually call the messaging plugins to send the messages. PolicyCenter
ignores this setting for non-safe-ordered messages because PolicyCenter uses one thread for each destination
for these types of messages. If your performance issues primarily relate to many messages but few messages
per claim for each destination, then this setting is the most important messaging performance setting.
chunksize
The number of messages to read in a chunk.
The method can throw the following exceptions:
• If there are permission or authentication issues, the method throws WsiAuthenticationException.
• If the destination ID is invalid, the method throws IllegalArgumentException.
354 chapter 18: Messaging and events
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• “Message processing cycle” on page 307
• “Messaging tools web service” on page 347
See also
• Rules Guide
Procedure
1. In Guidewire Studio, navigate in the Project window to configuration→config→Plugins→registry and open
consoleTransport.gwp.
2. Replace the registered Gosu class with gw.plugin.messaging.impl.ConsoleMessageTransport.
3. Navigate in the Project window to configuration→config→Messaging and open messaging-config.xml.
4. Select the destination with ID 68, Java.MessageDestination.ConsoleMessageLogger.Name.
5. Clear the check box for Disable destination.
6. Verify the settings for this destination.
In the base configuration, some useful settings for this destination are the following:
Property Setting
Transport Plugin consoleTransport
Max Retries 3
Initial Retry Interval 100
Events \w*
This configuration specifies that PolicyCenter is to send all events to this destination and trigger Event Fired
rules accordingly.
7. Restart the PolicyCenter server.
Messaging and events 355
Guidewire PolicyCenter 9.0.6 Integration Guide
Result
After restarting the server, watch the console window for messages.
Policy‐related integrations
Guidewire PolicyCenter 9.0.6 Integration Guide
chapter 19
Rating integration
Rating is the process of obtaining a price or set of prices for policy coverage. PolicyCenter supports rating from
within PolicyCenter (internal rating) or an external rating engine. This topic discusses how to write a rating engine
to work with the built-in PolicyCenter rating framework. It also describes the relationship between cost entity
instances and cost data objects, the rating plugin, and how to implement a line-specific rating engine class.
This is the critical part of rating code for costs that make sense only as calculations using period-wide
subtotals. Consider encapsulating your actual algorithm into separate Gosu classes, one for each type of
premium.
6. Convert rating results into cost entity instances. The rating engine must adjust the rows in the database to
match the rating results. Up until this step, all the rating happens on CostData objects. Cost data objects are
non-entity class instances that mirror the role of actual Cost entity instances. There are subclasses of
CostData for each cost type, effectively mirroring the various line-of-business-specific subtypes of the Cost
entity. There are several parts of this conversion process.
a. Update reusable cost entity instances. If the rating engine can reuse an existing cost entity instance, the
rating engine updates the cost to match an updated cost data object. The rating engine updates the cost’s
effective/expiration dates, all the rating-related properties, and all amount-related properties. The rating
engine sets the properties in the cost entity instance to the values in the cost data object.
b. Create new cost entity instances if necessary. If the rating engine cannot find an existing cost entity
instance for this cost, the rating engine creates a new cost. Generally speaking, this means that there is no
cost that matches the cost’s key values and is effective on the effective date of the cost data. The rating
engine then adds a new cost by cloning an existing cost entity instance that matches on its same cost key
but for different effective dates. This ensures that the new cost entity instance shares the same version list
because they have the same fixed ID value.
c. Delete untouched cost entity instances. Cost entity instances from previous rating requests may no longer
be relevant. For example, if you rate a policy and then remove a coverage, costs for that coverage no
longer apply. If any cost entity instances do not match any cost data objects in the recent rating request,
the default rating engine deletes the cost entity instances. Before rating begins, the rating engine makes a
temporary list containing all cost entities for this policy. As the rating engine converts rating results into
Cost entity instances, it removes any updated (reused) entities from the list. After the rating engine
iterates across all cost data objects, any cost entity instances still in this list match no cost data objects in
the current request. The relevant Gosu code refers to this as the untouched list of costs. The rating engine
removes all entities in that list.
This general algorithm works for typical lines of business, and generally speaking results in easy-to-maintain and
easy-to-understand code. It also helps that for slice mode changes, the abstract rating engine class handles the more
complex parts of revisioning (date detection, cost merging, prorating) automatically.
Some lines of business are ill-suited to this approach, however. For example, in the United States for workers’
compensation, regulators mandate a certain rating algorithm that varies greatly from the way most other lines of
business generate costs.
• Draft
4. Obtain and install a license key for Guidewire Rating Management.
See also
• “Create a new policy line rating engine” on page 386
This approach helps rating engines separate the two major processes of rating.
• Determining the appropriate rates and costs, including calling out to an external system if necessary
• Persisting rating information changes in the database in the most efficient and correct way possible
Guidewire strongly recommends that you write your rating engine to populate CostData objects instead of actual
Cost entities. It is easier and safer to integrate rating using the built-in CostData objects and the built-in code that
generates and manipulates them.
The following are notable differences between Cost entities and CostData objects.
Guidewire strongly recommends that you write your rating code to use the cost data architecture and the built-in
code to manipulate them. This simplifies your rating integration code. In theory, your rating plugin can manipulate
raw cost entities. However, this approach is challenging and not recommended for the reasons stated earlier.
A cost data class includes the following important properties and methods.
• Cost-related properties – Cost-related properties defined by the corresponding cost entity.
• Revisioning properties – Cost data objects duplicate revisioning-specific fields from the Cost entity, such as the
effective date and expiration date.
• Methods that you override – Each cost data object class helps the rating engine with tasks such as finding the
related cost entity instance for this cost data object.
• API methods that you can call – Every cost data class inherits built-in APIs from the CostData class.
When modeling your costs, consider the downstream usage of financial data, including general ledger, billing, agent
commission payments and statistical reporting requirements. A general best practice is to store premium at the most
granular level required and aggregate as needed later rather than split costs when sending to downstream systems.
For example, create a Cost subtype and create multiple cost rows for similar data rather than requiring splitting a
cost when sending to a billing system. Note that adding a typekey to the cost simplifies grouping, as done in PIP
costs and Non-Owned liability costs in the Commercial Auto line.
However, creating very granular costs can create far too much data to store. In some cases, granular breakdown is
only needed for audits. In that case, a single cost with additional data attached to that cost is better than splitting an
object into many costs. An example of this multi-peril rating, where each peril requires a different algorithm that
calculates a part of the premium. You can create one cost for the coverage because this is typically how it is charged
and financially accounted.
Optionally, if you want to show the breakdown on the quote page or on reports, extend the Cost object with an array
of objects containing details for each peril. The quote page and reports can optionally show this extra information.
There are three basic strategies you could use to integrate your rating integration code into PolicyCenter.
• Focus on rating each slice, and use the built-in architecture. This strategy is the easiest and safest approach.
• Use built-in cost data objects, but rewrite slice and window logic.
• Do everything on your own with raw cost entities. This strategy is not recommended.
The following table compares and contrasts these three strategies.
already takes that time component into consideration. Notable basis-scalable objects include workers’
compensation exposures and some general liability exposures.
Each cost data subclass indicates whether to merge that cost data subclass as rate-scalable or basis-scalable.
See also
• Application Guide
It is far safer to re-rate everything than try to maintain a list of dependencies that permit selective re-rating.
Can we rate the whole policy for each slice, rather than line by line
In some cases, rating a multi-line policy is required to be one slice at a time across all lines rather than rating each
line independently. For example, one reason for this approach might be because the slice calculation includes
discounts that depend on premiums across the entire policy. The default rating approach does not automatically
support this requirement.
With additional customization, you can make this change by peforming the following steps.
1. Create a new implementation of the rating plugin based on the default rating plugin, or customize the existing
rating plugin. The built-in implementation of the rating plugin is the Gosu class
gw.plugin.policyperiod.impl.SysTableRatingPlugin.
2. Modify the plugin to rearrange the logic of how to calculate slices and call out to the rating engines for each
line. In the ratePeriodImpl method of the SysTableRatingPlugin class, find the following Gosu code.
3. Modify this code to instead iterate across slices instead of by rating engine (iterating across policy lines). The
best thing is to review the code for the base class for rating engines, which is the class
gw.rating.AbstractRatingEngine. Look at the method implementations for the method rateOnly and the
private method rateSlices. You must copy that code or similar code to the rating plugin so that it iterates
across each slices. For each slice, iterate across the rating engines for each line of business just like the code
that you found in the previous step.
4. Additionally, make whatever special rating changes you require, such as the previously-mentioned example of
discounts that depend on premiums across the entire policy.
This approach could allow you to get the advantages of using cost data objects and the AbstractRatingEngine
helper methods, but implement looping the way you want.
For most types of costs, this approach works for rate-scalable costs.
You might have a rare case in which you want non-linear proration. For example, a snow plow might have higher
cost during winter months. You could represent the winter months as one type of coverage and the non-winter
months with a different and lower coverage. However, if you want to represent the coverage as a single type of
coverage cost but with non-linear proration, this requires changes to the proration plugin.
If you want to change this logic, refer to the class gw.plugin.policyperiod.impl.ProrationPlugin in the static
inner class ForGivenRoundingLevel in the method called prorateFromStart.
There are two different places where the default rating engine assumes linear proration.
• In the proration step within the main merge-and-prorate part of the algorithm. You can workaround this by
skipping proration by explicitly setting the standard amount (CostData.StandardAmount) and the actual amount
(CostData.ActualAmount) properties on a cost data object.
• If you permit a line of business to rate only from the effective date forward, the default rating engine assumes
linear proration in some of that code. The default rating engine constructs cost data objects for costs that are
earlier in effective time than the job effective date. The default rating engine assumes that it can linearly prorate
costs that span the job effective date.
3. Set the TermAmount property on the cost data object based on the 280 day rate.
4. Set the NumDaysInRatedTerm property on the cost data object to 280.
This way, the insured sees costs that represent the entire term that do not appear prorated. The rate varies if the
period length varies, but this may be your desired behavior for some or all rating lines.
As you parse data from your external rating engine, your code might need to check flags or check for zero premium
to detect error conditions. Have conversations about error handling early in your implementation project. If your
rating engine detects errors from your external rating engine, log the error and throw an exception from your Gosu
code.
Procedure
1. Find and edit the gw.job.QuoteProcess class in Studio.
2. Remove the call to handleQuoteResponse.
3. Decide where to inject your rating code. Carefully consider where you want to inject your rating code. The
result has large consequences for how you design your asynchronous messaging code. For example, do you
want just one message payload per policy, or one per slice date?
4. Wherever you decide to add your rating code, instead of a synchronous call to your rating engine, add the
RequestQuote messaging event. A messaging event is a special signal that triggers the Event Message rule set
in the same database transaction as the current Gosu code.
5. Write new Event Fired rule set rules that listen for the event and generate a message payload for your rating
engine. It would contain important information from your policy so that it could generate prices for
everything.
6. Write a messaging transport that calls out to your rating external system.
7. Eventually your messaging transport gets a response. During the message acknowledgement (message reply)
part of your messaging plugin code, create and attach the raw cost entities based on the rating engine response.
8. Finally, your messaging transport tells PolicyCenter that rating is complete by calling the
handleQuoteResponse method on the quote process.
Next steps
Whether you use synchronous or asynchronous rating, with the built-in rating engine architecture, if an exception
occurs during rating, you must mark the quote as invalid.
See also
• “Where to override the default rating engine” on page 364
• “Triggering custom event names” on page 318
• “Generating new messages in event fired rules” on page 319
instantiates the rating engine objects. If you make your own rating engine subclasses, be sure to modify the rating
plugin to create the correct rating engine subclass based on the line of business. This topic goes into further detail
about what cost data objects and how to subclass AbstractRatingEngine.
The easiest approach is to use the built-in structure of CostData subclasses rather than directly producing Cost
entities.
Your rating code can split, merge, prorate, and sum these CostData objects until your rating calculations finish. At
that point, a built-in method of the AbstractRatingEngine class takes the list of CostData objects that each rating
engine produces and compares them with what is in the database. This code alters the Cost entity instances in the
database for this line of business. This code may do some combination of adding, modifying, splitting, and removing
cost entity instances as appropriate. This is difficult code to write safely, and hence the benefit in abstracting the
costs into the cost data objects.
Most built-in rating engine subclasses (although not all) implement rating using the following algorithm,
implemented in part by the AbstractRatingEngine class.
1. Find all dates on which anything changes in the branch. In other words, find any entity that starts or ends in
effective time. The AbstractRatingEngine class constructor implements this and sets the internal instance
variable _effectiveDates. The method rateSlice uses this information variable’s contents.
2. At each of those dates, traverse down the tree (graph). As the code traverses down the tree, it produces costs
for everything that can be rated in slice mode. Slice mode changes includes the common things like personal
auto coverage and building costs. The resulting costs are not prorated and span from the slice date to the next
slice date. The AbstractRatingEngine class method rateSlice implements this.
3. The rating engine rates each slice-mode cost. The AbstractRatingEngine class method rateSlice
implements this. Your rating engine can override this method to rate each slice.
4. The rating engine merges back together any costs that are adjacent in effective time and which are equivalent,
which means they have the same rates. There are methods in the base class AbstractRatingEngine that
perform this task.
5. Your rating engine prorates costs that do not yet have an actual amount in the ActualAmount property.
6. Rate window-mode costs (like discounts and taxes) that might depend on sums of the prior costs.
7. Take the resulting set of cost data objects and adjust Cost rows in the database to match them.
This approach is used by all built-in rating engines other than the built-in workers’ compensation rating engine.
You could describe this approach as rating down each slice and then merging costs back together. Think of this as
the down-each-slice-and-merge approach. A theoretical alternative is to find all effective-dated split dates, or at least
all relevant splits (this would be harder to determine). Next, rate across each object, such as a vehicle or coverage,
calculating rates at each relevant point and then splitting off new CostData rows when the rates change. Such an
approach avoids the need to remerge costs back together. However, it is more difficult to write easy-to-improve and
easy-to-maintain code using this approach. As a result, PolicyCenter takes the down-each-slice-and-merge approach
instead of the across-each-object-and-split-on-differences approach.
The logic for rating each particular type of object tends to share a common pattern. For rate-scalable types, the
computation usually looks like the following operations.
1. Set the base rate to the result of some lookup. The lookup result might be based on coverage terms, date, state.
2. Set the adjusted rate to the base rate multiplied by various other factors. The other factors might include the
underwriting company, driver ages, vehicle cost, and modifiers.
3. Set the term amount to the adjusted rate multiplied by the basis. Typically, the basis is 1.
4. Set the amount to the value of the following formula.
The amount computation happens during the proration phase mentioned above, not during the actual initial
rating. For basis-scalable costs, the algorithm is similar. However, the basis is generally not 1 and the rating
engine simply sets the amount to the term amount rather than prorated based on time.
See also
• For more information about rating integration strategy possibilities, see “Where to override the default rating
engine” on page 364.
• For details of writing your rating algorithm, including why and how to use standard entities for table lookups, see
“Coding your actual rating algorithm” on page 391.
See also
• “Cost data object methods and constructors to override” on page 377
• “Cost data APIs that you can call” on page 383
values, whereas some are automatically calculated. Some properties you typically compute and explicitly set the
values. See the Description column for details.
The NumDaysInCoverageRatedTerm is a method that you must implement in your rating engine. It is abstract in the
superclass AbstractRatingEngine. It returns the number of days in a standard coverage term.
package gw.lob.ba.financials
uses gw.api.domain.financials.CostAdapter
@Export
class BACostAdapter implements CostAdapter {
var _owner : BACost
construct(owner : BACost) { _owner = owner }
return transaction
}
}
Additionally, most line-specific costs (subtypes of the root cost entity) must implement a set of methods (and
properties) specific to the line. The line encapsulates these required methods and properties in a line-specific
interface with the name of the line followed by the suffix CostMethods.
For example, personal auto cost entities must implement all the methods and properties in the interface
PACostMethods. Each subtype must override (implement) these methods.
The line-specific methods typically include methods that the user interface requires to display the cost or to collate
entities for display in the Quote page.
For example, for the personal auto line of business, all costs must contain Coverage and Vehicle properties, which
are links to the relevant coverage and vehicle entity instances.
package gw.lob.pa.financials
/**
* Additional methods and properties provided by the costs that supply this interface.
*/
@Export
interface PACostMethods {
property get Coverage() : Coverage
property get Vehicle() : PersonalVehicle
}
These line-specific properties on a cost from these adapters also appear on the corresponding cost data object.
//...
To get the fixed ID Key object from an entity, simply access its FixedID property.
You can convert a fixed ID Key object to a standard direct link using the cost object method setFieldValue. Typical
code uses this method to implement the cost data object method setSpecificFieldsOnCost, which copies line-
specific (non-core) properties to the cost entity instance.
A critical difference between cost entity instances and cost data objects is how they treat links to other objects. Cost
data objects store a fixed ID Key, which encapsulates a numeric fixed ID value and the entity type of the object.
Other Gosu code in PolicyCenter use a Key object to track other types of foreign keys, but in rating-related code a
Key typically contains a fixed ID.
If rating only from the date of change forward, then the rating engine must create cost data objects that represent
existing costs prior to the change in effective time. The following steps occur.
1. The rating engine finds the relevant Cost entities that have an effective date prior to the effective date of the
change.
2. For each cost data object, the rating engine creates a cost data object using the cost data constructor that takes
an existing Cost entity. The constructor creates a cost data object that matches the existing cost.
3. If the CostData object has an expiration date that is later than the effective date of the change, the expiration
date is set to the effective date of the change. The rating engine prorates the CostData object using the new
expiration date.
For details, see the AbstractRatingEngineBase class in the extractCostDatasFromExistingCosts method.
Rating integration 377
Guidewire PolicyCenter 9.0.6 Integration Guide
To support this process, all CostData subclasses requires a constructor that takes a Cost of the appropriate type.
Contrast this with the other constructor. The other constructor takes the effective and expiration dates for a new
initialized cost data but no existing Cost entity.
For example, if a rating engine’s extractCostDatasFromExistingCosts method creates a CostData subclass, it
calls this constructor. This method is only used when rating only from the date of change forward.
The following code was taken from the personal auto cost data subtype PersonalAutoCovCostData. This
constructor takes the specific type of Cost entity as a parameter and sets local variables.
construct(c : PersonalAutoCovCost) {
super(c)
_vehicleID = c.PersonalVehicle.FixedId
_covID = c.PersonalAutoCov.FixedId
}
For each of the two types of constructors mentioned for the CostData class, there is a variant that you must use if
you plan to support multicurrency.
For the constructor that takes a Cost entity instance, the multicurrency variant takes an argument of type
PolicyPeriodFXRateCache. The PolicyPeriodFXRateCache type is a cache of financial exchange rate data. This
cache object is stored in every rating engine automatically when you based your rating engine subclass on
AbstractRatingEngine. That base class populates a property called RateCache, which contains the
PolicyPeriodFXRateCache object.
When your CostData subclass constructor calls its superconstructor, be sure to call the appropriate constructor and
pass the multicurrency information. To support the rate cache from your rating engine, reference the RateCache
property and pass it to the superclass.
For example, the cost data class for the business auto line (BusinessVehicleCovCostData) has a method signature
that takes a PolicyPeriodFXRateCache object as a parameter.
From your rating engine, reference the cache in the RateCache property of your rating engine, as shown below.
Similarly, for the constructor that takes an effective date and an expiration date, the multicurrency variant takes two
additional arguments.
• A currency (Currency) for the cost – The as-rated currency, which is the currency that was used for the rate
calculation. This is different from settlement currency, which is the currency for billing the customer.
• A PolicyPeriodFXRateCache exchange rate cache object – The financial exchange rate cache for this rating
engine.
Setting this list properly is crucial for the PolicyCenter default rating engine to merge and convert cost data objects
properly. Be extremely careful how you implement this method in new cost data classes.
Carefully consider how you implement the KeyValues method. Errors in this method corrupt rating data during the
merge process.
PolicyCenter uses the key values that you return to create an instance of CostDataKey. That object encapsulates the
key values that the default rating engine uses as it merges cost data objects.
To help in the merge process, PolicyCenter has the concept of the cost key for a given cost. This topic provides some
context about how the rating engine uses the key values property in the cost data object.
Do not confuse cost keys with Key objects, which simply contain a numeric fixed ID value and an entity type. The
fixed ID Key objects are how cost data objects store a link to a revisioned object within the policy graph.
For Cost entity instances, the key has type CostKey and includes the following properties.
• The type of the Cost
• The ChargePattern, ChargeGroup, and RateAmountType columns
• Any other columns on the Cost that are not defined on the Cost delegate and not a standard policy graph
property like cost.EffectiveDate.
Extension properties on the Cost delegate (in Cost.etx) are not part of the CostKey.
Rating integration 379
Guidewire PolicyCenter 9.0.6 Integration Guide
In contrast, for cost data objects, the key has type CostDataKey and includes the following properties.
• The CostData subtype
• The ChargePattern, ChargeGroup, and RateAmountType properties
• Any values in the CostData.KeyValues property for that cost data subclass
Compare the following statements.
• Cost entity instances are the same kind of cost for the same thing only if the values match for all properties on
their CostKey objects.
• Cost data objects are the same kind of cost for the same thing only if the values match for all properties on their
CostDataKey objects.
// This does NOT work because the cost data private variables like _line
// contain a Key object (which contains a fixed ID), not a real link to a PolicyLine entity
costEntity.PolicyLine = _line
To resolve this difference between how costs and cost data objects handle links, you can use a method called
setFieldValue on the Cost entity. The setFieldValue method takes two arguments.
• The String property name on the Cost entity
• A Key containing the fixed ID for the object to which you want to link. Alternatively, you can optionally pass a
fixed ID String directly to this method instead of a Key if you have a plain fixed ID String for some reason.
You might notice that some of the built-in rating code passes a fixed ID Key object to setFieldValue.
For example, the personal auto cost data subtype PersonalAutoCovCostData looks like the following code.
The first argument is the root PolicyPeriod for that branch. You can easily get that from the getVersionedCosts
first parameter of type PolicyLine. Simply get the PolicyLine.Branch property. The getVersionedCosts second
parameter is the fixed ID Key that identifies the desired object with a cost. Get this information from a private
variable in your cost data object. For example, the PersonalAutoCovCostData._covID property.
The createVersionList method returns that object’s version list, which is an object that can provide information
about a revisioned entity and how it changes across time. The compile-time type of this version list is an untyped
version list (typed to the version list superclass). Cast it as appropriate to the more specific type to access type-
specific properties on it.
For a real world example, a PersonalVehicleCovCostData gets the coverage version list as shown below.
For the common simple case, the target object directly contains costs for only one thing and stores it the Costs
property. In this simple case, the version list for this object also contains a Costs property. It is important to note that
this version list property does not contain costs directly. Instead, it returns a list containing one version list that
represents one or more database rows of Cost entities in the branch that represent that same thing. Your
getVersionedCosts method can return this list containing a single version list.
Rating integration 381
Guidewire PolicyCenter 9.0.6 Integration Guide
The Costs property on the version list is an example of a generated property. Gosu dynamically adds it to the
PersonalVehicleCovVersionList object because it is a property on a PersonalVehicleCov entity and contains an
array of entities.
If no such cost object exists, the version list Costs property instead contains an empty list. In other words, it is a list
containing zero version lists. Return that value to tell the rating engine that no such cost objects yet exist.
It is unsupported to return more than one version list in the list that you return from getVersionedCosts. In real
world conditions, each cost data object corresponds to no more than one fixed ID, so no more than one version list is
supported. The code that calls the getVersionedCosts method throws an exception if it gets more than one version
list.
For example, the personal vehicle coverage cost data class (PersonalVehicleCovCostData) creates a version list
and simply gets the version list property called Costs.
// Get versionlist.Costs. It contains a list of 1 version list for costs, or is an empty list
return covVL.Costs
}
However, some cases are more complex. In some cases the target object may have a Costs property but it represents
multiple types of costs. For example, a personal auto coverage may support multiple vehicles. In such a case, there is
a separate cost for each vehicle. This means that this method must iterate across all costs for the target object and
determine which cost entity instances correspond to the current cost data object.
For example, for the personal vehicle coverage cost data class (PersonalVehicleCovCostData), some costs
represent taxes, fees, or costs for vehicles other than the one we want. To find the right cost, use the where collection
enhancement method and to determine if the cost matches the current cost data object.
In the personal vehicle coverage example, the Gosu block that tests each item must match a cost object if and only if
all of the following are true.
• The cost is associated with the coverage for the cost data.
• The coverage’s cost object has the right type (PersonalAutoCovCost).
• The coverage’s cost object is for a vehicle whose fixed ID Key matches the vehicle ID stored in the cost data
object.
This example uses a separate helper method called isCostVersionListForVehicle, which determines if the cost is
for the same vehicle. Note that this helper method is actually comparing a version list for the cost not the cost entity
itself.
[...]
// Among all rows in the database for this cost, choose the one with the earliest effective date
var firstVersion = costVL.AllVersions.first()
return firstVersion typeis PersonalAutoCovCost and firstVersion.Vehicle.FixedId == _vehicleID
}
This example chooses the coverage version with earliest effective date. Although this choice appears arbitrary, cost
cannot represent more than one car and a car cannot change its fixed ID value over time. Thus, you can get any
coverage version from the version list, dereference its vehicle, and get the fixed ID from that entity instance.
An example of when you might use more complex logic in this property get function is general liability exposure
costs. The built-in cost data subclasses returns true for costs with class codes that have an auditable basis, and
false for any other class codes.
To simply get a reference to the corresponding Cost entity instance, call the cost data object method
getExistingCost. This method takes the PolicyLine to search. This method does not modify the effective window
of the returned cost. It merely finds the matching cost object, if any, that is effective as of the effective date of this
cost data object. If there is no existing cost, this method returns null.
Internally, this method calls the getVersionedCosts method, which each cost data must override.
var c = getExistingCost(myPolicyLine)
In some cases, you might want to actually create a new Cost row or modify an existing one. This choice depends on
whether there is an existing Cost instance that corresponds to this cost data with the appropriate effective dates. The
cost data object method getPopulatedCost implements this logic.
There are several possibly outcomes of getOrCreateCost.
• If there is an existing Cost at the effective date of this cost data object, this method returns it.
• If there is an existing Cost but none at the effective date of this cost data object, this method creates a new cost
entity cloned from an existing cost. If there are multiple to choose from, the rating engine chooses the one with
earliest effective date. Among other properties cloned, the fixed ID value for the new cost entity is always the
same as cloned cost. This is important to remember. The fixed IDs must be the same because both costs represent
the cost for a specific thing, just at different effective dates. The method returns the new cost object.
• If there is no existing Cost, even at other dates, the method creates a new cost entity. The new cost object has an
entirely new auto-generated fixed ID. The method returns the new cost object.
Unlike the getExistingCost method, the getOrCreateCost method never returns null.
var c = getOrCreateCost(myPolicyLine)
Finally, there is another method called getPopulatedCost. It performs the following operations.
1. Calls the public method getOrCreateCost to get the matching cost object, or creates a new one. See the
earlier description of this method in this section.
2. Calls an internal method populateCostEntity that populates the entity with the core cost properties from this
cost data object.
3. Calls the public method setSpecificFieldsOnCost, which each cost data class implements to copy all the
non-core (line-specific) cost properties from the cost data object to the Cost entity instance.
var c = getPopulatedCost(myPolicyLine)
data objects that are otherwise the same but for different vehicles or a different coverage. By properly adding
the key values for vehicle and coverage to the key values, the rating engine considers the costs different. The
rating engine does not merge together or otherwise throw them away as duplicate.
If you customize built-in entities or create entirely new cost data subclasses, remember to add entity
relationships to the KeyValues return value. Otherwise, new costs disappear during the merging process.
5. Override the cost data method getVersionedCosts. Use the new foreign key properties in the cost data object
to find the existing costs (in the database) that are for the same thing. For example, for a line-level vehicle
cost, this method must return only the ones that are for a specific vehicle and coverage.
If you customize built-in entities or create entirely new cost data subclasses, remember to consider your new entity
relationships in your getVersionedCosts implementation. Otherwise, new costs disappear during the merging
process.
The other typical thing a cost data subclass must do is to add extra properties that distinguish between costs that are
different but that connect at the same level. For example, suppose you have several possible line-level taxes, such as
state tax, uninsured coverage surcharge, and so on. You would need a tax type field that explains which tax this
represents. Like a foreign key property, add this information as a new private variable in the class, add it to the
constructor, and do all steps in the previous numbered list.
In some cases, you might need to add to cost data variables but not add them to the KeyValues return value or use
them in the cost data method getVersionedCosts. For example, you might add the following types of information.
• Useful information about the cost data, such as its rating tier
• Information that does not uniquely identify the cost in the graph, for example the cost for state tax for vehicle 1
and coverage B
A common mistake is to add new entity relationships but not add them to the KeyValues return value or add within
your getVersionedCosts implementation. This makes new costs disappear during the merging process. Be careful
to do all of these steps correctly.
Procedure
1. Create a new subclass of AbstractRatingEngine for the rating line. You must use Gosu generics syntax to
parameterize the type with the line of business class. The example below is taken from the
CommercialPropertyLine class.
2. Configure your line of business to instantiate your new rating engine class. In your PolicyLineMethods class
for your line of business, find the createRatingEngine method. This method must return an instance of your
new rating engine class. Method arguments include a rate method (RateMethod) and a set of parameters as a
java.util.Map object. Optionally use these arguments choose different rating engine subclasses. The
following example instantiates a different rating engine if the rate method is TC_SYSTABLE.
3. Create a CostData subclass for the line and further subclasses of CostData for each subclass of cost on the
line.
4. Decide whether your line can be rated from the change date forward only or whether PolicyCenter must re-
rate the whole period.
5. Override methods on AbstractRatingEngine to actually do the rate calculations. The exact methods might
vary.
6. Consider encapsulating the logic for each type of rating in a separate class for each type of rating algorithm.
You can put your actual rating formulas and table look-ups into these classes. Wherever your actual rating
code is, separate your table look-up code from your formulas.
7. If this line handles premium overrides, add relevant logic.
The methods in the following table are utility methods, helper methods for the default rating engine, or internal
methods that you override only if you significantly change the logic.
Utility methods perform the following types of functions.
• Merge and prorate CostData objects
• Calculate the number of days in the rated term based on the default policy term for the product
• Calculate a demo tax rate
• Calculate a short rate penalty rate
extractCostDatasFromExistingCosts This method take a list of costs and a cut‐off date and performs No
the following actions.
• Extracts cost data objects from any existing slice‐mode costs
on the line.
• Adds cost data objects to the internal list for any cost that is
effective prior to the given cut‐off date.
• Prorates any costs that fall across the cut‐off date boundary. In
the case of normal non‐basis‐scalable costs, the method
prorates by removing the actual amount (the ActualAmount
property) so that the cost potentially can merge with another
slice. After merging, the code re‐prorates the cost after slice
rating is complete.
The built‐in rating engine only calls this if the method
shouldRateThisSliceForward returns true.
whole policy from the period start date, for example for a cancellation. Design your code to ensure that if
PolicyCenter rates the entire period or from the change date, the rating engine always returns the same consistent
cost values.
The behavior of the built-in implementation is described below.
• Policy changes rate from the change date forward provided that the period start date did not change. The method
returns true. If the period start date changed, the method returns false.
• Reinstatements rate from the change date forward provided that the period start date did not change. The method
returns true. If the period start date changed, the method returns false.
• Cancellations always rate from the change date forward. The method returns true.
• All other jobs always rate the whole period. The method returns false.
Subclasses can override this method to return true if the rating engine must always re-rate the whole period for a
particular line of business. If the line allows for edits that are prior to the effective date, typically it is necessary to
re-rate the whole period. For example, in general liability or workers’ compensation lines, any job can result in
changes prior to the effective date of that job. This quality is a result of how users edit exposures in window mode
(not a particular slice date). If a particular rating engine never rates from the change date forward, you can override
the shouldRateThisSliceForward.
This is the case for the built-in general liability line of business rating engine because you can edit some things in
window mode. Window mode edits can cause changes to the policy prior to the effective date of the policy change.
When rating from the change date forward, at the end of the rating, PolicyCenter must contain a complete set of
CostData objects representing the entity graph and its costs. So, PolicyCenter must still create CostData objects for
each Cost already in the database even if you do not intend to rate it.
To implement this, the rating engine for every line of business must implement the existingSliceModeCosts
method. This method must determine which costs are slice mode costs (and thus might not be rated).
You also must implement the rating engine method createCostDataForCost. It must create a CostData object from
an existing cost. The actual logic that operates using these methods is in the
extractCostDatasFromExistingCosts method. It contains additional logic to un-prorate rate-scalable costs and to
prorate basis-scalable costs or overridden costs.
Next, your rating engine must set all the rating-related properties on new cost data objects.
If PolicyCenter is configured to support multicurrency, you must call the alternate constructor that contains a
financial exchange rate cache object.
In addition to creating an entirely new cost data objects from your main rating algorithm, a rating engine subclass
must override the createCostDataForCost method. This method takes the cost as a parameter. The method must
create and return a new instance of the appropriate subclass of CostData.
The built-in rating code only calls this method when rating from the slice date forward.
}
}
Of course, if you are using an external rating engine, be sure that your external engine follows this general pattern. If
you have questions about supporting these rules, please contact Guidewire Customer Support.
You must carefully implement rates and formulas, and be particularly careful with changes with real production
data. Reference dates must be consistent. Never backdate rate changes or formulas. Avoid round-off errors. If you
fail to follow these rules, customer data may be affected, and PolicyCenter has undefined behavior.
Procedure
1. Check if there is an existing cost.
2. If so, check if there are non-null values for any override properties.
3. If there are overrides, copy the appropriate properties from the existing cost.
4. Find and use override properties in your rate table lookups and algorithms.
5. Optionally, disallow user overrides for a cost by setting the Overridable property on a new cost data object to
false. The default value of Overridable is true.
6. Decide how you want to handle zero-cost costs. A real-world rating engine calculates that there is zero cost
($0) for a particular cost in some cases. Typically, the rating engine does not generate a cost row for that zero
cost. Because the premium overrides user interface allows you to override existing rows but not add new Cost
rows, by default, you cannot override a zero-cost cost. To allow users to edit (override) this cost, you can
choose to create a zero-cost Cost entity instance in these cases. If you want to do this, you must modify the
392 chapter 19: Rating integration
Guidewire PolicyCenter 9.0.6 Integration Guide
quote screen to filter out all the zero-cost rows. To edit those rows, you must show these zero-cost costs in the
premium override screen.
Rating logic does not create costs whose effective dates fall outside the audit period. For example, suppose the
policy period is from January 1, 2019 to January 1, 2020 and the audit period is for February 1, 2019 through
March 1, 2019. Rating must not return any costs that are effective prior to February 1, 2019 or which expire later
than March 1, 2019. To prevent mistakes, PolicyCenter detects this condition and throws an exception for any rule
violations.
The cost and cost data property SubjectToReporting controls what happens to the rating and billing of certain
types of costs for policies subject to reporting. The property is important if you implement rating for premium
reports.
During premium reporting rating calculations, you might want to omit some items from calculations, or handle them
differently during rating. For example, the following behaviors are employed when handling the workers’
compensation rating line.
• The expense constant is meaningful only for the period as a whole, not for any single monthly or quarterly report.
• Taxes are billed up front and at final audit. However, premium reports omit them.
• Rating can determine the premium discount percentage only by looking at the total premium for the entire period.
PolicyCenter estimates this at submission or renewal time and determines a discount percentage. During
premium reports, the system uses the percentage determined previously. It does not calculate a new discount
percentage. This is because the premium report does not calculate a full period premium so it would have no way
of deciding which discount percentage is appropriate. At final audit, PolicyCenter calculates the correct final
discount and uses it to determine final audited premium.
Personal auto cost entity Description Personal auto cost data class
PACost The root entity type for all personal auto costs. This includes a PACostData
link to PersonalAutoLine and an array of PATransaction enti‐
ties.
PAMultiPolicyDiscCost A cost value that represents multipolicy discounts PAMultiPolicyDiscCostData
Personal auto cost entity Description Personal auto cost data class
PAShortRatePenaltyCost A cost value that represents a cancellation short rate penalty. PAShortRatePenaltyCostData
PersonalAutoCovCost A cost value that adds a link to a PersonalVehicleCov and a link PersonalAutoCovCostData
to a PersonalVehicle. This line uses this cost to join together a
line‐level coverage and a particular vehicle, since line‐level cover‐
ages are priced for each vehicle.
PersonalAutoTaxCost A cost value for taxes PersonalAutoTaxCostData
PersonalVehicleCovCost A cost value for a vehicle coverage that has a link to PersonalVehicleCovCostData
PersonalVehicleCov. The link to the coverage already implies a
link to the vehicle.
The CostData classes directly mimic the Cost hierarchy for this line. There is one root PACostData class. It
contains a link to the PersonalAutoLine (a Key that contains the value of its fixed ID). There are subclasses that
correspond to each of the Cost subclasses, each with its own properties (also stored as fixed ID Key objects) where
appropriate.
The angle bracket notation indicates the use of Gosu generics. This declaration shows that the class extends the
PACostData generic class to work with the class PersonalAutoCovCost. This syntax allows the definition of
PACostData to be written in a general way to work with many types of data, but be type-safe at compile time. Some
of the rating code uses this parameter to determine which Cost entity subtype to create.
The class contains properties for the vehicle’s FixedId property and the coverage’s FixedId property. These fixed
IDs are encapsulated in a Key object.
The class has an alternative constructor that populates a cost data object based on an existing Cost row. The
superclass constructor does most of the work. This version just needs to extract out subtype-specific properties, in
this case the vehicle and coverage fixed ID Key objects.
394 chapter 19: Rating integration
Guidewire PolicyCenter 9.0.6 Integration Guide
construct(c : PersonalAutoCovCost) {
super(c)
_vehicleID = c.PersonalVehicle.FixedId
_covID = c.PersonalAutoCov.FixedId
}
In this case, the method calls a private method called isCostVersionListForVehicle to do most of the work. To
determine if a given PersonalAutoCovCostVersionList applies to this vehicle, it looks at the first (chronological)
version and check the FixedId of its associated Vehicle.
The switch statement using the type of the coverage is a fairly standard pattern in the built-in rating code, within the
rateSlice method of a line-specific rating engine.
Let us now look at the rating code for the personal auto collision coverage.
The structure in this example is typical. First, figure out the date on which to look up rates. Next, look up a base rate
factor in the demonstration system tables used for personal auto rating. Multiply those factors by various modifiers,
such as the following items.
• Chosen deductible
• Vehicle age
• Vehicle cost
• Diver’s record
• Loss history
• Underwriting company
In this example, the last line of the method calls out to the common rateVehicleCoverage_impl function. That
function sets the effective date span of the cost to be one of the following dates.
• Start date = the start of the slice to rate
• End date = the start of the next slice date
The implementation is shown below.
396 chapter 19: Rating integration
Guidewire PolicyCenter 9.0.6 Integration Guide
The method calls a standard populateCostData method that is common to both vehicle-level and line-level
coverage costs. The method copies the rates into the cost, sets the term amount, and copies the standard columns
into the actual columns.
Rating variations
Rating for some lines of business may vary significantly from the approach exemplified by the personal auto line.
The following sections discuss notable differences for very different built-in lines of business. Even if you do not
need to modify rating for these lines of business, these documentation topics might help orient yourself to potential
rating variations.
date. There are other possible reasons, such as re-rating the policy midterm to give the insured new rates mandated
by the state. Each of these reasons to split the period causes the following operations.
• PolicyCenter creates a new RatingPeriodSplitDate object, sometimes called an RPSD.
• PolicyCenter makes the CoveredEmployee exposures (class code, basis amount) split on that date.
• Modifiers also sometimes split, depending on a setting for the modifier pattern in the product model.
Fundamentally, worker’s compensation rating performs the following operations.
1. Calculate manual premium – Manual premium means applying the standard rates as published in “the manual”
to each covered employee. This is standard for all states. The rating engine iterates across the exposure rows in
the database. PolicyCenter applies the following calculation.
The user interface needs to know to display certain price subtotals after certain steps. There are a couple of times
where you need to get to a certain stage of the calculation across all states and rating periods. For example, getting a
subtotal of premiums policy-wide prior to determine the premium discount percentage.
You can think about this like certain step numbers are synchronization points in a process that is otherwise a parallel
calculation by state and rating period. For each combination of state and rating period, each calculation pauses at
that step number to perform some calculation across the full policy period. If you are interested in the details, refer
to the WCRatingEngine method called rateJurisdictionCosts.
For worker’s compensation rating steps, PolicyCenter sets up a double loop over state and rating period. It checks
whether there are any days to rate within the rating period. This is because PolicyCenter may be rating only a
premium report for 1 month, so it can skip any rating period that does not overlap with that 1 month.
The rateJurisdictionCosts method calls the processWCRatingSteps method, which sets up the loop across state
and jurisdiction. Within the loop, it calls the processWCRatingStepsByPeriod method. That method looks up data
from the configuration table and then iterates across each step. It uses a switch statement that calls code that knows
how to handle each type of step. It defines a number of different types of steps that the engine can use. Many of the
calculations that the worker’s compensation rating algorithm requires can use a generic handler. For example,
calculating a subtotal or applying a modifier. However, some of the most important calculations require specific
handlers, such as determining the expense constant or minimum premium.
In workers’ compensation, there are standard subtotals that the rating engine uses in later steps. For example,
manual premium, modified premium (after applying the experience modification), and so on. The table defines
when to calculate each standard subtotal and then which subtotal to use in subsequent calculations.
The most complex code is what happens at synchronization points, particularly for the premium discount. The basic
idea is to determine the total standard premium policy wide. Next, use that number to determine the discount percent
based on the rules for each state and (rating period start) date independently.
For a premium report, in which you only rate a portion of the period, the rating engine uses the discount percent
previously calculated, for example during submission or renewal. The rating engine does not recalculate the discount
percent during the premium report because the calculation only makes sense when rating the entire period.
each CoveragePart object. The private method ratePart checks the CoveragePart subtype and gets the
appropriate rating subclass for each type to rate that information. These part-specific rating engine subclasses extend
a base class unique for inland marine: IMAbstractPartRatingEngine.
Although the name for this class contains the words “rating engine,” IMAbstractPartRatingEngine does not
extend the rating engine root class AbstractRatingEngine. The IMAbstractPartRatingEngine is just a special
utility class for use only with inland marine rating. This class allows the default rating engine to separate the shared
rating behavior from part-specific rating calculations (such as rating the contractor equipment part).
Each of these classes have a rate method that does the actual work of rating for inline marine. The
IMRatingEngine class calls the rate method on each part-specific class. The rate method returns a list of cost data
objects (List<CostData>).
Reinsurance integration
PolicyCenter supports reinsurance handling through integration of Guidewire Reinsurance Management or your own
reinsurance management system.
Note: Guidewire Reinsurance Management is available within Guidewire PolicyCenter. To determine
whether your Guidewire PolicyCenter license agreement includes Reinsurance Management, contact
your Guidewire sales representative. Reinsurance Management requires an additional license key. For
instructions on obtaining and installing this key, contact your Guidewire support representative.
See also
• Application Guide
• Configuration Guide
PolicyCenter
Reinsurance System
PCReinsurancePlugin Legend
Custom Integration Point
{IReinsurancePlugin} plugin
web service
The plugin lets you integrate a reinsurance system with PolicyCenter. The web service lets you integrate
PolicyCenter with a claims system for the purposes of reinsurance coverage.
• IReinsurancePlugin – Plugin that lets you integrate a reinsurance system with PolicyCenter. The reinsurance
system can be Guidewire Reinsurance Management, or it can be your own reinsurance system.
• RICoverageAPI – Web service that lets claims systems, such as Guidewire ClaimCenter, retrieve reinsurance
coverage information from policies in PolicyCenter.
Legend
Reinsurable
A relates to B
A B
B relates to A RiskNumber
A B A has a B
A B A has 0 or more Bs
* A is a subtype of B PolicyPeriod PolicyRisk LocationRisk
A B
A delegates to B
ValidReinsurance *
*
*
RIRiskVersionList RIAttachmentInclusion
RiskNumber *
AllVersions
*
RIRisk
RiskNumber
* *
RIAgreement RIPolicyAttachment
A PolicyPeriod has a ValidReinsurance property that flags policies with reinsurable risks (Reinsurable and
descendants). Rules or people authorized as reinsurance managers determine which policy periods are valid for
reinsurance and what specific reinsurable risks to attach.
402 chapter 20: Reinsurance integration
Guidewire PolicyCenter 9.0.6 Integration Guide
Each reinsurable risk has a unique RiskNumber and a list of RIRisk instances (RIRiskVersionList). Each RIRisk
instance in a RIRiskVersionList represents the details of a reinsurable risk for one interval of effective time on a
policy period.
Risk entity
The RIRisk entity represents a reinsurable risk on policy period. If a policy period qualifies for reinsurance
coverage, each reinsurable risk has a list of RIRisk instances.
Method Description
Agreements Array of ReinsuranceAgreement instances associated with this risk.
Attachments Array of ReinsuranceAttachment instances associated with this risk.
Reinsurable Foreign key to the reinsurable risk (a subtype of Reinsurable) that this RIRisk describes.
Method Description
attach Attaches this RIRisk to a reinsurance agreement.
The attach method takes a reinsurance agreement (RIAgreement) and a reinsurance program (RIProgram). A
reinsurance agreement can be belong to several reinsurance programs.
canAttach Determines whether you can attach a given ReinsuranceAgreement to this RIRisk.
If errors that prevent attachment are not found, then the canAttach method returns an empty list, not null. If
errors that prevent attachment are found, then the canAttach method returns a list of the errors as human‐
readable String values.
detach Detaches a risk or policy attachment from an agreement.
The detach method has two signatures. One takes an RIRisk, and the other takes an RIPolicyAttachment.
Method Description
makeActive Makes this RIRisk of the reinsurable risk the active version. The active version is the RIRisk is the one that is in
effect today.
Property Description
RiskNumber Unique identifier of a reinsurable risk.
AllVersions Array of RIRisk instances that represent different versions of the same reinsurable risk.
AttachmentInclusions PolicyCenter creates an RIAttachmentInclusion if the inclusion status of the attachment differs
from the default, Included. Therefore, only attachments that are excluded or have special accept‐
ance have an attachment inclusion row. When you exclude an attachment, PolicyCenter creates an
RIAttachmentInclusion with the status set to Excluded.
PolicyPeriod Policy period to which all versions of a reinsurable risk provide reinsurance coverage. Each version
covers a different effective date range that does not overlap with the others. Only of one version is
active at a time, though sometimes none are active.
Method Description
addToAttachmentInclusions Adds an RIRisk to the array of RIAttachmentInclusion instances on this
RIRiskVersionList. The array name is AttachmentInclusions. An
RIAttachmentInclusion relates an RIRisk on a policy period to a reinsurance agree‐
ment.
addVersion Adds an RIRisk to the array of RIRisks on this RIRiskVersionList. The array name is
AllVersions.
endDate Splits the active RIRisk by doing all of the following operations.
• Sets ExpirationDate to today on the current RIRisk.
• Creates a new RIRisk instance with the same RiskNumber as the original.
• Sets the EffectiveDate on the new instance to today.
• Replaces all remaining fields except ExpirationDate from the original.
• Adds the new instance to the same RIRiskVersionList as the original.
Method Description
getRIRisk Gets the RIRisk that is active today.
getVersionAsOfDate Gets the RIRisk that is active for a specified date.
removeFromAttachmentInclusions Removes an RIRisk from the array of RIAttachmentInclusion instances on this
RIRiskVersionList. The array name is AttachmentInclusions. An
RIAttachmentInclusion relates an RIRisk on a policy period to a reinsurance agree‐
ment.
Reinsurance plugin
PolicyCenter provides the IReinsurancePlugin plugin interface to integrate with Guidewire Reinsurance
Management or let you integrate your own reinsurance management system with PolicyCenter. You can find the
Plugins registry for the IReinsurancePlugin in PolicyCenter Studio by navigating in the Project window to
configuration→config→Plugins→registry. The source code is in the IReinsurancePlugin.gwp file.
In the base configuration of PolicyCenter, the Gosu class PCReinsurancePlugin is a implementation of the
IReinsurancePlugin plugin interface. The PCReinsurancePlugin enables the default behaviors of Guidewire
Reinsurance Management within PolicyCenter.
PolicyCenter Legend
plugin
PCReinsurancePlugin
optional callout
{IReinsurancePlugin}
Implementation Class
{Interface}
Guidewire
Guidewire Reinsurance
Reinsurance Management
Management
Legacy Reinsurance Logic
ReinsuranceConfigPlugin
{IReinsuranceConfigPlugin}
PCReinsuranceCedingPlugin
{IReinsuranceCedingPlugin}
You might want to configure Guidewire Reinsurance Management with your own logic for assembling treaties into
programs, assigning treaties to policies, and calculating ceded premiums. For example, you extend the PolicyCenter
Reinsurance integration 405
Guidewire PolicyCenter 9.0.6 Integration Guide
data model for reinsurance with new entities or properties. So, you must configure the PCReinsurancePlugin
plugin implementation with your own logic to handle your data model extensions.
To integrate your own reinsurance system with PolicyCenter, you must write your own implementation of the
IReinsurancePlugin plugin interface. The default Gosu implementation PCReinsurancePlugin demonstrates
internal details of the methods that you must provide in your own implementation of IReinsurancePlugin.
Programs for succeeding years may either be in draft status or not yet entered into PolicyCenter. The Java class
RIProgramFinderImpl selects the program for a risk in the following order.
406 chapter 20: Reinsurance integration
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• Application Guide
Reattaching risks
PolicyCenter calls the reattachRisk method on IReinsurancePlugin to recompute program-related information
associated with the given RIRisk. This normally occurs in situations where the reinsurance programs changed. The
reattachRisk method reattaches a risk to its attachments.
Reinsurance integration 407
Guidewire PolicyCenter 9.0.6 Integration Guide
The reattachRisk method takes one argument, which is the risk that needs attachments refreshed. It computes the
attachments and returns no values.
In the default implementation for a given Reinsurable, this method performs the following operations to each
RIRisk in the RIRiskVersionList.
• Finds the one RIRisk that is effective at the edit effective date of the policy period.
• Changes the ExpirationDate of that RIRisk to the edit effective date of the policy period.
• Removes any RIRisk after that date.
In effective time, this means that the RIRisk expires on the given date. There is no future version of that risk.
Reinsurable
RiskNumber
RIRiskVersionList
Legend
RiskNumber A relates to B
A B
B relates to A
AllVersions
A B A has a B
*
RIRisk A B A has 0 or more Bs
* A is a subtype of B
RiskNumber A B
A delegates to B
CancellationDate
* *
RIAgreement RIPolicyAttachment
Validating risks
PolicyCenter calls the validateRisk method on IReinsurancePlugin to validate all risks attached to a reinsurable
at the specified validation level.
See also
• Configuration Guide
instances, but the cloned branch may contain implementation data related to the removed Reinsurable entity
instances.
See also
• “Policy period plugin” on page 166
The method must bind all of the draft version list instances associated with a branch. PolicyCenter usually calls this
method while binding a policy period.
This method takes a contact as a parameter. The method returns true if the contact can be deleted. Otherwise, the
method returns false.
The risk parameter is the Reinsurable risk from which to get the location risk group. The method returns the
location risk group as a String.
The risk parameter is the Reinsurable risk on which to set the location risk group. The method sets the location
risk group on the RIRisk associated with the Reinsurable.
Reinsurance integration 409
Guidewire PolicyCenter 9.0.6 Integration Guide
The locationRiskGroup is the location risk group from which to get the risks. The date is the date on which the
risks must be in effect. This method returns all the risks in the group as a list of riskNumbers.
The method returns a MonetaryAmount with the calculated gross retention amount.
The method returns the default inclusion type for the given reinsurance agreement and RIRisk.
410 chapter 20: Reinsurance integration
Guidewire PolicyCenter 9.0.6 Integration Guide
If you change this method to return different default values, this default value is changed, all policy periods that use
earlier default values must change. The impact is large. It includes draft and bound branches, which in turn requires
recalculating ceded premium amounts on affected policy periods.
The method returns the override amount to cede as a MonetaryAmount. If the method calculates no amount, it
returns null.
The default implementation of the getOverrideCededAmountForSurplusRITreaty method does not calculate an
override amount for how much to ceded on a surplus reinsurance treaty. It always returns null instead of a
BigDecimal.
The method returns a Date with the time portion specified. Use the value returned as the time portion of reinsurance
effective dates and intervals.
The base implementation of the ReinsuranceEffectiveTime property provides a constant Date value, 12:01 am.
You might change this implementation if you want reinsurance effective time to begin at noon instead of at
midnight.
The method returns a java.lang.String with the unique number of a reinsurable risk.
The base implementation of the generateRiskNumber method uses the gw.api.database.SequenceUtil class to
obtain a unique risk number, with the following, single Gosu statement.
You might replace the preceding statement with a call to your own reinsurance system to obtain risk numbers for
new reinsurable risks stored in PolicyCenter.
Reinsurance integration 411
Guidewire PolicyCenter 9.0.6 Integration Guide
This method returns a MonetaryAmount with the target net retention for a given RIRisk.
The default implementation of this method determines the targeted maximum retentions based on the reinsurance
program associated with the RIRisk.
You can use this method to specify additional risk criteria for the program. For example, you can specify whether
programs cover particular regions.
The default implementation does not examine the reinsurable. It considers all programs applicable.
The program parameter is the program in that the method evaluates. The method attempts to apply the program to
the reinsurable passed in the reinsurable parameter. This method returns true if the program can cover the
reinsurable.
Parameter Description
candidates A list of candidate reinsurance programs with the correct RICoverageGroup type.
Parameter Description
reinsurable The reinsurable risk.
See also
• For an example of how PolicyCenter calculates the ceded premium, see the Application Guide.
Parameter Description
period The policy period for which ceding calculations are needed.
reason The reason for needing to recalculate ceding amounts, as a code from the RIRecalcReason typelist.
comment An optional comment describing why a recalculation is requested.
To trigger calculations, an entity that needs ceding calculations must be added to the work queue. For example, with
a branch promotion, the PolicyPeriod is added to the work queue.
Parameter Description
period The policy period for which ceding calculations are needed.
recalculateAll Whether all ceding amounts on the policy period must be recalculated.
If the value is true, the method must calculate all ceding amounts attached to the policy period. If the value
is false, the method must calculate ceding amounts only for new reinsurable risks on the policy period.
reason The reason for needing to recalculate ceding amounts, as a code from the RIRecalcReason typelist.
comment An optional comment describing why a recalculation is requested.
updateUser The user to assign the activity to if the work queue change caused an error in an RIRisk.
The method takes a single parameter of type RICedingWorkItem, which is the item to evaluate for recalculation.
The method returns a boolean in which the value true indicates that ceding amounts must be recalculated on the
work item.
Parameter Description
period The period that the program affected.
dirtyPrograms The list of programs that changed.
The method returns the user who is responsible for correcting validation errors. After calling this method,
PolicyCenter assigns the user an activity to look at the job affected by the program change.
Parameter Description
policyNumber A policy number of the policy to find risks in.
coverageCode A code for the coverage pattern of a reinsurance coverage group type. The method finds risks of this reinsur‐
ance coverage group type.
date A date on which to find these risks on the policy.
The following illustration shows some of the objects accessed by this method.
PolicyPeriod
*
Coverable
getCoverage()
Coverage
Legend
A relates to B
A B
* B relates to A
Reinsurable A B A has 0 or more Bs
*
See also
• “Reinsurance risk information” on page 417
Parameter Description
policyNumber A policy number of the policy to find risks in.
Parameter Description
date A date on which to find these risks on the policy.
The following illustration shows some of the objects accessed by this method.
PolicyPeriod Reinsurable
Legend
A relates to B
A B
B relates to A
* A B A has 0 or more Bs
PolicyRisk * A is a subtype of B
A B A delegates to B
A is enhanced by B
Reinsurable
Legend
RIRisk
A relates to B
A B
B relates to A
A B A has 0 or more Bs
*
*
RIAgreement
Field Description
Agreements An array of reinsurance agreement RIAgreementInfo objects, as described below.
Description A description such as “Property coverage for Location 1” or “Auto liability coverage for Personal Auto line.” The
pattern for the description is shown below.
CoveragePattern.Name coverage for Reinsurable.DisplayName
Field Description
AgreementNumber The AgreementNumber of the agreement.
AttachmentPoint For non‐proportional agreements only, the AttachmentPoint of the agreement.
AttachmentPointIndexed For non‐proportional agreements only, the AttachmentIndexed property of the agreement.
Forms integration
For an insured customer, the physical representation of an insurance policy is a collection of forms. Different forms
define different aspects of a policy, such as coverages, exclusions, government regulations, and similar items.
PolicyCenter supports forms in the user interface. This topic describes how to integrate an external forms printing
service with PolicyCenter.
See also
• Application Guide
FormInferenceEngine.Instance.inferPreBindForms(_branch)
_branch.addEvent("IssueSubmission")
Inference data
The important method for creating inference data is the abstract method populateInferenceData. It is called by the
forms inference engine to populate this instance with the appropriate data from the policy graph. The method is
called immediately after the instance of the FormData is created.
The context argument contains information, such as the PolicyPeriod, the set of forms in the group, and the
differences between periods.
The availableStates argument contains all the states in which the form was found to be available. Any state-
specific form that replaces the national version is not included in the set.
The recommended approach to implement the method is to generate and then store inference data in a private
variable so it can be read by other methods in your class. The Form_Example class shown below assumes a built-in
personal auto form that can create towing labor coverage data like that referenced in the sample
populateInferenceData method.
@Export
class Form_Example extends FormData {
In the example, mapVehicles uses a mapVehicles method implemented in PAFormData. It uses the helper method
mapArrayToSet. The result of mapVehicles is a Map object mapping vehicles to towing information data created by
another helper method. Finally, the result is converted to a java.util.List object and sorted by the vehicle
identification number. This result must be stored in a private variable defined in your FormData subclass. Note that
the final result is a List and not an XMLNode or XML-formatted text.
The subclassed FormData class must also implement the abstract getter method InferredByCurrentData. The
method indicates whether the form is part of the policy.
The method returns true if the form is part of the policy. Even if the method returns true, however, does not
guarantee that the form will be added to the policy. The final determination depends on the processing type specified
in the FormPattern and whether the data on the form matches the data on any previous version of the form.
The following code continues implementing the sample Form_Example class. The implemented
InferredByCurrentData method references the class's _towingInfo list initialized in the sample
populateInferenceData. The method returns true if the list contains any data.
420 chapter 21: Forms integration
Guidewire PolicyCenter 9.0.6 Integration Guide
The XML output of your inference exports to text and persists to the database with the form. This persisted version
of the XML data has a special purpose. It determines whether a change to a policy triggers printing of a new form.
The XML data contains only the data that changes and is unique to this policy on the form. If the policy changes but
your forms inference class generates the same XML for it, by definition the form did not change. If the XML
exported is different after a policy change or if it is newly available, PolicyCenter knows that this is a new form.
In addition to the PolicyPeriod.Forms property that contains all forms for the policy, PolicyCenter tracks new
forms specially from the complete list of forms in the PolicyPeriod.NewlyAddedForms property. Some of these
forms may be new forms and some may be forms to reprint because of recent policy changes.
You might need one form to be duplicated for a series of items, such as separate duplicate forms for each vehicle
rather than one form that lists all vehicles.
Because PolicyCenter uses the XML output to determine whether forms need to be reprinted, in general your XML
contains only the critical variable data for this form. Be careful not to include extra data that might falsely tell
PolicyCenter that this form must be reprinted. However, in some cases you might want to include XML data that
might be useful metadata for your message to the external system but not to compare forms for changes.
You can omit certain nodes or information in the node by adding special attributes to the XML nodes. Additionally,
the FormData data class has methods on it you can use to conveniently add these attributes to an existing XMLNode. If
you call the methods, they return the original node back to make it easier to wrap or chain method calls to multiple
methods or other APIs.
For example, you can store data in attributes and use important codes or IDs for comparisons. You can, however,
ignore attributes such as class code descriptions that can change without requiring forms to be reprinted. Use the
ignoreAttributes attribute for this feature.
Alternatively, if you package your data as text content on a child node, set child nodes for package names to
ignoreAll so PolicyCenter ignores them during comparison.
The following table lists the purpose, the attribute on an XMLNode that you can set to have this behavior, and the
method name you can use to add this attribute.
The most important attributes and methods are ignoreAll and ignoreAttributes. The other methods exist
primarily for completeness.
This method returns true only if the private variable for inference data contains a non-empty list.
Method Description
createScheduleNode Creates a parent XML node and a list of child nodes. You specify a container name, a child element
name, and a list of children elements. Specify the list of children elements as an iterable collection of
String values for the text value for each child node.
createTextNode Creates an XML node with the specified name and text content.
mapArrayToSet Given an array, a filter (a Gosu block) and a mapping operation (a Gosu block), this method produces a
set as the output. The set contains the result of the mapping applied to every element in the array for
which filter returns true. If that filter argument is null instead of a block, PolicyCenter processes all
elements. If you pass an array workers’ compensation exposures, you can use this method to produce a
set of states that have exposure for a given class code. To do this, use the filter argument to accept only
exposures with the given class code and write a mapping block to extract the state from the exposure.
Additionally, several useful generic inference classes are defined in the package gw.forms.generic that might help
in your form design. The following table lists helper classes in this package.
Class Description
AbstractMultipleCopiesForm Abstract class that you can subclass to easily deal with forms with multi‐
ple instances of the same form attached to the policy. This class assumes
that the forms have a one‐to‐one relationship with some entity on the
policy. The class also assumes there is a corresponding FormAssociation
entity subtype that tracks which form points to which entity.
AbstractSimpleAvailabilityForm Base class for any form that does not need any data to be gathered and
packaged, but needs a simple availability script. Subclassing classes must
implement the isAvailable method to indicate whether or not to add
the form.
GenericAlwaysAddedForm Base class for any form to always add to a policy whenever the form is
available. Using this class with no further subclassing directly leads to a
form with no data populated. However, you can extend this class and
override the addDataForComparisonOrExport method to output your
data.
GenericRemovalAndReplacementEndorsementForm Base class for removal and replacement endorsement form. It checks if
any forms were completely invalidated or replaced and that also set this
form as their removal endorsement form number. If such a form is
found, PolicyCenter creates a form that contains a parent RemovedForms
node with a child RemovedForm node for each form completely invalidat‐
ed. Underneath that node are nodes for Description,
EndorsementNumber, and FormNumber nodes that describe the removed
form. This class creates a comparable structure for forms replaced by a
new copy of the same form.
GenericRemovalEndorsementForm Base class for a generic removal endorsement form. It checks if any
forms were completely invalidated and that also set this form as their re‐
moval endorsement form number. If such a form is found, it creates a
form that contains a parent RemovedForms node with a child
RemovedForm node for each form that became completely invalidated.
Underneath each of those nodes are Description, EndorsementNumber,
and FormNumber nodes with the actual data about the form that became
invalidated.
The usage of the term “generic” in the package and class naming of the preceding classes means the classes include
common functionality that you can subclass as desired. They do not necessarily use Gosu generics features.
However, the AbstractMultipleCopiesForm class does use Gosu generics.
If you have multiple instances of the form, your Form has multiple instances, each with its own instance of your
inference class.
Procedure
1. In the data model, create a subtype of FormAssociation.
For a personal auto form associated with single personal vehicle, create a new subtype of FormAssociation
called PAVehicleFormAssociation.
2. On that entity, add property with a foreign key link to the desired type, such as a personal vehicle.
Suppose the property is called Vehicle.
3. In your inference class, extend the AbstractMultipleCopiesForm class instead of the extending the
FormData class. This class uses Gosu generics features to abstract this class for your linked-to type.
Use the following syntax to define the inference class.
4. To support form multiplicity, add the getEntities method to your inference class. This method must return a
list containing one or more entities of your desired type. If there is more than one entity returned, PolicyCenter
knows that there are multiple instances of the form, each linked to one of the items in this list.
getEntities returns a list of all personal vehicles on the policy.
Do not implement the populateInferenceData method. That method is used only if you do not use form
multiplicity.
5. Add to your inference class the FormAssociationPropertyName method, which returns the name of the
property in your FormAssociation subtype, as a String.
Pass the String value "Vehicle" because the property name is Vehicle.
6. In your inference class XML generation method addDataForComparisonOrExport, export the data for only
one entity in your generated list of entities. Your code refers to the current entity by using the private variable
called _entity, which is set up by the AbstractMultipleCopiesForm.
The _entity variable contains one PersonalVehicle from the list returned in your getEntities method.
Your addDataForComparisonOrExport would add child XML nodes for that vehicle only.
7. In your inference class, create the createFormAssociation method to instantiate one version of your form
association subtype.
This method can use simple code, such as the following example.
Next steps
In your messaging code, you must access Form.FormAssociations to get form associations that link to the
associated entity.
implementation the FormData and AbstractMultipleCopiesForm classes support only a one-to-one mapping of
Form instance to FormAssociation. It is possible to support one-to-many mappings of Form to FormAssociation.
Supporting one-to-many mappings requires subclassing the built-in Gosu classes to manage multiple
FormAssociation objects. Your subclasses set their values and set the _entity variable before calling the XML
export method. Refer to the source code for the AbstractMultipleCopiesForm class to see how the multiplicity
code is implemented.
Forms messaging
The role of your messaging code for forms integration is to examine the list of newly added forms in the
PolicyPeriod.NewlyAddedForms property and generate messages for the newly added forms.
Your messaging destination that represents your forms printing system must listen for the issuance events such as
IssueSubmission, IssuePolicyChange, IssueReinstatement, and others for other jobs.
Your Event Fired rules must capture these events and generate one message for each form, or one message that
contains the data for all the newly added forms.
Within each form there is a property that contains the cached XML data created by the inference class. You can get
the cached XML data using code like that shown below.
cachedXML = myForm.FormTextData.TextData
You might make your message payload simply the XML payload generated from that XMLNode such as the following
code.
If you support form multiplicity, remember that you might need to access the Form.FormAssociations property to
access the form associations to access the linked entity to generate the payload.
Messaging plugins
Design your messaging transport plugin to send this message to the external forms printing system. Depending on
the external system, you could send the XML directly to the system (or to integration code that manages the system).
Alternatively, if your message contained XML, you could traverse the XML data and format the data as appropriate
for your printing system. If you use this approach, use XML APIs to convert the XML String data to XMLnode
objects.
Creating documents
If your forms printing system can integrate with a document management system (DMS), the printing system can
generate a visual representation of the form and add it to the DMS. After it does this, the integration code can call
back into PolicyCenter to let it know there is a new document associated with the policy.
Forms integration 425
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• “Document management” on page 193
PolicyCenter compares two policy branches for many reasons. A branch is a snapshot of a policy at a specific model
time for a specific logical policy period. For example, PolicyCenter compares two branches to show what changed
in a policy change job or to compare differences in a multiple-version quote. You can customize the underlying logic
that determines the differences between two policy branches. You can also customize the appearance of policy
differences in the PolicyCenter user interface.
The base configuration of PolicyCenter includes a reference implementation of the policy difference plugin in
gw.plugin.diff.impl.PolicyPeriodDiffPlugin. You modify this class or implement your own class to
customize the comparison of policy branches.
PolicyCenter provides API classes for comparison of policy branches in the gw.api.diff package and
implementations of abstract classes that you can customize in the gw.api.diff.impl package.
PolicyCenter chooses which strategy and, therefore, which plugin method to call based on the context of the request.
The following table lists the places where PolicyCenter checks for differences between policy periods, how the
check is implemented, and which strategy is used to generate the difference items.
The full set of differences that PolicyCenter needs in order to perform the underlying data actions might be more
than you want users to view in the user interface.
For example, some application tasks require generating multiple difference items, which you might consolidate and
show as a single difference to the user. For another task, you might want to omit some differences between low level
properties or window mode changes. You configure what difference items to display in the tree view within the user
interface by using a difference tree configuration XML file. You must define one difference tree XML file for each
product.
You can create these difference items directly by using their constructors, with code like the following Java lines.
Policy difference customization 429
Guidewire PolicyCenter 9.0.6 Integration Guide
Alternatively, use APIs to create difference items by comparing entities in two branches.
If you make new lines of business in PolicyCenter, create new helper classes named with the line of business as a
prefix. Your helper class encapsulates your difference logic for that line of business. Your helper class must extend
the built-in DiffHelper class. Your subclass must encapsulate the line-specific logic and call methods on other
classes such as DiffUtils as necessary.
compareEffectiveDatedFields
Compare a field on the effective dated fields to a configurable graph depth as an argument. Effective dated fields
is an object on the policy period. This object contains various fields that need to be effective dated. Those fields
cannot be on the PolicyPeriod because PolicyPeriod is always the root of the graph and never is duplicated
across effective time.
compareLineField
Compare a field on the line (passed as a String of the property name) to a configurable graph depth as an
argument.
430 chapter 22: Policy difference customization
Guidewire PolicyCenter 9.0.6 Integration Guide
comparePolicyPeriodField
Compare a field on the line to a configurable graph depth as an argument.
For example, the compareLineField method compares a String property to a specific depth in the second
argument.
diffItems.addAll(this.compareLineField("Vehicles", 3))
For advanced comparisons, you can use the methods on the DiffUtils class by accessing the DiffUtils property
in the DiffHelper base class. The property is an instance of the DiffUtils class that is instantiated with the correct
bean matcher.
PersonalAutoLine#PALineCoverages.PropertyInfo
The # syntax identifies a feature literal such as a property or method. The compareField method returns an
ArrayList of differences as DiffItem.
To customize the built-in behavior, add logic to the class that instantiates DiffUtils. For example, for personal auto
line of business, modify the PADiffHelper class, which extends DiffHelper, which instantiates DiffUtils. The
addDiffItems method adds the differences.
The following example code instantiates the DiffUtils class and compares two business lines. The code adds
differences for properties PersonalAutoLine.PALineCoverages and PersonalAutoLine.Vehicles.
...
To define a new matcher, extend the relevant abstract class that PolicyCenter provides as a base implementation of
each matcher interface in the gw.api.logicalmatch package:
• For effective-dated subobjects in a PolicyPeriod graph, extend the AbstractEffDatedPropertiesMatcher
class.
• For all other entity types, extend the AbstractPropertiesMatcher class.
In your new matcher class, override the abstract property definition for the IdentityColumns property. You use the
set of fields that uniquely identify an entity to create the IdentityColumns property of the matcher.
To assist the matching task, the LogicalMatcher interface provides the genKey method to generate a unique key for
an object. In the abstract implementations of the LogicalMatcher interface, the genKey method uses the
IdentityColumns property to create the unique key. Two objects match if this unique key is the same for both
objects. If the keys for two objects do not match, the objects definitely do not refer to the same item.
If the keys for two objects match, the objects might or might not refer to the same item. To confirm whether the two
objects are the same, PolicyCenter calls the isLogicalMatchUntyped(KeyableBean bean) method, which
optionally performs more checks. These additional comparisons could include whether a set of parent foreign keys
also match. For example, two VehicleDriver entity instances match if the foreign keys to PersonalVehicle and
PolicyDriver also match.
The implementation of the delegate-based matchers in the base configuration relies on properties on the entity,
including parent foreign key links, to determine whether two objects match.
General guidelines for writing new matchers are described below.
• You can match on whatever properties you want, but using properties backed by database columns is
recommended over using virtual properties.
Avoid matching on non-database-backed properties, such as dynamically generated Gosu properties. Contact
Guidewire Customer Support for guidance before implementing matchers that use virtual properties.
• Column values must be immutable values that never change over the life of the object. For example, an
automobile VIN does not change over time. The only reason for editing a VIN is to correct a data entry error.
isLogicalMatchUntyped
Returns true if the argument object is logically the same as the calling object and returns false otherwise.
genKey
Generates a logical key that identifies the calling object.
The KeyBasedLogicalMatcher interface provides an additional isLogicalMatch method that supports strongly
typed matching of objects. The abstract AbstractPropertiesMatcher<T extends KeyableBean> class
implements this interface. Extend this class to match objects of a class that is not effective-dated.
The EffDatedLogicalMatcher interface provides an additional findMatchesInPeriodUntyped method that
supports matching effective-dated objects. Effective-dated entity types implement this interface. The abstract
AbstractEffDatedPropertiesMatcher<T extends EffDated> class extends the
AbstractPropertiesMatcher<T extends KeyableBean> class and implements this interface. Extend this class to
match objects of a class that is effective-dated.
See the Javadoc for descriptions of the classes and methods and the lists of classes that implement the interfaces.
implements EffDatedLogicalMatcher. If you need to change the matching behavior for generating a list of
differences, you can edit that class.
Copier classes
A copier class is able to completely duplicate an entity instance. In a typical policy difference operation, the
difference generation is read-only. The difference generation itself does not need to copy data from one entity to a
duplicate of that entity.
However, in some cases, PolicyCenter uses a copier as well as a matcher. For example, an out-of-sequence job or a
preemption job might need to do the following process, which is known as DuplicateAdd.
1. Generate a policy difference between two branches to find added entity instances.
2. Use matchers to check whether new entity instances have a match elsewhere in the graph.
3. If a match exists, use copiers to ensure that the matches are fully synchronized, as defined by the entity type.
If you write a new matching class, you must write a new copier class. If a copier class does not exist, a task such as a
DuplicateAdd does not work as expected. PolicyCenter might extend an existing entity, but lose the new property
values by not copying them.
See also
• PolicyCenter Application Guide
File name Example in the base Products and LOBs that Description
configuration use the file
PolicyPeriodDiffPlugin.gs n/a All Functions to filter the list of DiffItem
objects and compare entities.
File name Example in the base Products and LOBs that Description
configuration use the file
LOBDiffHelper.gs PADiffHelper.gs All Contains the helper functions to filter
and add DiffItem objects for this line
of business.
PCBeanMatcher.gs n/a All For multi‐version policy comparisons
and other contexts for comparing two
branch graphs, this file compares prop‐
erties in entities to determine whether
two entities are the same. For example,
it checks if cars are the same by check‐
ing their VIN number.
file names vary n/a All Delegate‐based matcher files for each
type.
difftree.xsd n/a All The XSD for node generation configura‐
tion XML files.
PRODUCTDiffTree.xml PADiffTree.xml All The node generation configuration XML
file for each product. You must have
one node generation configuration file
for each product, such as PA (personal
auto) or WC (Workers’ Comp). For prod‐
ucts that have multiple lines of busi‐
ness, such as commercial package, they
share one XML file.
DiffTreePanelSet.pcf n/a All except BOP and WC. They Displays the differences tree based on
use a legacy approach to dif‐ settings in the XML file.
ferences display. (See later
rows in this table.)
DifferencesPanelSet.pcf n/a All. However, BOP and WC call Displays the differences tree based on
out to ComparisonCV.pcf and settings in the XML file.
DifferenceCV.pcf and use a
legacy approach to differences
display.
ComparisonCV.pcf n/a BOP and WC for legacy display. For multi‐version policy comparisons
If the XML file is not config‐ and similar application logic, this PCF
ured for a product, page displays the differences.
PolicyCenter uses this.
DifferenceCV.pcf n/a BOP and WC for legacy display. For policy change comparisons and sim‐
If the XML file is not config‐ ilar application logic, this PCF file dis‐
ured for a product, plays DiffItem objects in separate list
PolicyCenter uses this. views by the status of the entity: add‐
ed, removed, or changed. Additional
tabs may additionally appear and show
non‐slice changes and window mode
changes.
Alternatively, you can define your logic to apply only to certain conditions, such as the reason code that is a
parameter to the method. It is an enumeration called DiffReason containing values such as TC_POLICYREVIEW,
TC_INTEGRATION, TC_MULTIVERSIONJOB, TC_PREEMPTION, TC_COMPAREJOBS.
For example, the following code filters differences for out of sequence jobs.
if (reason == DiffReason.TC_APPLYCHANGES) {
diffHelper = new DiffHelper(reason, null, null)
diffItems = diffHelper.filterDiffItems(diffItems)
}
You may want to update or add to the logic for each line of business in the helper files such as PADiffHelper for
personal auto.
After filtering the generated difference list, if PolicyCenter needs to display the differences to users, PolicyCenter
passes the list to the difference tree generation system for furthering processing. You configure what differences the
tree view displays and how the differences appear by customizing difference tree configuration XML files.
See also
There are three ways to filter difference item display in the XML configuration.
• An ExcludedProperty element in XML excludes certain properties from displaying. An example of this is in
IMDiffTree.xml.
• If you do not define an entity in the XML file, PolicyCenter will not display it.
• On each <Entity> element in the XML file, there are attributes showadds, showremoves, and showchanges. Use
those to suppress difference adds, removes, and changes.
Do as much of your filtering in the XML files as possible. However, note that the difference tree XML file primarily
customizes the user interface.
PolicyCenter takes the already-generated list of difference items and this XML file and constructs a tree that
represents nodes in the tree at appears in the user interface.
The following steps describe how PolicyCenter uses various objects to create the difference user interface.
1. Some application flow determines it is time to recalculate the differences user interface.
2. That code calls the policy period difference plugin method recalculateRootNode. This method must do
whatever is necessary to build the difference tree and return it. More precisely, it returns the root node type,
which is RowTreeRootNode. Either base your code on the built-in implementation or modify the built-in
implementation. The built-in implementation gets the file name of the XML configuration file and then builds
the tree. The following steps describe this process in more detail.
3. Gosu code calculates which XML file to use. By default, the built-in implementation just uses the line of
business and returns a specific file. To change the default logic, customize the policy period difference plugin
method getDiffTreeConfig. In the base configuration, this method exists only on the implementation class
for the built-in plugin implementation. You can put complex logic into this. For example, you might
dynamically change which XML file to use for your product based on one or more of the following
conditions.
• Whether the user is an underwriter or a producer and show different levels of detail to each.
• The difference reason. Is this a multiple version job or comparing a policy to a history revision?
• Line of business.
• Other application context.
4. PolicyCenter loads the XML file based on its file name. It specifies how to present entities, property changes,
and how to label sections in the user interface. This file name is an argument to the constructor for the
DiffTree class, which controls much of this flow. You can view the DiffTree.gs file in Studio.
5. PolicyCenter creates an internal in-memory representation of the difference tree XML elements.
6. PolicyCenter creates a tree of node generators. A node generator knows how to generate a node in the final
tree. The node generator tree is roughly parallel to the XML element tree. However, there are important
differences. The most important differences between the XML structure and the node generator tree structure
are described below.
• In most cases property changes naturally appear under the entities they are on. Because of this, the format
implicitly creates node generators underneath entities that generate nodes for changed properties. Because of
this, compared to the input XML file structure, the generator tree has additional objects. (There are ways to
customize the property behavior, such as suppressing properties or having them display in other places in the
tree structure.)
• For any entity that you identify in the XML file, in the typical case PolicyCenter creates three node
generators. One generator knows how to display a row identifying an added object. One generator knows
how to display a row identifying a removed object. One generator (the EntityNodeGenerator) is primarily
a container for descendents in the tree. For example, changed properties for that entity appear underneath
this section.
7. PolicyCenter iterates across the list of difference items and finds the appropriate node generator for that
difference item using the following information.
• The type of the object that changed
• Whether the object was added, removed, or changed
• If a property changed, what is the property name
If PolicyCenter does not find a node generator for that information, then PolicyCenter skips this difference
item. It does not appear in the difference tree user interface.
Policy difference customization 437
Guidewire PolicyCenter 9.0.6 Integration Guide
8. For each difference item, PolicyCenter asks the appropriate node generator to generate a new node in the tree
of tree nodes. Each node is an object that implement the IDiffTreeNode interface. For example, if a property
changed, the node object contains information about how to display that specific property change.
9. Before proceeding to the next difference item, PolicyCenter must determine where in the destination tree to
put the new node. For example, suppose the difference item fixes an incorrect drivers license number for a a
driver on car. Presumably you want this change to appear underneath a tree node with a label that describes the
driver. If it is important to understand that the driver displays under a specific car, then PolicyCenter must
create a node for that label too, one level above the driver.
PolicyCenter first checks to see if the parent container for this new node already exists in the actual difference
tree yet. If it does exist, PolicyCenter sets the new node to point to its parent container. If it does not exist,
PolicyCenter asks the appropriate node generator for the parent type to generate the container node. (It knows
what generator to use by looking at the tree of node generators, which have parent links that lead up eventually
to the root.) This process recursively ensures that all new nodes are contained within ancestor nodes that tell
the user the context of the new change.
For example, suppose there are three changes on a car for an auto policy. For the first property change,
PolicyCenter asks the node generator to create the container node representing the car. For additional property
changes on that car, PolicyCenter can reuse the existing parent container node that represents the car. All three
property changes appear as child nodes underneath the car.
The result is a complete tree of IDiffTreeNode objects that describe the structure of the difference tree.
10. The user interface PCF files use the tree to display the difference tree using a tree widget.
The following diagram describes the basic flow of the difference tree creation.
There is not a one-to-one relationship between the difference items and the nodes in the final output tree. The XML
file describes what information appears and how to structure it. The number of input difference items is independent
of the number of final output nodes.
• It is common for the number of nodes in the final difference tree to exceed the number of difference items. This
is because PolicyCenter creates nodes to describe ancestors in the tree to what entities changed. Also, some nodes
describe groups solely for display purpose (these are called “sections”).
• The converse could also be true. For example if there is no reference to that entity in the difference tree XML file
or you filter out some costs. Thus, there could be more difference items than nodes in the final tree.
For example, consider a single difference item representing a change of driver on a car. The difference tree might
include multiple nodes that describe the change as well as multiple levels of context of the change , as shown in the
following line. The example shows one difference item but four nodes in the final output tree. The four nodes
include nodes that describe the ancestors of the node that describes the change. Users can see each change in its full
context.
Root of the line of business → A label that contains “Vehicles” → A specific car → The change of driver
<DiffTree xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="schema/difftree.xsd">
<Section label="displaykey.Web.Differences.LOB.Common.PolicyInfo">
<RootProperties includefromtype="PolicyPeriod" sortorder="1"/>
<RootProperties includefromtype="EffectiveDatedFields" sortorder="2">
<PropertyDisplay propertyname="OfferingCode" value="ENTITY.getOfferingName(VALUE)"/>
</RootProperties>
<RootEntity type="PolicyPriNamedInsured"
label="displaykey.Web.Differences.LOB.Common.PolicyPriNamedInsured(ENTITY.DisplayName)"
sortorder="3"/>
<RootEntity type="PolicySecNamedInsured"
label="displaykey.Web.Differences.LOB.Common.PolicySecNamedInsured(ENTITY.DisplayName)"
sortorder="4"/>
<RootEntity type="PolicyAddlInterest" showadds="false" showremoves="false"
label="displaykey.Web.Differences.LOB.Common.PolicyAddlInterest(ENTITY.DisplayName)"
sortorder="5"/>
<RootEntity type="PolicyAddress"
label="displaykey.Web.Differences.LOB.Common.PolicyAddress(ENTITY.AddressType)"
sortorder="6"/>
</Section>
<Section label="displaykey.Web.Differences.LOB.PA.Drivers">
<RootEntity type="PolicyDriver"
label="displaykey.Web.Differences.LOB.Common.PolicyDriver(ENTITY.DisplayName)"/>
</Section>
<Section label="displaykey.Web.Differences.LOB.PA.Vehicles">
<RootEntity type="PersonalVehicle">
<SubSection label="displaykey.Web.Differences.LOB.Common.Coverages" sortorder="1">
<Entity type="PersonalVehicleCov" parentpath="ENTITY.PersonalVehicle"/>
</SubSection>
<SubSection label="displaykey.Web.Differences.LOB.Common.Modifiers" sortorder="2">
<Entity type="PAVehicleModifier" parentpath="ENTITY.PAVehicle">
<Properties includefromtype="PAVehicleModifier" parentpath="ENTITY">
<PropertyDisplay propertyname="TypeKeyModifier" value="
if (ENTITY.Pattern == "PAPassiveRestraint") {
return (VALUE as PassiveRestraintType).DisplayName
} else if (ENTITY.Pattern == "PAAntiTheft") {
return (VALUE as AntiTheftType).DisplayName
} else {
return VALUE as String
}
"/>
</Properties>
</Entity>
</SubSection>
<Entity type="VehicleDriver" parentpath="ENTITY.Vehicle"
label="displaykey.Web.Differences.LOB.PA.AssignedDriver(ENTITY.DisplayName)" sortorder="3"/>
<Entity type="PAVhcleAddlInterest" parentpath="ENTITY.PAVehicle"
label="displaykey.Web.Differences.LOB.Common.PolicyAddlInterestDetail(ENTITY.DisplayName,
ENTITY.AdditionalInterestType)" sortorder="4">
<Properties includefromtype="PAVhcleAddlInterest" parentpath="ENTITY">
<PropertyDisplay propertyname="AdditionalInterestType" />
</Properties>
</Entity>
</RootEntity>
</Section>
<Section label="displaykey.Web.Differences.LOB.Common.LineCoverages">
<RootEntity type="PersonalAutoCov"/>
</Section>
</DiffTree>
Notice that this relatively small file describes all the possible changes to the personal auto line of business. One
reason it is so small is that it does not have to specify all the properties on each entity. For property changes, the
default node generation code implicitly creates nodes in the difference tree underneath each entity. You can
customize the behavior with elements and attributes to omit properties.
Section element
A section element (<Section>) is essentially a container. A section groups together various other properties and
entities. For example, the personal auto XML has several sections.
• A section for policy information
• A section for drivers
• A section for vehicles
The section contains a label expression to determine what to display as the label for the section. The label must be a
valid Gosu expression that returns a String.
Sections correspond to top level label nodes in the resulting difference tree such as Policy Info or Locations and
Buildings. Sections can have child elements of three types.
• RootEntity
• RootProperties
• Section
<Section label="displaykey.Web.Differences.LOB.PA.Drivers">
<RootEntity type="PolicyDriver"
label="displaykey.Web.Differences.LOB.Common.PolicyDriver(ENTITY.DisplayName)"/>
</Section>
<RootEntity type="PolicyDriver"
label="displaykey.Web.Differences.LOB.Common.PolicyDriver(ENTITY.DisplayName)"/>
Entity element
An entity element (<Entity>) is exactly the same as a RootEntity element except that these elements have an
ancestor element of type RootEntityElement or EntityElement. Since the ancestor entity element itself requires
an entity at node generation time, these elements must additionally supply a parentpath expression.
This parentpath expression is a Gosu expression that returns an entity of the same type as the ancestor entity
element. The expression can access a symbol ENTITY, which corresponds to the entity for the node. This symbol
automatically has the appropriate Gosu type for the entity.
Subsection element
Separate from the section element, the XML format supports the subsection element (<SubSection>). It is the same
as <Section> except that it must have an ancestor element of type RootEntityElement or EntityElement. Because
a subsection is underneath an entity in the hierarchy, it can have different types of children.
Subsection elements display differently than sections. Subsections do not have the same gray line as sections, and
subsections appear mostly like other tree elements, but with an additional level of subsections. Use subsection
elements to organize difference data into labeled folder-like sections. For example, you could organize the properties
on an entity under a label named Properties by putting a <Properties> element underneath the <SubSection>
element.
Subsection elements can have children of three types.
• EntityElement
• PropertiesElement
• SubSectionElement
Properties element
A properties element (<Properties>) is exactly the same as a RootPropertiesElement except that these elements
have an ancestor element of type RootEntityElement or EntityElement.
Because the ancestor entity element itself requires an entity at node generation time, these elements must
additionally supply a parentpath expression. This parentpath expression must be a Gosu expression that returns
an entity of the same type as the ancestor entity element. The expression can access a symbol ENTITY, which
corresponds to the entity for the node. This symbol automatically has the appropriate Gosu type for the entity.
(typically the right column). If you do not specify this attribute or set it to null, the default behavior is described
below. The first rule in the list that applies is used.
◦ Use a matching CovTermPattern.DisplayValue display value property, if applicable.
◦ Display Boolean values as either Yes or No.
◦ Typekeys use their Name property instead of the Code or Description properties. You can configure this value
with a display key.
◦ Dates use the format in the system configuration parameter DefaultDiffDateFormat. The default format is
"short."
◦ Convert the value to a String.
If you provide a value Gosu expression, none of the default display logic applies for Boolean values, typekeys, or
dates. If you want this display logic, you must explicitly replicate this display logic in the Gosu expression.
You may have to manually add entities not automatically recognized from the compare functions in DiffUtils, for
instance Effective and Expiration date differences between versions.
You can create DiffItems manually for these objects by creating an instance of one of the following classes that are
subclasses of DiffItem. For instance, DiffAdd, DiffRemove, and DiffSlice.
// Filter diffs by LOB if this is not for integration or out of sequence jobs
if ( reason != DiffReason.TC_INTEGRATION
and reason != DiffReason.TC_APPLYCHANGES) {
// Add diffs for PolicyPeriod attributes
if (currentPeriod.Renewal == null and reason != null) {
diffItems = addPolicyPeriodDiffItems(currentPeriod, currentPeriod.BasedOn, diffItems)
}
Because there are several reasons for calculating differences, you can vary your application logic based on the
difference reason. The difference reason is a DiffReason enumeration passed to the PolicyPeriodDiffPlugin
plugin method compareBranches. Choices are defined in the DiffReason typelist and include TC_INTEGRATION,
TC_MULTIVERSIONJOB, TC_PREEMPTION, TC_POLICYREVIEW, TC_COMPAREJOBS.
paDiffs.addAll(diffUtils.compareField(line1, line2,
PersonalAutoLine.TypeInfo.getProperty( "Vehicles"), 2))
In the PADiffHelper class, the filterDiffItems method filters out all unnecessarily added difference items. This
method is called from the addDiffItems method. If you want to customize which properties specific to personal
auto policies to be filtered, modify this method.
Also in the PADiffHelper class is the compareBranches method. PolicyCenter passes this method the two
PolicyPeriod objects of the two personal auto quotes, the difference reason (DiffReason), an enumeration to
specify the business context for the difference detection.
The addDiffItems method is called from the compareBranches method.
Customize this code if you need different application logic. The addDiffItems method in PADiffHelper adds
individual compared properties. For example, it adds line coverages and vehicle differences using code like that
shown below.
Refer to the PADiffHelper.gs class for full details of what it does for that line of business.
The difference tree for personal auto is contained in the PADiffTree.xml file. The user interface for the difference
tree is controlled by the XML file.
myDifferences = myPolicyPeriod.getDiffItems(DiffReason.TC_INTEGRATION)
You use code similar to this line in cases such as if you write integration messaging code to notify an external
system of changes from Policy Change jobs. You might also use this approach to compare a renewal with the period
on which it was based. However, you might prefer to use the compareTo method for renewals in some edge cases.
Policy difference customization 445
Guidewire PolicyCenter 9.0.6 Integration Guide
You use code similar to this line in cases such as if you write new PCF code to compare arbitrary revisions, or a web
service that compares two policy periods.
This topic describes web services, plugin interfaces, and tools for communicating with claim systems such as
Guidewire ClaimCenter.
Your implementation of this plugin must call out to your claim system and generate a new claim set and a series of
new claims. Populate all the required properties in the data model for the Claim and Exposure entities. Refer to the
Data Dictionary for details.
On the PolicyCenter side, you can modify the built in implementation of this API to do additional things. You could
also have different code paths depending on the size of the gross total of the loss.
criteria.setPolicyNumber("54-456353");
Calendar cal = Calendar.getInstance();
cal.set( 2019, 8, 21 );
criteria.AsOfDate = calendar.Time;
This array might contain zero items if there are no matches. It could also return more than one match if the request is
ambiguous.
Given the returned list of policy summaries, the claim system user might select one of these to get and associated
with a claim.
Retrieving a policy
After the claim system knows what policy it needs, the claim system calls the retrievePolicy method of the policy
search web service to retrieve the policy.
Claim and policy integration 451
Guidewire PolicyCenter 9.0.6 Integration Guide
The claim system identifies the requested policy by using the following items.
• Policy number of type String which corresponds to the CCPolicySummary field _policyNumber
• Effective date of type java.util.Calendar which corresponds to the CCPolicySummary field _effDate
An example invocation is shown in the following lines.
See also
• Application Guide
policySearchAPI.findPolicyPeriodPublicIdByPolicyNumberAndDate("123435", DateUtil.currentDate())
The method performs the search only against policy periods stored in PolicyCenter.
The findPolicyPublicIdByPolicyNumber method uses a policy number to find and return a policy’s public ID.
policySearchAPI.findPolicyPublicIdByPolicyNumber("123435")
The method performs the search only against policies stored in PolicyCenter.
For more general search for policies, use the web service CCPolicySearchIntegration.
http://localhost:8080/cc
• Open BillingCenter to directly view and edit account information. The file Account_BillingScreen.pcf
provides a View in BillingCenter button that uses the BCAccount exit point.
To set the URL for the exit point to BillingCenter, edit the configuration parameter BillingSystemURL
config.xml. Set this parameter to the base URL for the server as shown in the sample URL below.
http://localhost:8580/bc
You can integrate with a system other than a Guidewire core application, such as a billing system that is not
Guidewire BillingCenter. If you want to send the system additional parameters, you can add them to the URL
configuration parameter for that system. In the case of a billing system, you set the configuration parameter
BillingSystemURL it to the actual URL of the billing system and add any required additional HTTP parameters. If
the configuration parameter is absent or is set to the empty string, exit point buttons for that system in the user
interface are hidden.
LossType
*
LOBCode PolicyLinePattern
*
*
* *
PolicyType Product
* Equivalent concepts
* *
CoverageType CoveragePattern
*
CoverageSubtype
ExposureType Legend
A relates to 1 or more Bs
A B
* B relates to 1 A
A relates to 1 or more Bs
A B
* B relates to 1 or more As
*
C ClaimCenter definition
D PolicyCenter definition
For example, LOB codes in ClaimCenter are equivalent to policy lines in PolicyCenter. Policy types are equivalent
to products, and coverage types are equivalent to coverages. The generator adds new LOB typecodes to the
ClaimCenter LOB typelist that correspond to codes for new PolicyCenter policy lines. The generator adds new
typecodes to the typelists for policy type and coverage type in a similar way.
The code that you specify for a new product model pattern in the Product Designer becomes the codeIdentifier
attribute of that element in the product model. The Product Designer generates a new public ID for the new product
model pattern. The maximum length of a public ID is 64 characters. The maximum length of a code identifier for a
policy line pattern or a product pattern is 64 characters. The maximum length of a code identifier for other product
model patterns is 128 characters.
The generator uses the public-id attribute of the product model pattern and the code attribute of a ClaimCenter
typecode in the equivalent typelist to match products and typecodes. If the public-id attribute of the product model
pattern does not match the code attribute of any ClaimCenter typecode in the equivalent typelist, the generator
creates a new typecode. The generator uses the codeIdentifier attribute of the product model element to add an
identifierCode attribute to all typecodes that do not have a code identifier. The value that you use in a program to
refer to the typecode is TYPELIST.TC_IDENTIFIERCODE.
The ClaimCenter lines of business model also has typelists in its hierarchy above and below the PolicyCenter
equivalents. For example, LOB codes in ClaimCenter link to loss types. The generator does not link LOB codes to
loss types. You must link new LOB codes to their parent loss types manually in ClaimCenter Studio. Similarly, at
the bottom of the hierarchy, you must link new coverage types and coverage subtypes from PolicyCenter to
exposure types in ClaimCenter.
See also
• Gosu Reference Guide
Option Description
Input directory Location from where the generator reads ClaimCenter typelists and typelist localization files.
Output directory Location from where the generator writes ClaimCenter typelists and typelist localization files.
Map new coverages to general Specify whether the generator associates new coverages from PolicyCenter with the generic
damage exposure General Damage exposure type in the base configuration of ClaimCenter.
This option is particularly helpful during a configuration's initial‐development phase.
ClaimCenter version Specify the ClaimCenter version relevant to the input and output LOB typelists.
The following diagram illustrates the basic operation of the ClaimCenter Typelist Generator.
Input Directory
ClaimCenter ClaimCenter
LOB Typelists 0..* Typelist Localization Files
PolicyCenter PolicyCenter
ClaimCenter Typelist Product Model Display Properties
Generator
Output Directory
productModelGenReport.txt
Generated Generated
LOB Typelists 0..* Typelist Localization Files
demonstration situations. However, using the same directory for input and output prevents you from using a
difference tool to determine the typecodes that the generator changed.
In a development or demonstration environment, you generally set up a PolicyCenter and a ClaimCenter instance on
the same machine. If so, the generator can use the ClaimCenter directory that holds the lines of business typelist files
as the input and output directories. This approach avoids steps to manually copy files from and to ClaimCenter.
In a production environment, do not configure the ClaimCenter Typelist Generator to use ClaimCenter directories
for input or output.
*
CoverageSubtype
Legend
Only when configured to
link new coverages to the
* General Damage exposure type
A B A has 0 or more Bs
*
ExposureType C ClaimCenter definition
D PolicyCenter definition
Coverage subtypes duplicate their coverage types to implement many-to-many relationships between coverages and
exposures on claims.
For new coverages in PolicyCenter, the generator creates corresponding coverage types and subtypes in
CoverageType.ttx and in CoverageSubtype.ttx. To link generated coverage types to generated subtypes, the
generator adds the types and subtypes as categories of each other. Use the generated subtypes to link corresponding
coverage types to exposure types in ClaimCenter Studio.
The ClaimCenter Typelist Generator adds generic subtype typecodes in CoverageSubtype.ttx for new coverage
types. The generic coverage subtypes have the same codes, names, and descriptions as the corresponding coverages.
Typically, you link a coverage type to a single exposure type. Sometimes, you need to link a coverage to several
exposure types. For example, you want liability coverage on a claim to allow exposures for injured people and
damaged property.
type if you plan to use more specific exposure types. Otherwise, you must find and delete links to the General
Damage before you create new links to correct exposure types.
Before you run the ClaimCenter Typelist Generator, the following conditions must exist.
• You must know the location of the input and output directories.
• You must place the ClaimCenter typelist and typelist localization files in the input directory.
The generator will preserve the lines of business codes that you configured in ClaimCenter Studio or imported from
other third-party policy administration systems.
Procedure
ClaimCenter/modules/configuration/config/locale/
For example, if your instances have three locales, US English, Canadian English, and Canadian French, copy
the following files to the input directory.
• typelist_en_CA.properties
• typelist_en_US.properties
• typelist_fr_CA.properties
3. At a command prompt, navigate to the PolicyCenter directory.
4. Run the following command.
The following table lists the command arguments. These arguments do not have default values. You must
provide a value for every argument.
Argument Value
-Dinput_dir The directory that contains the input typelist files.
-Doutput_dir The directory in which to place the output typelist files.
-Dmap_coverages Whether to map new PolicyCenter coverages to the ClaimCenter generic General Damage expo‐
sure type. Specify true or false.
This option is particularly helpful during the initial development phase of a configuration.
-Dcc_app_version The ClaimCenter major version relevant to the input and output LOB typelists. Specify 8 or 9.
5. Check the output directory for generated typelist and localization files and the generation report
productModelGenReport.txt.
In the output directory, the generator creates typelist_ll_CC.properties localization files for each locale.
For example, if your instances have three locales, US English, Canadian English, and Canadian French, the
generator creates the following files.
• OUTPUT_DIRECTORY/typelist_en_CA.properties
• OUTPUT_DIRECTORY/typelist_en_US.properties
• OUTPUT_DIRECTORY/typelist_fr_CA.properties
6. Use the generation report to achieve the following goals.
• Determine success or failure of the generation command.
• If the command succeeded, identify new coverage types to map to exposure types in ClaimCenter Studio.
Next steps
To complete the integration of new lines of business into the ClaimCenter model, you perform the following tasks.
• “Copy generated files to ClaimCenter” on page 461
• “Link new lines of business types to loss types” on page 461
• “Link new coverage types to an exposure type” on page 462
• “Adding new lines of business codes to related ClaimCenter typelists” on page 463
• “Adding references to codes in Gosu classes and configuration files” on page 464
Legend
A relates to 1 or more Bs
A B
* B relates to 1 A
A relates to 1 or more Bs
LossType A B
B relates to 1 or more As
* *
*
*
CostCategory PolicyType * PolicyTab
*
*
* *
*
CovTermPattern CoverageType InternalPolicyType
*
*
*
*
LossPartyType CoverageSubtype InsuranceLine
*
ExposureType ClaimTier
ExposureTier
9. Search ClaimCenter for references to lines of business codes that the generator removed, such as references in
rules. Fix obsolete references by deleting them or changing them to use other codes.
Procedure
1. If necessary, copy generated typelist files (.ttx) to:
ClaimCenter/modules/configuration/config/extensions/typelist
2. Copy the typelist localization (.properties) files from the output directory to the ClaimCenter locale
directory.
ClaimCenter/modules/configuration/config/locale
Using the generation report to identify added coverages and LOB codes
The ClaimCenter Typelist Generator writes a generation report, productModelGenReport.txt, in the output
directory. The report includes lines for the following items.
• Coverage subtypes that the generator added to CoverageType but did not link to exposure types in
ExposureType.
• LOB codes that the generator added to LOBType but did not link to loss types in LossType.
The following example shows lines from the generation report.
...
Warning: LOB Code [BOPLine] is not mapped to any loss types.
Warning: LOB Code [GLLine] is not mapped to any loss types.
Warning: LOB Code [BusinessAutoLine] is not mapped to any loss types.
Warning: LOB Code [GolfCartLine] is not mapped to any loss types.
...
Warning: Coverage subtype [BOPBuildingCov] is not mapped to any exposure types.
Warning: Coverage subtype [BOPOrdinanceCov] is not mapped to any exposure types.
Warning: Coverage subtype [BOPPersonalPropCov] is not mapped to any exposure types.
Warning: A new default coverage subtype was created for [zfhg4jesa2eia1ht9ie8ggceba8].
It is not mapped to any exposure types.
Warning: A new default coverage subtype was created for [z98j04d2c97fv95ebf7qh3qc4rb].
It is not mapped to any exposure types.
...
Values in square brackets are typecodes that were not linked. In ClaimCenter Studio, you must link reported LOB
codes to loss types, and you must link reported coverage subtypes to exposure types.
If you chose to link new coverages to the General Damage exposure type when you ran the generator, the generation
report does not include lines for new coverage types. The generator linked all new coverage types to the typecode
GeneralDamage in ExposureType. In this case, use a difference tool to compare the input and output versions of
CoverageSubtype.ttx to identify new coverage types that you must link to exposure types.
Procedure
1. In ClaimCenter Studio, navigate to configuration→config→Extensions→Typelist, and open the LossType.ttx
file.
2. On the Line of Business tab, in the list in the LOB column, select the loss type that you want to assign to the new
coverage type.
3. Right-click the loss type, and then click Add new→LOBCode.
4. To add the new line of business type to this loss type, click the Select typecode tab.
a. Select the Typecode from the list of unassigned typecodes.
b. Click OK.
Result
The new line of business is linked to the loss type.
Next steps
To complete the integration of new lines of business into the ClaimCenter model, you perform the following tasks.
• “Link new coverage types to an exposure type” on page 462
• “Adding new lines of business codes to related ClaimCenter typelists” on page 463
• “Adding references to codes in Gosu classes and configuration files” on page 464
Procedure
1. In ClaimCenter Studio, navigate to configuration→config→Extensions→Typelist, and open the
CoverageSubtype.ttx file.
2. On the Line of Business tab, in the list in the LOB column, select the new coverage subtype.
462 chapter 23: Claim and policy integration
Guidewire PolicyCenter 9.0.6 Integration Guide
3. If the generator linked new coverages to the General Damage exposure type, expand the coverage subtype and
the Children folder, right-click the row for GeneralDamage, and then click Remove.
4. Right-click the coverage subtype, and then click Add.
To create a new exposure type for this subtype, use the New typecode tab.
a. Enter a value for Code and Name.
b. Optionally, enter a value for Description and Priority.
c. Select an Incident.
d. Click OK.
To use an existing exposure type for this subtype, use the Select typecode tab.
a. Select a Typecode from the list of existing typecodes.
b. Click OK.
Result
The new coverage is linked to the exposure type through its generic coverage subtype. In the following example,
New Coverage Subtype links to the ClaimCenter Property exposure type.
Next steps
To complete the integration of new lines of business into the ClaimCenter model, you perform the following tasks.
• “Adding new lines of business codes to related ClaimCenter typelists” on page 463
• “Adding references to codes in Gosu classes and configuration files” on page 464
4. For new CoverageType typecodes, add them as categories to appropriate LineCategory and CostCategory
typecodes.
Note that the generator writes an updated CovTermPattern.ttx and LossPartyType.ttx files, so you do not need
to change CovTermPattern or LossPartyType in ClaimCenter Studio.
Typelist localization
If you configure your PolicyCenter and ClaimCenter instances with multiple locales, the ClaimCenter Typelist
Generator helps you with typelist localization. The generator produces an updated typelist localization file for each
locale. A typelist localization file contains translated typecode names and descriptions for a specific locale for all
typelists in a Guidewire instance. ClaimCenter locale files are located in the following directory.
ClaimCenter/modules/configuration/config/locale/
The generator produces updated ClaimCenter localization files with names and descriptions for new typecodes that
come from PolicyCenter. The ClaimCenter Typelist Generator always produces a localization file for the default
locale in your PolicyCenter instance, regardless of whether you configure the instance for multiple locales.
The generator preserves names and descriptions for typecodes that do not originate in PolicyCenter. The generator
does not remove names and descriptions for typecodes that originated in PolicyCenter and now are deleted. The
generator cannot distinguish localization properties that refer to deleted PolicyCenter typecode and properties for
typecodes that originate from elsewhere. Localized strings for typecodes that are removed from PolicyCenter remain
in the ClaimCenter typelist localization files.
464 chapter 23: Claim and policy integration
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• “Run the ClaimCenter typelist generator” on page 458
• “Copy generated files to ClaimCenter” on page 461
gw.webservice.pc.pcVERSION.ccintegration.PolicyLocationSearchAPI
PolicyCenter provides this web service for integration with ClaimCenter. ClaimCenter uses the returned policy
location information to plot policy locations on the Catastrophe Search page.
PolicyCenter provide catastrophe sample data which you can use for testing.
• The geometric chord between the top-left and bottom-right of the bounding box must be less than 1/4 of the
earth’s diameter.
Billing integrations
Guidewire PolicyCenter 9.0.6 Integration Guide
chapter 24
Billing integration
PolicyCenter supports integration with any billing system by using plugin interfaces for outgoing requests and web
services for incoming requests. The PolicyCenter base configuration includes optional integration with
BillingCenter.
See also
Plugin Interface to Implement Description PolicyCenter uses during bind, issue, policy change,
Name or renewal
Billing IBillingSystemPlugin The primary mechanism for Yes. PolicyCenter calls the billing‐related plugin meth‐
system PolicyCenter to get informa‐ ods in IBillingSystemPlugin during critical parts of
plugin tion from a billing system or the process of creating or modifying a policy in
to notify the billing system of PolicyCenter. For example, for a new policy the
changes to a policy. IBillingSystemPlugin provides a list of billing plans
to choose from in the user interface. The billing sys‐
tem plugin behavior is critical to how PolicyCenter
works with billing information about a policy.
Billing IBillingSummaryPlugin To support the PolicyCenter No. In theory, you can remove the billing summary
summa‐ billing summary screens in screen from the PolicyCenter user interface, and
ry plugin the account file and policy PolicyCenter continues to work normally in other
file, implement the billing ways. In such a case, PolicyCenter would not call this
summary plugin. PolicyCenter plugin.
uses the information that this
plugin returns only for the
billing summary screen.
See also
• “Asynchronous communication between PolicyCenter and billing system” on page 472
• “Implementing the billing system plugin” on page 501
• Installation Guide
• Application Guide
See also
• “Asynchronous communication between PolicyCenter and billing system” on page 472
PolicyCenter also notifies the billing system for less common changes:
• Midterm changes to period effective and expiration dates
• Midterm change to producer of service
See also
• “Policy period plugin” on page 166
policy transaction. Because of this, the integration uses asynchronous communication in non-time-critical cases.
This makes policy and billing integration robust but non-blocking to the user interface. PolicyCenter implements
asynchronous communication by using the system wide event and message system.
The billing system plugin creates an event message, which triggers Event Fired rules, which create a message. In
another thread, a message transport sends the message to the billing system and waits for confirmation from the
billing system that it received the message.
See also
• “Messaging and events” on page 295
_branch.addEvent( BillingMessageTransport.CREATEPERIOD_MSG )
3. As PolicyCenter tries to commit the policy period’s bundle, the Event Fired rule set fires.
4. The Event Fired→Billing System→Policy Period→Bind Period rule detects this event and creates an event message.
5. The event message is put into the messaging send queue in the same transaction as the change that triggered
the event (the submission).
6. PolicyCenter in a separate thread pulls a message and delivers it to the BillingMessageTransport plugin,
which is a MessageTransport plugin.
7. The messaging transport (in BillingMessageTransport.gs) calls out to the billing plugin.
case CREATEPERIOD_MSG:
...
plugin.createPolicyPeriod(policyPeriod, getTransactionId(message) + "-2")
break
8. The currently registered implementation of the billing plugin (IBillingSystemPlugin) handles the request.
PolicyCenter includes two implementations of this interface:
• For demonstration purposes whenever a billing system is unavailable, the class
StandAloneBillingSystemPlugin implements this interface. This implementation does nothing with the
billing information and pretends that a billing system is attached.
• For the real integration with BillingCenter, the class BCBillingSystemPlugin implements this interface.
See the Gosu file BCBillingSystemPlugin.gs for this code. Wherever this documentation refers to the
PolicyCenter side of the base configuration BillingCenter integration, this class and its related
implementation typically implement this behavior. This class does not handle all integration tasks. For
example, PolicyCenter handles some behaviors by using web services that PolicyCenter publishes.
9. In the createPolicyPeriod method, the plugin handles the request by calling web service (SOAP API) calls
on BillingCenter:
return publicId
}
10. PolicyCenter calls its billing plugin method createPolicyPeriod, which would do different things for
different billing systems. In the BillingCenter integration, PolicyCenter integration code constructs an
IssuePolicyInfo object that is specific to web services that BillingCenter publishes. These SOAP objects are
Billing integration 473
Guidewire PolicyCenter 9.0.6 Integration Guide
not Guidewire entities. The web service implementation on the BillingCenter side transforms this SOAP-
specific object into what it calls a billing instruction. BillingCenter uses these billing instructions to track
charges and instructions from the policy system.
See also
• “Billing instructions in BillingCenter” on page 480
• “Messaging and events” on page 295
http://server/bc
If you need to integrate with billing systems other than BillingCenter and that system requires additional parameters,
you can add them to the URL. If this parameter is absent or set to the empty string, the exit point buttons in the user
interface are hidden. (If the entry-point URL syntax is different enough from what BillingCenter uses, modify the
PCF code for the Exit Point.)
If you need to create additional Exit Points in either application, carefully consider how you want them to work
before implementing them. For example, you might want BillingCenter to have a new exit point to PolicyCenter so
that a BillingCenter user can view PolicyCenter policy file information. Some things to consider in your
integrations:
• How do you want this exit point to appear in the user interface?
• How do you want authentication to work between the applications? Are you using a single-sign-on authentication
system? Do you have completely different sets of users for each application?
• How do you want to set permissions for BillingCenter users? For example, do you want to support BillingCenter
users creating and editing PolicyCenter Policy File notes? Do you want to limit users to certain note types?
474 chapter 24: Billing integration
Guidewire PolicyCenter 9.0.6 Integration Guide
For assistance designing and implementing exit points between applications and setting up permissions in each
application, contact Guidewire Customer Support.
IMPORTANT Do not pass Guidewire entities directly between applications. Encapsulate your data in
Gosu classes that your web services expose as method parameters and as return types.
commission to the producer who holds a particular producer code. The producer also receives notices related to
agency billing.
BillingCenter uses only some properties on producers and producer codes. Specifically, it uses properties related to
commission and agency bill plans. PolicyCenter sets initial values for those properties in entity instances that it
creates, so that you do not have additional setup in BillingCenter for simple cases. You edit these properties in
BillingCenter.
PolicyCenter propagates the following producer information to BillingCenter asynchronously:
• New producers
• New producer codes
• Changes to name and contact information on a producer
• Changes to status on a producer code
If you make a change to a Contact entity in PolicyCenter, BillingCenter updates the PrimaryContact entity,
including properties on subobjects such as Address. The producer record that PolicyCenter sends to the billing
system is the producer of record, not the producer of service.
If you change the Code, Organization, or ProducerStatus property in a producer code, PolicyCenter sends a
message to BillingCenter to update the producer code. In the PolicyCenter base configuration, you can only change
properties for which the application is the system of record.
The following table shows how the integration populates PolicyCenter properties to BillingCenter properties. The
table also shows which application is the system of record for each property.
The list of commission plans that PolicyCenter re‐ PolicyCenter CommissionPlan CommissionPlanID
trieved from BillingCenter.
See also
• The Data Dictionary
Direct bill commission payment properties. Defaults BillingCenter Not applicable Direct bill commission
in BillingCenter to sending a check every month on payment properties
the first day of the month.
Agency billing plan. PolicyCenter displays a list of BillingCenter AgencyBillPlan AgencyBillPlan
agency bill plans retrieved from BillingCenter.
Account representatives. Optional in BillingCenter. BillingCenter Not applicable AccountRep
PolicyCenter does not send a value.
Unique identifier for the producer within Guidewire BillingCenter PublicID PublicID
applications.
See also
• The Data Dictionary
Billing accounts
PolicyCenter shares account information with BillingCenter. There is a one-to-one mapping between a PolicyCenter
account and a BillingCenter account currency group. BillingCenter supports multiple accounts in an account
currency group to support billing and payments in multiple currencies. PolicyCenter uses a single account regardless
of the currency that a transaction uses. BillingCenter sends invoices from the applicable account for the currency. In
the base configuration, BillingCenter uses a separate invoice stream and designated unapplied fund for each policy.
Communications from PolicyCenter to BillingCenter use the BillingCenter account that has the necessary currency
for the transaction.
PolicyCenter sends messages to create accounts in BillingCenter whenever the first policy for an account binds.
PolicyCenter sends a message to BillingCenter to update the account whenever the following occur:
• A change to the account holder
• An addition or update to a billing contact
The native structure of the Account entity differs between the PolicyCenter and BillingCenter applications. Some
properties on accounts are used only by BillingCenter. These properties are related to billing plan and other account-
level settings for invoicing. PolicyCenter sets initial values for those properties in entity instances that it creates, so
that you do not have additional setup in BillingCenter for simple cases. You must edit these properties in
BillingCenter if you need to change them later.
PolicyCenter propagates the following account information to BillingCenter asynchronously:
• New accounts, but only if the first policy for that account is bound
• Changes to an account holder
• Adding a billing contact
• Changes to contact information for a billing contact
PolicyCenter does not access other accounts that your billing system might store.
Business property System BillingCenter Account entity properties PolicyCenter Account entity proper‐
of record ties
The account number PolicyCenter AccountNumber AccountNumber
that serves as the
unique ID for mapping
between the applica‐
tions.
Account name. Policy PolicyCenter AccountName For an account holder that is a compa‐
Center uses different ny, AccountHolderContact.Name. For
properties on the ac‐ a person, AccountHolderContact.
count holder entity for FirstName and
the name of a person AccountHolderContact.LastName.
or a company.
Service tier for the ac‐ PolicyCenter ServiceTier ServiceTier
count.
Billing plan for the ac‐ BillingCenter BillingPlan Not applicable
count. BillingCenter
has default values.
Meaning of the bill BillingCenter BillDateOrDueDateBilling Not applicable
date. Optional in
BillingCenter. Defaults
to DueDateBilling.
Invoice frequency, ba‐ BillingCenter InvoiceDayOfMonth, InvoiceDayOfWeek, Not applicable
sis, and due day. Op‐ FirstTwicePerMonthInvoiceDayOfMonth,
tional in BillingCenter. SecondTwicePerMonthInvoiceDayOfMonth
Defaults to monthly in‐
voicing with a due day
of 15.
Delinquency plan. De‐ BillingCenter DelinquencyPlan Not applicable
faults in BillingCenter.
Invoice delivery types. BillingCenter InvoiceDeliveryType Not applicable
Optional in
BillingCenter. Defaults
to Mail.
Payment method. Op‐ BillingCenter DefaultPaymentInstrument. Not applicable
tional in BillingCenter. PaymentMethod
Primary payer. If BillingCenter From the Contacts array, the In priority order, from the
BillingContact ex‐ AccountContact that has its PrimaryPayer AccountContacts array, the
ists, use property set to true AccountContact that has in its Roles
BillingContact. Oth‐ array an AccountContactRole with a
erwise, use subtype of:
AccountHolder. • BillingContact
• AccountHolder
Account holder. In the PolicyCenter From the Contacts array, the From the AccountContacts array, the
base configuration of AccountContact that has in its Roles array AccountContact that has in its Roles
PolicyCenter, each ac‐ an AccountContactRole with the Role prop‐ array an AccountContactRole with a
count has only one ac‐ erty set to AccountRole.Insured subtype of AccountHolder
count holder.
Billing contact BillingCenter From the Contacts array, the From the AccountContacts array, the
AccountContact that has in its Roles array AccountContact that has in its Roles
an AccountContactRole with the Role prop‐ array an AccountContactRole with a
erty set to AccountRole. AccountsPayable subtype of BillingContact
See also
• The Data Dictionary
Billing plan
The billing plan contains rules about invoicing and due dates at the account level. For example, a billing plan
contains all billable charges for the policies in the account that will be direct billed. The billing plan reflects the
typical way that the insurer does business and is not usually an option that the producer or underwriter chooses.
Therefore, PolicyCenter does not display the billing plan. If BillingCenter creates a new account as a result of the
integration, the account uses the default billing plan. A BillingCenter script parameter defines the default billing
plan.
The billing plan can include:
• Thresholds, such as the balance value below which an invoice is unnecessary
• Whenever payment is due
• How much charge detail to show on the invoice
The PolicyCenter base configuration does not directly use billing plans or provide an integration for this
information.
See also
• “Billing Plans” in BillingCenter Application Guide
• Configuration Guide
Delinquency plan
The delinquency plan determines under which conditions the account becomes delinquent. The plan defines the
normal business practices of the insurer and is not usually an option that the producer or underwriter chooses.
Therefore, PolicyCenter does not display the delinquency plan. If BillingCenter creates a new account as a result of
the integration, the account uses the default delinquency plan. A BillingCenter script parameter defines the default
delinquency plan.
See also
• “Delinquency Plans” in BillingCenter Application Guide
• Configuration Guide
Invoicing
The frequency and timing of invoicing (due on the 25th of every month, for example) is based on the installment
plan of each policy in the account. However, if the account has account-level charges and no policies in the account,
BillingCenter generates an invoice based on InvoiceDayOfMonth. If necessary, BillingCenter uses the account
defaults to create a monthly invoice stream. In the base configuration, BillingCenter uses a separate invoice stream
for each policy. BillingCenter links the stream to an unapplied fund, which can be used for multiple policies. You
can choose to use a new invoice stream on policy renewal.
See also
• “Billing instructions in BillingCenter” on page 480
Contacts
In PolicyCenter, each account must have one AccountHolder contact. Each account can have zero or more account
contacts of type BillingContact and AccountingContact. There can also be one BillingContact on each
PolicyPeriod. PolicyCenter sends all account contacts with AccountHolder and BillingContact roles to
BillingCenter. BillingCenter sets the Insured role on the contact to identify the account holder contact and the
Accounts Payable role to identify the billing contact.
Billing integration 479
Guidewire PolicyCenter 9.0.6 Integration Guide
Service tier
Service tiers enable an insurer to provide special handling or value-added services for certain customers, typically
high-value customers. For an integration with BillingCenter, every time a submission is bound and issued in
PolicyCenter, PolicyCenter sends the service tier on the account to the BillingCenter account.
The integration maps the optional PolicyCenter Account.ServiceTier property to a BillingCenter
Account.ServiceTier property. In PolicyCenter, the typekey values for ServiceTier are configurable.
See also
• Application Guide
See also
At the time that PolicyCenter binds a job that can generate premium transactions, PolicyCenter sends a billing
instruction to BillingCenter. Even if there are no charges, BillingCenter may need to know about a change to the
policy period, such as knowing whether the period was canceled or reinstated. The following table summarizes what
type of billing instruction PolicyCenter sends for different situations. A factor that determines what to send is
whether PolicyCenter created a new policy and/or new period.
See also
See also
• “Policy period plugin” on page 166
Instead, the property indicates whether the insured confirmed the new term. If you use this feature, you may want to
send this information to the billing system while creating new terms in the billing system.
If you use BillingCenter, the base configuration billing system plugin sends this information to the billing system in
the billing instruction TermConfirmed property.
If this property changes in PolicyCenter again, PolicyCenter calls the billing system plugin method
updatePolicyPeriodTermConfirmed. If you use BillingCenter, the base configuration plugin implementation
updates this information in BillingCenter.
If the billing system needs to later change the setting in PolicyCenter, PolicyCenter publishes a web service that an
external system can call. External systems can call the confirmTerm method in the PolicyRenewalAPI web service.
See also
See also
If in PolicyCenter, the Producer of Service changes midterm, PolicyCenter does not push an update to BillingCenter.
When Producer of Service becomes Producer of Record on renewal, PolicyCenter pushes that producer to
BillingCenter with the new policy period.
To give some commission credit to the new producer midterm, you must make the change in BillingCenter.
The most straightforward way to change the producer of record is to issue a cancel and rewrite in PolicyCenter. That
change sends the new producer to BillingCenter as part of the new policy period.
If you must change the producer of record without a rewrite, you must perform additional customization so that
PolicyCenter has the following behavior:
• Allows editing of producer of record in a policy change.
• Sends the producer change to BillingCenter.
• Provides a means to determine the midterm commission treatment for that change. The commission either has a
default value or requires a change in the PolicyCenter user interface that requests the value from the underwriter.
The base configuration implementation does not support this feature.
Re‐ How PolicyCenter renews a policy If the insured pays If the insured does not
newal pay
flow
Bind In the typical case, renewal occurs By this time, the policy is already issued. No special By this time, the policy is
and without user intervention. First, action happens. already issued.
cancel PolicyCenter quotes the renewal. If you use BillingCenter,
Next, PolicyCenter sets the job and BillingCenter does
workflow status to Renewing. The not receive a payment,
workflow behavior after this status BillingCenter instructs
change is configurable, based on PolicyCenter to perform
how close the current date is to the a “cancel for non‐
effective date of the renewal. If the payment”. The delin‐
renewal effective date is sufficient‐ quency plan determines
ly in the future, the workflow whether BillingCenter
waits. After a configurable date, specifies a flat cancel or
such as 30 days before the renewal midterm cancel.
effective date, the workflow auto‐ After BillingCenter re‐
matically issues the renewal. quests cancellation of
On issuance of the policy renewal: the policy, any money re‐
• PolicyCenter sends charges to ceived after any cancella‐
BillingCenter. tion remains in the ac‐
count unapplied fund.
• The PolicyTerm.Bound
property becomes true.
Re‐ How PolicyCenter renews a policy If the insured pays If the insured does not
newal pay
flow
Before PolicyCenter automatically
sets the workflow status to
Renewing, you can manually make
this change in the user interface.
Within the policy renewal job, click
Edit, make changes, click Bind Op-
tions, and then click Renew. The job
workflow status becomes
Renewing.
Before PolicyCenter automatically
issues the policy, you can manually
make this change in the user inter‐
face. Within the policy renewal job,
click Edit, make changes, click Is-
sue Now. The renewal immediately
issues.
Re‐ In the typical case, renewal occurs The billing system sends PolicyCenter notice of pay‐ If the workflow status is
newal without user intervention. First, ment by using the PolicyCenter PolicyRenewalAPI Renewing, the job waits
offer PolicyCenter quotes the renewal. web service method for the insured to re‐
Next, PolicyCenter sets the job notifyPaymentReceivedForRenewalOffer. spond to the offer.
workflow status to Renewing, If you use BillingCenter, this happens because If the insured did not re‐
which is a waiting state. BillingCenter registers the payment including the of‐ spond by the renewal
When the job workflow status fer reference number. BillingCenter holds the pay‐ deadline, the workflow
changes to Renewing, you must ment as a suspense payment with an associated of‐ job status changes to
configure your Event Fired rules fer reference number. A suspense payment is a pay‐ Not Taken (NotTaken)
to send an offer to the insured: ment not yet matched to an account and a policy. status.
• The base configuration does BillingCenter then calls the PolicyCenter If the workflow status
not provide an integration to PolicyRenewalAPI web service as mentioned earlier. changed to Not Taken
send an offer to the insured. The PolicyCenter PolicyRenewalAPI web service and money arrives after‐
You can decide whether to binds the policy. Binding the policy sets the ward, the billing system
provide the insured with a PolicyTerm.Bound property to true. tells PolicyCenter about
single payment plan or multiple the payment received.
options. To get the payment PolicyCenter does not
plans, configure PolicyCenter to accept this request. In‐
request this information from stead, PolicyCenter re‐
the billing system. Include any turns an error to the bill‐
payment plan information on a ing system that the re‐
renewal offer letter. newal is incapable of re‐
• The offer must contain a newal. If you use
reference number to identify BillingCenter,
this job. Use the renewal job ID BillingCenter creates an
as the PolicyCenter offer activity for someone to
identifier. look into the new pay‐
In some cases, the automatic re‐ ment that it cannot ap‐
newal does not reach the ply.
Renewing status, for example, if
the policy had approval problems.
In the policy renewal job, click
Quote. The renewal offer status
changes to Renewing. This status
change causes your Event Fired
rules to send the offer letter to the
insured.
At this point, the property
PolicyTerm.Bound is false.
Re‐ How PolicyCenter renews a policy If the insured pays If the insured does not
newal pay
flow
Con‐ The confirmed renewals flow can After receiving sufficient payment for the renewal, Eventually, the billing
firmed be summarized as follows: the billing system notifies PolicyCenter. For example, system notifies
renew‐ • PolicyCenter binds and issues the billing system calls the PolicyCenter PolicyCenter of a Not
al the renewal. PolicyRenewalAPI web service method Taken cancellation. All
• PolicyCenter waits for confirmTerm. Not Taken cancellations
confirmation from the insured The confirmTerm method performs the following ac‐ are flat cancellations.
that the insured wants the tions:
policy. PolicyCenter sets the • PolicyCenter sets Policy.PolicyTerm.Bound to
property PolicyTerm.Bound to true.
false until receiving sufficient • PolicyCenter sends a message to the billing
payment. system to confirm the renewal.
The following table lists how to configure each type of renewal flow.
If you want to choose different renewal flows for different renewal jobs, add your own logic for the plugin methods
described in the previous table. For any renewal job, your policy renewal plugin logic must define exactly one
renewal flow. For example, for one renewal job you cannot return true for both doesRenewalRequireConfirmation
and isRenewalOffered.
In the base configuration, all lines of business use the bind-and-cancel flow.
date. The fact that no renewal term yet exists because the job is unfinished complicates the question of coverage
and billing
• For renewal offers, BillingCenter is not in charge of the invoicing for the renewal offer itself. Some insurers want
BillingCenter in charge of the renewal offers, particularly for receiving electronic payments.
See also
Depending on what regions you support and the laws, you might need this method to vary the result by jurisdiction.
For example, in the United States, some states allow bind-and-cancel. However, some states prohibit it because they
do not want insurers to bind a policy before payment.
See also
See also
• “Renewal offers flows” on page 492
• “Billing flow for new-period jobs” on page 484
See also
• “Policy renewal web services” on page 126
See also
• “Billing flow for existing-period jobs” on page 487
• “Billing implications for premium reporting” on page 497
Delinquency cancellation
The primary example of delinquency cancellation is cancellation for non-payment. If there are overdue invoices,
BillingCenter starts a delinquency process. As part of the delinquency process, BillingCenter tells PolicyCenter to
494 chapter 24: Billing integration
Guidewire PolicyCenter 9.0.6 Integration Guide
cancel as soon as possible, ideally immediately. In the base configuration, PolicyCenter calculates the actual
cancellation date by using the minimum lead time required by law.
If BillingCenter starts a cancellation, the integration performs the following steps:
1. BillingCenter sends a message to PolicyCenter to cancel.
2. PolicyCenter cancels the policy.
3. PolicyCenter sends a Cancellation billing instruction back to BillingCenter.
4. BillingCenter marks the policy period as canceled on receipt of the Cancellation billing instruction.
See also
• “Choosing the renewal flow type” on page 489
• “Billing implications of renewals or rewrites” on page 489
Billing integration 495
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
PolicyCenter cannot calculate the total amount due because PolicyCenter does not know the amount that the billing
system already collected. PolicyCenter and BillingCenter do have the following information:
• PolicyCenter knows the difference between the audited premium and what was previously sent to billing in
transactions that PolicyCenter already charged. Call this amount X.
• BillingCenter knows the value of currently uncollected amounts, including anything that might not yet have
billed, if that is possible. Call this amount Y.
The total due is X+Y, just as it would be for any new charges. The package that the insurer sends to the policyholder
typically includes the following:
• An invoice showing any open balance plus any new charges including audit amount X
• An audit report showing Total Audit Premiums and Change in Premiums. This is the data from the two tabs on
the quote page in PolicyCenter that explains the value derived in the amount X.
An insurer can optionally add code to PolicyCenter to call out to a billing system to display difference between the
final audit and the amount paid. This would not change what PolicyCenter must send to the billing system but it
might amend what to print on the final audit statement.
496 chapter 24: Billing integration
Guidewire PolicyCenter 9.0.6 Integration Guide
the amount received. The base configuration integration to BillingCenter includes information about whether the
payment was received. BillingCenter uses this information to create a PremiumReport billing instruction.
However, it is more common for a billing system to receive the premium report payment before the premium report
notification from PolicyCenter. Checks and reports are often send together and the insurer usually deposits the check
immediately before the report arrives in the audit department for data entry. If so, the billing system assigns the
payment to the account as a suspense payment and waits to receive the report.
The BillingCenter part of the integration sets the Premium Report due date as the override PaymentDueDate on the
premium report. This ensures that BillingCenter knows to expect the payment by that date rather than waiting for the
typical next invoice plus 30 days date.
See also
• “Billing flow for existing-period jobs” on page 487
Deposits in cancellation
Handling of deposits differs depending on when a cancellation occurs.
Midterm cancellation
In PolicyCenter, whenever the midterm cancellation binds, the policy period has a pending (scheduled or in
progress) final audit. PolicyCenter resends the existing collateral requirement to BillingCenter. PolicyCenter does
not recalculate the deposit amount. Even though the cost of the policy reduces after cancellation, PolicyCenter does
not reduce the deposit requirement explicitly. After BillingCenter processes the final audit, the billing system can
return any extra money to the insured.
Flat cancellation
For PolicyCenter, when the flat cancellation binds, the policy period does not have a pending final audit. In the
process of BillingCenter processing the cancellation request, the collateral billing instruction releases the deposit by
sending $0 (zero dollars) as the new collateral requirement.
In BillingCenter, the active collateral requirement status changes to closed. BillingCenter releases money paid and
held as “cash held by requirements” balance, which sets the money to the category of collateral cash held. The
collateral cash is available for transfer. Typically, the insurer eventually transfers this amount to either pay off the
final audit balance or apply the funds to the segregated collateral requirement of the renewal policy period.
See also
• “Payment integration” on page 512
• “Payments Web Service APIs (PaymentAPI)” in BillingCenter Integration Guide
IMPORTANT Your billing system plugin code is called as part of an asynchronous task that the
messaging system manages. It is not called as part of the original database transaction for the
change that triggers the call to the billing system.
7. Your plugin code must always act on the PolicyPeriod passed to it. Because this is asynchronous,
theoretically multiple changes might happen to a policy before all the messages are processed by the
messaging system. By the time your plugin is called, it might actually not be the most recently bound version
of the policy. However, you must always handle the requests in the order you receive them. Just use the
Billing integration 501
Guidewire PolicyCenter 9.0.6 Integration Guide
PolicyPeriod reference that is the method parameter, and it is possible you might get additional updates or
changes in future calls to your plugin.
See also
• “Billing integration overview” on page 469
• “Asynchronous communication between PolicyCenter and billing system” on page 472
• Installation Guide
Account management
The billing system plugin has several methods related to accounts.
Your createAccount method tells your billing system to create an account associated with the policy period for a
particular transaction. As a method parameter, this plugin method gets the PolicyCenter Account entity instance that
represents the new account. The Account entity properties contain the data for the new billing system account.
Note: PolicyCenter always calls this method asynchronously with respect to the user interface. The
messaging code calls out to the plugin.
Use the account number of an account, not its public ID, to uniquely identify the account in both systems. The
method contains a second parameter, which is the billing system transaction ID.
The transaction ID is an identifier that PolicyCenter creates. Your plugin must track this billing system transaction
ID. If PolicyCenter requests the same transaction ID twice, the billing system or your plugin that represents it must
detect that PolicyCenter requested it twice. If you receive the same transaction ID more than once, you must ignore
the duplicate requests.
Your implementation of the updateAccount method likely is similar to your createAccount method. It takes the
same method parameters, an Account entity instance and a transaction public ID String. However, instead of
creating a new account, PolicyCenter calls this method to notify the billing system that some account information
changed. Use the current properties on the Account entity instance to update the billing system version of the
account. Use the account’s public ID (the PublicID property) to uniquely identify the account in both systems.
Your accountExists method asks your billing system whether an account exists, based on the account number.
Return true if it exists, otherwise return false. PolicyCenter does not track whether the billing system already
knows about an account, so it always asks and then creates it if necessary.
See also
• “Billing system notifications of PolicyCenter policy actions” on page 504
See also
• “Policy cancellation and reinstatement web services” on page 116
Rewrite
Your plugin must also prepare for a policy rewrite request and send that information to your billing system.
PolicyCenter calls the rewritePolicyPeriod method to rewrite the policy period and rewritePolicyPeriod must
send that information to your billing system. Its two method parameters are a policy period (PolicyPeriod) and a
billing system transaction ID.
Note: PolicyCenter always calls this method asynchronously with respect to the user interface. The
messaging code calls out to the plugin.
The transaction ID is an identifier that PolicyCenter creates. Your plugin must track this billing system transaction
ID. If PolicyCenter requests the same transaction ID twice, the billing system or your plugin that represents it must
Billing integration 503
Guidewire PolicyCenter 9.0.6 Integration Guide
detect that PolicyCenter requested it twice. If you receive the same transaction ID more than once, you must ignore
the duplicate requests.
See also
• “New policy periods” on page 502
Producer management
PolicyCenter tracks various types of organizations with the Organization entity. Every organization has an
organization type in its Type property, which holds a BusinessType typecode. If the typecode of the organization
Billing integration 505
Guidewire PolicyCenter 9.0.6 Integration Guide
Producers
To accommodate new producers, implement the createProducer method, which takes as arguments the
Organization entity instance and the billing system transaction ID.
The transaction ID is an identifier that PolicyCenter creates. Your plugin must track this billing system transaction
ID. If PolicyCenter requests the same transaction ID twice, the billing system or your plugin that represents it must
detect that PolicyCenter requested it twice. If you receive the same transaction ID more than once, you must ignore
the duplicate requests.
Your method must return the billing system version of the public ID for this Organization. Your method
implementation must notify the external system of the new producer in whatever way is appropriate.
Your code would typically use the following Organization entity properties:
• Name
• AgencyBillPlanID
• PublicID
• Tier.Code
• Contact (copy all the properties on the Contact entity instance for this producer)
Your code might use additional properties on Organization.
Update producers
You also must prepare for changes to the producer within PolicyCenter. If it changes, PolicyCenter calls the billing
system plugin to send updates to the billing system. Implement the updateProducer similar to your
createProducer method. It takes the same parameters but return nothing. Use the PolicyCenter public ID to
identify the producer in the external system.
You also must implement the method producerExists, which takes a producer public ID and returns true or false
to indicate if the producer exists in the billing system.
Syncing producers
Your plugin must implement the syncOrganization method to synchronize an Organization object with the latest
values from the corresponding producer in the billing system. The method takes a Organization object and returns
nothing.
Producer codes
Your plugin must implement a method to notify the billing system of a new producer code. Implement the
createProducerCode method. Its arguments are a producer code (ProducerCode) and a billing system transaction
ID.
The transaction ID is an identifier that PolicyCenter creates. Your plugin must track this billing system transaction
ID. If PolicyCenter requests the same transaction ID twice, the billing system or your plugin that represents it must
detect that PolicyCenter requested it twice. If you receive the same transaction ID more than once, you must ignore
the duplicate requests.
Your method must return the billing system version of the public ID for this producer code.
Your code would typically send the following ProducerCode entity properties:
• PublicID
• Code
• ProducerStatus
506 chapter 24: Billing integration
Guidewire PolicyCenter 9.0.6 Integration Guide
• producerCode.Organization.PublicID
• producerCode.CommissionPlanID
newPolicyPeriod.SelectedPaymentPlan = selectedPlan.createPaymentPlanSummary(currentBundle)
Use the properties on the selected PaymentPlanData object to set the values of the properties on the
PaymentPlanSummary entity instance. The PaymentPlanSummary entity instance does not have separate
implementations for installment and reporting plan types as PaymentPlanData does. Instead, the data model
requires non-null values only for the properties that both types use. The properties that only installment or reporting
plan types use are optional and can have null values. Your implementation must set these properties appropriately.
In the base configuration, the implementation of the createPaymentPlanSummary method sets the properties that
both installment and reporting plan types of PaymentPlanSummary entity use. This method then calls the
doCreatePaymentPlanSummary method. The classes that extend AbstractPaymentPlanData set the additional
properties that the payment plan type uses.
See also
• Gosu Reference Guide
See also
• “Retrieving payment plans from a billing system” on page 508
Billing integration 509
Guidewire PolicyCenter 9.0.6 Integration Guide
Updating contacts
In the base configuration, PolicyCenter is designed to use a contact management system as the system of record for
contact management. If a contact associated with billing information changes in PolicyCenter, PolicyCenter
determines whether to notify a contact management system by calling the method
gw.contact.ContactEnhancement.ShouldSendToContactSystem. If the method returns true, the contact updates
are sent to the external contact system.
If you do not use an external contact management system, comment out the contents of the
shouldSendContactUpdate method and change its return value to false. For example:
renewing a policy. You can remove the billing summary screen from the user interface and PolicyCenter would
continue to work normally.
Note: If you use BillingCenter, the base configuration plugin implementation handles these tasks. You
do not perform the tasks in this topic.
See also
• “Billing integration overview” on page 469
• Installation Guide
Payment integration
Payment integration involves setting up PolicyCenter communication with a payment system. The types of
communication include:
• Adding and using payment instruments that a payment system uses for billing
• Using a payment gateway to make an up-front payment
information about the success or failure of the payment to PolicyCenter. PolicyCenter sends the information about
successful up-front payments to the billing system.
UpFrontPayment Data Stores an up‐front payment for a job. The PaymentGatewayResponseProcessor ob‐
model en‐ ject creates this entity for an up‐front payment on receiving a successful response
tity from the payment gateway.
IMPORTANT External payment systems and payment gateways return only partial information for
payment sources. For example, payment systems do not return entire credit card numbers. Instead,
payment systems return tokens as identifiers that let PolicyCenter or its billing system initiate a
payment without requiring the entire credit card number or other authentication information.
WARNING Check with your legal department about all regulatory requirements relating to credit
card information before going to production.
See also
7. PolicyCenter uses the registered billing system plugin (IBillingSystemPlugin) implementation to notify the
billing system of the new payment instrument. PolicyCenter calls the plugin method
addPaymentInstrumentTo.
See also
• “Configure PolicyCenter to use a real payment system” on page 515
Procedure
1. In your application config.xml file, find the parameter PaymentSystemURL. Set that parameter to the URL of
your real payment system.
2. Change the code for the externalPaymentLocation method to contact your real payment system:
a. Locate the line that looks like the following code. Note the commented out URL:
3. If necessary, change the code for the externalPaymentLocation method to return to the required
PolicyCenter location.
a. Locate the line that looks like the following code. Note the commented out URL:
var returnURL =
gw.plugin.Plugins.get(gw.plugin.webconfig.IPolicyCenterWebConfigPlugin).PolicyCenterURL
4. Configure the entry point JobWithNewPaymentInstrument to send any additional attributes that the real
payment system sends to PolicyCenter.
takePaymentUsingPaymentInstrument plugin method, which uses the tokenized information. After saving
a PaymentGatewayTransaction entity to the database, takeElectronicPayment processes the response
from the payment gateway.
Redirection to the payment gateway for a new payment instrument occurs differently for the demonstration
gateway and a real gateway:
• For demonstration purposes, the redirectToPaymentGateway plugin method invokes the PCF exit point
called DemoPaymentGatewayPage, which calls a demonstration version of a payment gateway that
PolicyCenter itself implements.
• For a production environment, the code for the redirectToPaymentGateway plugin method uses a different
PCF exit point to open the user interface for your real payment gateway.
The following table compares the two payment gateways:
8. For a successful or voided payment, PolicyCenter removes the PaymentGatewayTransaction entity from the
database.
9. You issue or bind the policy. PolicyCenter uses the registered billing system plugin (IBillingSystemPlugin)
implementation to send a Gosu object to the billing system. PolicyCenter notifies the billing system that it has
received a payment by setting the OfferNumber property on the Gosu object. The value of the OfferNumber
property is the JobNumber property of the Job.
See also
Payment
PolicyCenter Silent Post
Gateway
Payment Gateway
User adds an up-front payment PolicyCenter exit point opens Payment Gateway processes transaction
Servlet processes
response and
creates entities Payment Gateway shows
confirmation page
The following table describes the plugins that support communication with a payment gateway.
Plugin Description
Payment gateway Specifies key information about a payment gateway, such as the URL.
configuration Purpose
plugin Specifies key information about a payment gateway, such as the URL.
Class or interface
Interface: gw.plugin.paymentgateway .PaymentGatewayConfigPlugin
Demonstration implementation: gw.plugin.paymentgateway .DefaultPaymentGatewayConfig Plugin
More information
• “Payment gateway configuration plugin” on page 161
• “Implementing the payment gateway configuration plugin” on page 521
Payment gateway Purpose
plugin Communicates with the payment gateway, sending payments, and receiving responses.
Class or interface
Interface: gw.plugin.paymentgateway .PaymentGatewayPlugin
Demonstration implementation: gw.plugin.paymentgateway .StandAlonePaymentGateway Plugin
Plugin Description
More information
• “Payment gateway plugin” on page 162
• “Implementing the payment gateway plugin” on page 521
The following table describes the servlet that supports communication with a payment gateway.
Servlet Description
Payment Purpose
gateway si‐ Processes a postback action from the payment gateway after the gateway processes a payment. This servlet
lent post ensures that PolicyCenter and the billing system receive information about a payment even if the user closes
servlet the browser.
Class
Demonstration implementation: gw.payment.paymentgateway .PaymentGatewaySilentPost Servlet
See also
“Implementing the silent post servlet for the payment gateway” on page 523
See also
• “Using and controlling the up-front payment user interface” on page 523
• “Implementing payment gateway data transfer” on page 524
PolicyCenter checks for existing PaymentGatewayTransaction entity instances and displays a Synchronize button
and a message requesting synchronization. The action that the Synchronize button takes is to call the
inquiryPaymentGatewayTransaction plugin method. Implement this method to check the status of the payment
request that relates to the PaymentGatewayTransaction entity instance. This method takes the Reference property
of the transaction as a String argument and returns an object that implements the PaymentGatewayResponse
interface. The response processor updates the PaymentGatewayTransaction, Job, and UpFrontPayment entity
instances.
Reversing a payment
The user can choose to remove an up-front payment from a job. This action credits the payment on the payment
gateway. Similarly to processing a payment, PolicyCenter uses a Gosu object that implements the
PaymentInformation interface to hold information about the up-front payment to reverse. Implement the
refundFullAmountForTransaction plugin method to credit the previous payment. This method takes an object that
implements the PaymentInformation interface as an argument and returns an object that implements the
PaymentGatewayResponse interface. If the credit request succeeds, the response processor removes the
UpFrontPayment entity instance for the payment and updates the set of up-front payments on the job.
point in the PaymentGateway.pcf file. This implementation uses the following parameters to build a URL to access
the payment gateway:
• paymentGatewayURL – The URL for the payment gateway. Use the payment gateway configuration plugin to set
up this URL.
• secureToken – Encoded information that identifies an individual transaction. Encoding the information ensures
that third parties cannot examine or modify the information during its transfer from PolicyCenter to the payment
gateway. The requestSecureToken plugin method takes an object that implements the PaymentInformation
interface as an argument and returns an object that implements the PaymentGatewayResponse interface. This
response object provides the value for secureToken. Typically, a secure token expires after a length of time or
after a number of unsuccessful attempts to complete the payment. You specify these parameters when you set up
the payment gateway.
• secureTokenID – A value that you provide to identify the secureToken to the payment gateway.
Implement the PaymentGatewayPlugin plugin method redirectToPaymentGateway to use the exit point. In the
exit point, map PolicyCenter values to URL parameters that your payment gateway requires.
See also
• “Implementing the payment gateway plugin” on page 521
• “Payments Web Service APIs (PaymentAPI)” in BillingCenter Integration Guide
Contact integrations
Guidewire PolicyCenter 9.0.6 Integration Guide
chapter 25
Contact integration
This topic discusses how to integrate PolicyCenter with an external contact management system other than
ContactManager, and also covers configuring other actions relating to contacts.
PolicyCenter includes built-in support for integrating with Guidewire ContactManager.
See also
• Guidewire Contact Management Guide
gw.plugin.contact.impl.StandAloneContactSystemPlugin
The PolicyCenter base configuration supports integration with Guidewire ContactManager. If you have a Client
Data Management module license and install ContactManager, do not write your own implementation of the
ContactSystemPlugin plugin interface. Instead, use the plugin implementation
gw.plugin.contact.ab900.ABContactSystemPlugin.
The PolicyCenter base configuration has built-in support for integration with Guidewire ContactManager. If you
have a license for the optional Client Data Management module, you can install and integrate ContactManager.
Your implementation of the contact system plugin defines the contract between PolicyCenter and the code that
initiates requests to an external contact management system. PolicyCenter relies on this plugin to perform the
following operations.
• Retrieve a contact from the external contact management system.
• Search for contacts in the external contact management system.
• Add a contact to an external contact management system.
Contact integration 529
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• “Contact web service APIs” on page 537
when at message send time. PolicyCenter calls the beforeSend method of the ContactMessageRequest
plugin to update the payload before the message is sent.
b. PolicyCenter calls the message transport plugin to send the message. The message transport
implementation finds the ContactSystemPlugin class and calls its sendAsyncUpdate method to actually
send the message. An additional method argument includes the modified late-bound payload that the
message request plugin returned.
Retrieve a contact
You use a web service and the contact system plugin to retrieve a contact from an external system.
Procedure
1. Write your web service code that connects to the external contact management system.
2. In the web service, write a method to return a data transfer object that contains enough information to populate
a contact.
The return type must contain equivalents of the following Contact properties.
PrimaryPhone
TaxID
WorkPhone
EmailAddress2
FaxPhone
HomePhone
CellPhone
DateOfBirth
Version
A contact of type Person must also have the properties FirstName and LastName.
A contact of type Company must also have the property Name, containing the company name.
Consider a web service in Studio with the name MyContactSystem and with a MyContact XML type from a
WSDL or XSD file. For this example, the contact retrieval web service returns a MyContact data transfer
object.
3. In your plugin code for the retrieveContact method, wait synchronously for a response.
4. To return the data to PolicyCenter, create a new instance of a contact in the current transaction's bundle.
a. Create the new instance by using the instance of ContactCreator that your plugin method gets as a
method argument. This class standardizes finding and creating contacts within PolicyCenter. It has a
loadOrCreateContact method that you can use for creating a contact.
b. Populate the new contact entity instance with information from your external contact.
Your code might look like something like the following example.
validateAutoSyncState(returnedContact, addressBookUID)
overwriteContactFromXml(returnedContact, contactXml)
}
return returnedContact
}
Contact searching
To support contact searching, your plugin must respond to a search request from PolicyCenter. PolicyCenter calls
the plugin method searchContacts to perform the search. The details of the search are defined in a contact search
criteria object, ContactSearchCriteria, which is a method argument. This object defines the fields that the user
searched on.
The important properties in this object are listed below.
• ContactIntrinsicType – The type of contact. To determine if the contact search is for a person or a company,
use code similar to the following example.
See also
• Guidewire Contact Management Guide
See also
• Guidewire Contact Management Guide
Procedure
1. Query the external system for a list of matching or potentially matching contacts.
2. Optionally, if the results you receive are only summaries, if it is necessary for detecting duplicates, retrieve all
the data for each contact from the external system.
3. Review the duplicates and determine which contacts are duplicates according to your plugin implementation.
4. Create a list of ContactMatch items, each of which contains a Contact and a boolean property that indicates
if the contact is an exact match. Each of these Contact objects is a summary that contains many, but perhaps
not all, Contact properties.
Contact integration 533
Guidewire PolicyCenter 9.0.6 Integration Guide
5. Create an instance of the concrete class DuplicateSearchResult with the collection of ContactMatch items.
Pass the list of duplicates to the constructor.
6. Return that instance of DuplicateSearchResult from this method.
The payload parameter uniquely describes the contact for the external system in whatever format the external
system accepts, such as XML specified by a published XSD. For a typical integration, your Event Fired rules
generate an XML serialization of your contact. The payload parameter represents the Message.Payload property of
the message.
The simpler method signature takes a Contact entity and a transaction ID.
The transaction ID parameter uniquely identifies the request. Your external system can use this transaction ID to
track duplicate requests from PolicyCenter.
If you have multiple AccountContact subtypes, check the runtime subtype by checking contact.Subtype if your
behavior depends on the subtype.
function addContact(externalContact :
gw.webservice.pc.pc900.gxmodel.contactmodel.types.complex.Contact) : String
In this fully-qualified path, the part of the path before types indicates the path of the XML model in Studio. In
Studio, the path is:
configuration/gsrc/gw/webservice/pc/pc900/gxmodel/ContactModel.gx
Deleting a contact
You can delete a contact in PolicyCenter from an external system by using methods in ContactAPI. There are two
variants that take different parameters and return different values. Both methods cause PolicyCenter to remove the
contact across all accounts.
contactAPI.removeContactByPublicID("pc:1234");
The method finds all account contacts (AccountContact objects) in the database and tries to delete the contact.
contactAPI.removeContact("12345");
Adding a contact
To add a contact to PolicyCenter, call the addContact method.
To add a new contact you must populate and provide as an argument a contact in a specific XSD-defined XML
object that represents the contact. The fully qualified type name is
gw.webservice.pc.pc900.gxmodel.contactmodel.types.complex.Contact. A Guidewire GX model defines
this XML type.
The method returns the public ID of the new contact.
The method updates the contact only if auto sync is enabled for that contact.
The following Java example demonstrates the API.
gw.webservice.pc.pc900.gxmodel.contactmodel.types.complex.Contact contactXML;
// here you would populate fields in the contactXML object, including the PublicID property and
// any other required fields. See the Data Dictionary for details
contactAPI.addContact(contactXML, "my-transaction-ID-12345");
See also
• “GX models” on page 561
538 chapter 25: Contact integration
Guidewire PolicyCenter 9.0.6 Integration Guide
Updating a contact
You can update a contact from an external system by using the updateContact method. The method has no return
value.
To add a new contact you must populate and provide a contact as the first argument. Specify the contact in a XSD-
defined XML object. The type’s fully qualified name is shown below.
gw.webservice.contactapi.beanmodel.XmlBackedInstance
Unlike some other XSD-based types used in ContactAPI, this type does not contain a corresponding Guidewire GX
model file in PolicyCenter.
The XmlBackedInstance is a type defined in the BeanModel.xsd file. You can find the XSD file in Studio. The
XmlBackedInstance type in the XSD is an XML container for a series of pairs of property name and property value,
both as String values.
To determine which contact to update, PolicyCenter uses that object’s address book UID, which is in the LinkID
property in the XmlBackedInstance object. If the contact cannot be found, PolicyCenter throws an exception.
Finally, PolicyCenter uses the other properties in the contact XML object to update the contact entity instance.
The method updates the contact only if automatic synchronization (autosync) is enabled for that contact.
The following Java example demonstrates the APIs.
gw.webservice.contactapi.beanmodel.XmlBackedInstance contactXML;
// here you would populate fields in the contactXML object, especially the LinkID property,
// which contains the Address Book UID for this contact
contactAPI.updateContact(contactXML);
Merging contacts
You can merge two contacts from an external system. You need to know the IDs of both contacts, and you must
decide which one will survive after the merge.
There are two variants of this method, which support different styles of IDs.
• If you want to specify the objects by public IDs, use the mergeContactsByPublicId method.
• If you want to specify the objects by AddressBookUID, use the mergeContacts method.
Both methods return nothing.
Pass the following parameters in the listed order.
1. The ID of the contact to keep. This parameter is known as the “kept” contact.
2. The ID of the contact to delete. This parameter is known as the “deleted” contact.
3. A transaction ID (a String) that uniquely identifies the request from an external system. PolicyCenter
performs no built-in check with this parameter in the current release. You can modify PolicyCenter to use this
transaction ID to detect, log, and handle duplicate requests. A request is a duplicate if the transaction ID
matches a previous request.
Merging contacts has the following results.
• Non-duplicate entities on array properties on a contact are merged onto the kept contact. This includes
Addresses, RelatedContacts, CategoryScores, OfficialIDs, Tags. Duplicate entries are discarded.
• Fields on the deleted contact are not preserved.
• Account contact (AccountContact) objects that reference the deleted contact now reference the kept contact. If
both exist on the same account, the kept contact’s AccountContact property value is used.
• Account contact roles (AccountContactRole[]) on a merged AccountContact move to the kept contact’s
account contact. If there are duplicate roles, the kept contact’s roles are preserved.
• PolicyCenter refreshes the kept contact from the external Contact Management System. PolicyCenter calls the
contact system plugin (IContactSystemPlugin) method called retrieveContact(String, Bundle).
• If the deleted contact was an account holder (Account.AccountHolder), PolicyCenter makes the kept contact
active and gives it the AccountHolder role on that account.
• Policy contact roles (PolicyContactRole[]) that reference a merged AccountContactRole change to reference
the kept contact’s AccountContactRole. Duplicate PolicyContactRole objects remain on the policy, but raise a
validation error on Quote or Bind actions.
• The deleted contact and any duplicate subobject is retired (deleted). This includes the following:
AccountContact and AccountContactRole.
The following Java example demonstrates the API method.
Integer totalUpdated;
totalUpdated = contactAPI.activateContactOnAllAccounts("pc:1234", true /* activate */);
gw.webservice.pc.pc900.gxmodel.jobmodel.types.complex.Job
Job[] workOrderList;
workOrderList = contactAPI.getAssociatedWorkOrdersByPublicID("pc:1234", "BOUND");
gw.webservice.pc.pc900.gxmodel.policyperiodmodel.types.complex.PolicyPeriod
gw.webservice.pc.pc900.gxmodel.policyperiodmodel.types.complex.PolicyPeriod[] policyList;
policyList = contactAPI.getAssociatedPoliciesByPublicID("pc:1234");
gw.webservice.pc.pc900.gxmodel.accountmodel.types.complex.Account
gw.webservice.pc.pc900.gxmodel.accountmodel.types.complex.Account[] accountList;
accountList = contactAPI.getAssociatedAccountsByPublicID("pc:1234");
Address APIs
The AddressAPI lets external systems interact with addresses in PolicyCenter. This web service is WS-I compliant.
There are several ways to update addresses, with options such as linking and unlinking the address with other
addresses.
Refer to the implementation class gw.webservice.pc.VERSION.AddressAPI.gs for implementation details of the
methods in this web service.
Updating an address
You can update an address using methods on the AddressAPI web service.
There are several methods that update addresses, compared in the following table.
542 chapter 25: Contact integration
Guidewire PolicyCenter 9.0.6 Integration Guide
For all versions of the method, pass the following parameters in the listed order.
• The address data encapsulated in an object of type gw.webservice.pc.contact.AddressData. This is a Gosu
class. You can read the source code of the file in Studio.
• The public ID (a String) of the address object.
The following Java example demonstrates the APIs.
gw.webservice.pc.contact.AddressData updateAddress;
// here you would populate fields in the object in the updateAddress variable
// for example the PublicID property and
// any other required fields. See the Data Dictionary for details
addressAPI.updateAddress(updateAddress, "pc:1234");
PolicyCenter includes zone mapping functionality used by the assign by location, address auto-fill, and regional
holidays features. PolicyCenter supports high-volume bulk import of zone data by using database staging tables.
This topic describes the use of database staging tables to import zone data.
PolicyCenter supports database staging table import of zone data only. PolicyCenter does not support staging table
import of policies, accounts, or other business or administrative data. Use the standard Guidewire APIs to import
non-zone data. Implement segmentation strategies to improve loading performance if necessary.
link table. To reload data for a country for which zone data already exists, you must first clear the zone data for that
country from the operational zone tables.
The following diagram shows the major steps in a typical zone staging table import.
Zone Import
Typical Flow
Key
Your data and tools Import Tools Staging Operational
CSV File Tables Tables
Guidewire-managed data
Guidewire tools
Actions or
data flow Correction Error
List Tables
Actions or data flow at
server maintenance level
See also
• System Administration Guide
configuration→config→geodata→AU
Guidewire provides the US-Locations.txt and similar files for testing purposes to support autofill and
autocomplete when users enter addresses. This data is provided on an as-is basis regarding data content. The
provided zone data files are not complete and might not include recent changes.
Also, the formatting of individual data items in these files might not conform to your internal standards or the
standards of third-party vendors that you use. For example, the names of streets and cities are formatted with mixed
case letters but your standards may require all upper case letters.
The US-Locations.txt file contains information that does not conform to United States Postal Service (USPS)
standards for bulk mailings. You can edit the US-Locations.txt file to conform to your particular address
standards, and then import that version of the file.
postalcode,state,city,county
See also
• Globalization Guide
See also
• System Administration Guide
Staging tables
Staging tables are database tables that replicate the loadable columns of specific operational tables in the
PolicyCenter database. The operational zone table pc_zone has a corresponding staging table pcst_zone. You
prepare zone data for bulk import into the PolicyCenter operational table pc_zone by first loading the data into the
pcst_zone staging table.
Importing from database staging tables 549
Guidewire PolicyCenter 9.0.6 Integration Guide
A logical unit of work (LUW) groups related records across multiple staging tables into a single unit. All rows in an
LUW must load from staging tables into operational tables. An error in any row in an LUW invalidates the whole
LUW. For example, a Zone record for a postal code must load into the pcst_zone staging table at the same time as a
Zone record for its city. The zone import tool creates an identifier (LUWID) for each LUW that it defines.
After staging table data loads successfully into operational tables, PolicyCenter deletes all the rows from the staging
tables.
See also
• System Administration Guide
See also
• System Administration Guide
See also
• System Administration Guide
table_import –help
PolicyCenter also provides tools to load data from CSV files to the staging tables for zone data.
zone_import –help
See also
• “Table import web service” on page 107
• “Zone data import web service” on page 111
• System Administration Guide
Server modes and run levels for database staging table import
The database import tools do not require the server to run in a specific mode. You can perform database staging
table imports in any of production, test, or development modes.
For many of the tasks required to import data by using database staging tables and the database import tools, you
must set the server to the maintenance run level. The maintenance run level prevents new user connections, halts
existing user sessions, and releases all database resources. The server prohibits access from the PolicyCenter user
interface to the database whenever the server runs at the maintenance level.
Example commands are shown below.
• API method: SystemToolsAPI.setRunLevel(SystemRunlevel.GW_MAINTENANCE)
• Command prompt tool: system_tools -password password -maintenance
See also
• “System tools web service” on page 105
• System Administration Guide
See also
• System Administration Guide
Integrity checks
The PolicyCenter application includes a large set of database SQL queries that provide integrity checks on staging
table data. These checks find and report problems that would cause the import to operational tables to fail or put
PolicyCenter into an inconsistent state. Optionally, the integrity check command can clear error tables and exclusion
tables. You can see the integrity check SQL queries at Server Tools→Info Pages→Load Integrity Checks. You can check
if any integrity checks failed at Server Tools→Info Pages→Load Errors.
Before importing staging table data into operational database tables, PolicyCenter runs integrity checks. If the
checks fail, PolicyCenter rolls back the data import. To avoid rolling back a data import, run the integrity checks and
552 chapter 26: Importing from database staging tables
Guidewire PolicyCenter 9.0.6 Integration Guide
correct any errors before attempting the import. Even if the rows that caused errors in earlier integrity check runs
were removed, PolicyCenter must rerun integrity checks before importing your data.
• Identifying problems before a load starts is more efficient than triggering exceptions during the load process. If
population of the operational tables encounters errors, the database must roll back the entire set of loaded records.
Such rolling back of database changes is typically slow and resource-intensive.
• Some integrity check violations occur even if you remove all rows that contain errors from the staging tables.
These violations occur for errors that cannot be tied to a single row.
The following descriptions contrast data integrity checks with other validations.
• The user interface (PCF) code enforces additional requirements.
For example, a property that is nullable in the database may require that users set a value in the PolicyCenter user
interface. Importing a null value in this property passes integrity checks. However, if a user uses the
PolicyCenter interface to edit an object containing the property, PolicyCenter requires a non-null value before
saving because of data model validation.
• Integrity checks are different from validation rule sets and the validation plugin.
Before you run the checks, you must set the server run level to maintenance. After the checks complete, set the
server run level back to multiuser.
Example commands are shown below.
• Web service method example
var batchProcessID =
TableImportAPI.integrityCheckStagingTableContentsAsBatchProcess(clearErrorTable : true,
populateExclusionTable : false,
allowRefsToExistingNonAdminRows:false,
numThreadsIntegrityChecking : 8)
See also
• System Administration Guide
code substantially improves the ability of Guidewire to advise you on performance issues related to database
import.
Example commands are shown below.
• Web service method example
See also
• “Zone data import web service” on page 111
• System Administration Guide
ZoneImportAPI.clearStagingTables()
Example commands to delete all rows from the error table are shown below.
• Web service method example
var batchProcessID =
TableImportAPI.integrityCheckStagingTableContentsAndLoadSourceTablesAsBatchProcess(
clearErrorTable : true,
populateExclusionTable : false,
updateDBStatisticsWithEstimates : false,
allowRefsToExistingNonAdminRows : false,
numThreadsIntegrityChecking : 1)
Estimate the database statistics only on Oracle databases that contain few or no policy records. Estimating the
statistics on databases that have more data significantly reduces database performance.
Procedure
1. If you changed the data model, run the server to perform upgrades. The staging table import tools require that
source data be converted to the same format as the server data.
2. Create zone data files. Create zone data files in comma separated value (CSV) format.
3. Set the server to the maintenance run level. Set each PolicyCenter server to the maintenance run level by using
the system_tools command prompt tool or the web service SystemToolsAPI.setRunLevel method.
4. Back up the operational tables in the database. Back up operational tables before import.
5. Clear the staging tables, the error tables, and the exclusion tables. Use web service APIs or command-line
tools.
6. Run PolicyCenter database consistency checks, Database consistency checks verify that the data in your
operational tables does not contain any data integrity errors. Run database consistency checks using the web
services SystemToolsAPI. checkDatabaseConsistency method, or running the command prompt tool as
shown below.
Procedure
1. Run the zone import tool. Run the command prompt tool zone_import or use the IZoneImportAPI web
service to import your CSV data.
2. Set the server to the maintenance run level. Set each PolicyCenter server to the maintenance run level by using
the system_tools command prompt tool or the web service SystemToolsAPI.setRunLevel method.
3. Request integrity checks from the table import tools. Use the TableImportAPI web service method
integrityCheckStagingTableContentsAsBatchProcess or the following command prompt command.
For an Oracle database, take instrumentation snapshots before and after running integrity checks. Generate
database instrumentation reports to identify performance problems.
556 chapter 26: Importing from database staging tables
Guidewire PolicyCenter 9.0.6 Integration Guide
Note: The -batch option does not wait until the started process completes before returning.
Instead, it returns immediately and prints the ID of the started process (PID). The process caller
is responsible for waiting for the process to complete before taking further action.
4. Set the server to the multiuser run level. Set each PolicyCenter server to the multiuser run level by using the
system_tools command prompt tool or the web service SystemToolsAPI.setRunLevel method.
5. Check load errors from the Load History page. This page is available at Server Tools→Info Pages→Load History.
6. Correct errors in the zone data source files. Edit the zone data CSV file to correct the data.
7. Decide whether to populate or clear the error and exclusion tables. The error table contains information about
the rows that failed the earlier integrity checks. If you want to clear these errors before the next integrity
checks run or exclude data rows that cause errors, perform the following steps.
a. Exclude rows that caused integrity check errors. Populate the load exclusion table with the LUWIDs that
contain errors. Use the TableImportAPI web service method populateExclusionTableAsBatchProcess
or the table_import command prompt tool.
b. Remove excluded records from staging tables. Remove all rows from all staging tables for records whose
LUWIDs are listed in the exclusion table. You can use the table_import command prompt tool or the
TableImportAPI web service method deleteExcludedRowsFromStagingTablesAsBatchProcess.
c. Clear the error and exclusion tables. Optionally, for clarity, remove the errors and exclusion rows related
to earlier integrity checks. Use the TableImportAPI web service method
clearErrorTableAsBatchProcess or the table_import command prompt tool. When you next run
integrity checks, only the errors from that run appear in the user interface.
Procedure
1. Update the database statistics for the staging tables. Use the TableImportAPI web service method
updateStatisticsOnStagingTablesAsBatchProcess or the table_import command prompt tool. For
example, run the following command at a command prompt.
Note: The -batch option does not wait until the started process completes before returning.
Instead, it returns immediately and prints the ID of the started process (PID). The process caller
is responsible for waiting for the process to complete before taking further action.
2. Set the server to the maintenance run level. Set each PolicyCenter server to the maintenance run level by using
the system_tools command prompt tool or the web service SystemToolsAPI.setRunLevel method.
3. Load staging table zone data into operational zone tables. To load only zone table data, use a method that
begins with integrityCheckZoneStagingTableContentsAndLoadZoneSourceTables on the
TableImportAPI web service API. Alternatively, use the table_import command prompt tool with the -
integritycheckandload option. PolicyCenter inserts data rows into the operational zone tables and results
information into the load history table.
• For an Oracle database, take instrumentation snapshots before and after running the integrity check and
load. Generate database instrumentation reports to identify performance problems.
• For an Oracle database, if the operational tables contain no records or few records, use the load option to
estimate database statistics, as shown in the following command.
Importing from database staging tables 557
Guidewire PolicyCenter 9.0.6 Integration Guide
• For a non-Oracle database or an Oracle database that already contains many records, use the following
command.
4. Set the server to the multiuser run level. Set each PolicyCenter server to the multiuser run level by using the
system_tools command prompt tool or the web service SystemToolsAPI.setRunLevel method.
Procedure
1. Review the load history at Server Tools→Info Pages→Load History.
2. Ensure that the amount of data loaded is correct.
3. Update database statistics. Particularly after a large conversion, update database statistics.
4. If necessary, import additional records into the staging tables.
GX models
A GX model enables the properties of a data type to be converted to XML. Supported data types that can be
converted include Gosu classes and business data entities, among others. A GX model can include all or a subset of
an associated data type's properties. Use GX models to limit the transfer of object data to those properties you need
or desire to conserve resources and improve performance.
GX models overview
A GX model is a data type that is associated with another data type. The model includes the desired properties of the
associated type that will be subsequently converted to XML. A GX model can include all or a subset of the
associated type's properties. For example, a GX model called AddressModel can be associated with the Address
entity. The definition of the model might include the PublicID and Description properties from Address.
Even though the GX model contains properties of another entity, the internal formats of the model’s properties are
undefined. The model’s internal format can change in different PolicyCenter versions. Best practice is not to depend
on the internal format of GX model properties. Accordingly, do not access or modify a GX model’s properties.
Supported GX model operations include defining and creating models and converting their contents to XML.
GX models are defined in the Studio GX model editor. Using the editor, the properties of a data type are added to the
GX model. As the model is defined, the editor automatically generates an XSD schema that specifies the XML
structure of the model. Because of this automation, the XML definitions that the editor generates will be valid and
do not require further validation.
When configuration code subsequently creates an instance of the GX model, the constructor methods accept an
argument of an instance of the data type associated with the model. The properties of the argument that are
referenced by the GX model are stored in the new instance. They can be subsequently converted to XML that
conforms to the model’s XSD schema. Continuing with the Address and AddressModel example, an instance of the
AddressModel is created. The model’s constructor accepts an instance of Address as an argument. The PublicID
and Description properties of the argument are stored in the created GX model object. The model properties are
subsequently converted to XML using one of the supported conversion methods.
Create a GX model
Procedure
1. In Studio, navigate in the resource tree to the location configuration→gsrc.
2. Within the class tree, navigate to the package in which you want to store your XML model, just like you
would for creating a new Gosu class. If you need to create a top-level package, right-click on the folder icon
for gsrc, and select New Package.
GX models 561
Guidewire PolicyCenter 9.0.6 Integration Guide
3. Right-click on the desired package. From the contextual menu, choose New→GX Model to open the GX Model
window.
4. Select either the Search by Name or Project tab to list the available classes and data types to map.
5. In the Search field, enter the name of the type to export in XML format. For example, to map and export an
Address entity, type Address. The dialog box lists the types that match any partial name you type. Select the
desired class from the list.
6. Enter the desired GX model name in the Model Name field. The default name of the GX model is the name of
the selected class followed by the word Model. For example, if the selected class is Address, the model name
is AddressModel.
The GX model name defines the package hierarchy for the model, so choose its name carefully. For example,
if an XML model called AddressModel is created in the mycompany package, the fully qualified type for the
Address entity in the GX model is mycompany.addressmodel.Address.
7. Click OK to open the GX model editor.
8. To map a property to the GX model, select the property in the editor’s left pane.
To navigate through a property’s lower levels, click the arrow icon in front of the property to open the
hierarchy below it. Continue navigating to lower levels until the desired property is located.
Alternatively, locate the desired property by entering its name in the Filter field. Studio searches for the
property in lower levels to the depth specified in the Filter Depth field. For example, to find the myProp property
in the hierarchy myClass.propertyOne.subProperty.myProp, set the Filter Depth to three to search three
levels below the parent myClass.
9. With a property selected in the left pane, click Add>> to show the show the Mapping Type popup.
10. In the Mapping Type popup, select the property’s mapping type, either Key Property or Normal Property. The
selected property is added to the editor’s right pane.
11. Continue adding properties to the GX model until the model is complete.
Result
The XML definition of the GX model can be viewed by selecting the Text tab at the bottom of the editor.
In the editor’s lower pane, select the Schema tab to view the XSD schema that is automatically generated for the GX
model. Select the pane’s Sample XML tab to view a sample XML file that conforms to the XSD schema.
Next steps
For more information about key properties and normal properties in the context of the incremental mode, see "The
Incremental Option" under “GXOptions” on page 565.
http://HOSTNAME:PORT/pc/ws
The web server displays a list of XSD schema files. Click on a file to view it. If your external system imports XSD
schema files using an HTTP URL, save the URL to bookmark and retrieve the schema file as needed. If the external
564 chapter 27: GX models
Guidewire PolicyCenter 9.0.6 Integration Guide
system needs the schema file on disk, copy and paste the file contents into an appropriate application to save it. You
can also view the XSD schema in the Studio GX Model editor.
As an example, assume a GX model of the Address entity was created and named AddressModel. In addition, the
GX model is stored in the package com.mycompany. Finally, an instance of the Address entity called myAddress
contains valid address information. The following statement creates XML variables based on the GX model and
initializes them with data from myAddress.
GXOptions
The behavior of the GX model create method can be modified by specifying options as an argument of type
GXOptions. The GXOptions argument is optional.
// Alternatively, create and use a GXOptions variable with the Incremental option enabled
uses gw.api.gx.GXOptions
public static final var IncrementalOption : GXOptions = new GXOptions() {:Incremental=true}
var myGxModel02 = com.mycompany.addressmodel.Address.create(myAddr, IncrementalOption)
When the Incremental option is enabled, special behavior exists for key properties (as opposed to normal
properties) on the root entity. Key properties on the root entity that have not changed are still exported to the GX
model. The reason for this behavior is because key properties rarely change value. However, this behavior applies
only to the root entity. If a key property in a subobject of the root entity has not changed, the property is not exported
to the GX model.
Determining whether a property has changed is not always possible. Virtual properties and enhancement properties
are not defined in the data configuration file and, as a result, they are not stored in the database. This condition
prevents Gosu from determining whether a virtual or enhancement property has changed. In such situations, the
setting of the Incremental option is ignored for the property, and the property is exported to the GX model.
Also, Gosu cannot determine whether a property in subobjects of virtual and enhancement properties has changed.
Therefore, the Incremental option is ignored for the subobjects and all appropriate properties in the subobjects are
GX models 565
Guidewire PolicyCenter 9.0.6 Integration Guide
exported to the GX model. For example, the PrimaryAddress for a Claim entity is a virtual property. As a result,
Gosu cannot determine whether the PrimaryAddress property and any property in the subobjects of
Claim.PrimaryAddress have changed.
<myNullProperty xsi:nil="true">
Properties that exist in subobjects to the null property are naturally also null values, but they are not exported to
the GX model. Only the top-level null property is exported.
GX model labels
When an instance of a GX model is created, all the model's properties are included in the new object. Alternatively,
GX model labels enable the object to include only a subset of the model's properties. A label is assigned to one or
more of the model's properties. When an instance of the model is created and the label is specified, only the
properties assigned the label are included in the new object.
A GX model can have multiple labels assigned to its properties, and a single property can have multiple labels
assigned to it. When a GX model object is created, the appropriate combination of labels are specified to include the
desired properties.
By using labels, a single GX model can be defined and each instance of the model can include different properties
depending on the context. Imagine the following situation.
• External SystemA needs to include one key property and five standard properties on an entity.
• External SystemB needs to include two key properties and ten standard properties on the same entity.
Without labels, each system must create its own separate GX model. With labels, a single GX model can be created
where the properties that interest SystemA are assigned a special label, such as SysA. In the same GX model, the
SystemB properties are assigned a label like SysB. A property can have multiple labels assigned to it, which enables
a single property to be used by both SystemA and SystemB. When SystemA converts the model properties to XML,
only the properties with the SysA label are converted. Similarly, when SystemB converts the same model, only the
properties with the SysB label are converted. The result is that a single GX model is used to handle the requirements
of both SystemA and SystemB.
A GX model label applies to a parent entity and all child entities. For example, the AddressModel GX parent entity
might include a child entity called Country. The myGxLabel can be assigned to properties in both the parent
AddressModel and the child Country. When the GX model object is created and the myGxLabel is specified, the
resulting object includes all properties in the parent and child that were assigned the label.
566 chapter 27: GX models
Guidewire PolicyCenter 9.0.6 Integration Guide
AddressModel.Address.Label.SysA
If the GX AddressModel is located in the package com.myCompany, the complete reference to the SysA label is as
follows:
com.mycompany.addressmodel.Address.Label.SysA
You can assign the SysA label reference to a variable with the following syntax:
A label name used by two unrelated models produces two separate and distinct labels. You reference these labels
individually with static properties. In the following example, the myLabel name is used by both the AddressModel
GX model and the unrelated ContactModel GX model:
Instead of referring to a GX model label by its static property, you can refer to the label by its name. To do so, use a
String constant value. For the previous example, use "myLabel."
The differences between the String constant method and the static property method are a matter of convenience.
You can use both to refer to the same GX model label. However, the String constant method is often more
convenient than the static property method. As a case in point, the previous code example requires two static
properties to refer to two separate and distinct labels having the same name. By contrast, you only need to use one
String constant, "myLabel," to refer to both labels. While the static property referencing method can only refer to
one individual GX model label at a time, the String constant referencing method can refer to multiple labels at once
and requires fewer keystrokes.
GX models 567
Guidewire PolicyCenter 9.0.6 Integration Guide
If a GX model has labels, it must use the label syntax when creating an instance. This requirement applies even if
the labels are to be ignored and all of the properties in the model are to be included in the instance. In such cases, the
reserved label default_label can be referenced in the creation statement by using the static property method.
Labels referenced using the String constant method are included in a separate list of labels in the model’s create
code statement. The list of String constant label references is located after the list of labels referenced by their
static properties. Each list of label references is specified within curly braces with multiple label references
separated by commas.
Note: String constant label references must match the label name for an existing GX model. Be sure
to spell String constant label references properly and in the correct case. In addition, do not use a
String constant to refer to the reserved label default_label.
If the list of String constant label references is specified, then the preceding list of static property label references
must also be specified. This requirement applies even if the preceding list is designated as an empty list. Both lists
can be populated with items.
Some example code statements are shown below.
Static property label references and String constant label references vary in their dependence on the GX models to
which they relate. On the one hand, static property label references are specific to the GX models on which they are
defined. This is true even if the labels for the references have the same name. On the other hand, String constant
label references apply across GX models or within multi-level GX models.
For example, suppose that a GX model GxModel1 defines a property Property1_1 with label SystemA. Assume also
that a GX model GxModel2 defines a property Property2_1 with a label having the same name, SystemA. The
respective static property references for the SystemA label—GxModel1.Label.SystemA and
GxModel2.Label.SystemA—go in the first labels argument position. Alternatively, the String constant reference,
"SystemA," goes in the second labels argument position. The references of the static property variety are separate
and specific to their corresponding GX models. By contrast, the reference of the String constant variety is model-
independent and applies to both Property1_1 on GxModel1 and Property2_1 on GxModel2.
When any single GX model within a parent and child hierarchy defines labels, the label syntax must be used when
creating an instance of the parent. The following situations can exist.
• Parent model does not have labels, child model has labels – The child model can be located at any level below
the parent. The parent model will export all of its properties. The child model will export its properties that are
assigned the referenced label.
• Parent model has labels, child model does not have labels – The parent model will export its properties that are
assigned the referenced label. The child model will export all of its properties.
• Both the parent and child model have labels – Both the parent and child models will export their properties that
are assigned the referenced labels. A label can be used in both the parent and child models.
// Create an instance of the GX model that includes only the properties with the label myAddressLabel
var addrModelLabels = com.mycompany.addressmodel.Address.create(addr, {addrLabel})
// Create an instance of the GX model that includes all properties, regardless of labels
var addrModelAll = com.mycompany.addressmodel.Address.create(addr, {defLabel})
The output of the addrModelLabels variable is shown below. The output of the addrModelAll variable is similar,
but includes all the properties contained in the model.
<?xml version="1.0"?>
<Address xmlns="http://guidewire.com/bc/gx/com.mycompany.addressmodel">
<PublicID>example1234</PublicID>
<AddressLine1>123 Main St.</AddressLine1>
</Address>
if (MessageContext.EventName == "AddressChanged") {
var xml = mycompany.messaging.addressmodel.Address.create(MessageContext.Root as Address)
if (xml.$ShouldSend) {
var strContent = xml.asUTFString()
var msg = MessageContext.createMessage(strContent)
When Gosu checks for mapped data model properties that changed, Gosu checks both normal and key properties.
Because a key property uniquely identifies an object, typically that value never changes.
An important exception to this behavior occurs if any ancestor of a changed property changed its value, including to
null. In this case, the change might not trigger $ShouldSend to be true. If the original value of the non-data-model
field indirectly referenced data model fields, those fields do not count as properties that trigger $ShouldSend to be
true. If the property that changed has a path from the root type that includes non-data-model fields, Gosu’s algorithm
for checking for changes does not determine that this field changed. This behavior also occurs if the property value
changed to null. PolicyCenter can tell whether a property changed only if all its ancestors are actual data model
fields rather than enhancement properties or other virtual properties.
For example, suppose that a user action causes a change to the mapped field A.B.C.D property and also A.B.C
became null. If the B property and the C property are both data model fields, Gosu detects this bundle change and
570 chapter 27: GX models
Guidewire PolicyCenter 9.0.6 Integration Guide
sets $ShouldSend to true. However, if the B.C property is implemented as a Gosu enhancement or an internal Java
method, then $ShouldSend is false. This difference is because the bundle of entities does not contain the old value
of A.B.C. Because Gosu cannot determine whether the property changed, Gosu does not mark the change as one that
sets the property $ShouldSend to the value true.
This special behavior with non-data-model properties subgraphs is similar to how the Incremental property in
GXOptions is effectively disabled in virtual property subgraphs.
Note that if a property contains an entity array and its contents change, $ShouldSend is true. In other words, if an
entity is added or removed from the array, $ShouldSend is true.
The behavior of $ShouldSend does not change based on the value of the Verbose or Incremental options.
byte xsd:byte
byte[] xsd:base64Binary
float xsd:float
gw.api.database.spatial.SpatialPoint xsd:string
gw.api.database.spatial.SpatialPolygon xsd:string
gw.api.financials.CurrencyAmount xsd:string
gw.pl.currency.MonetaryAmount xsd:string
gw.xml.xsd.types.XSDDate xsd:date
gw.xml.xsd.types.XSDDateTime xsd:dateTime
gw.xml.xsd.types.XSDDuration xsd:duration
gw.xml.xsd.types.XSDGDay xsd:gDay
gw.xml.xsd.types.XSDGMonth xsd:gMonth
gw.xml.xsd.types.XSDGMonthDay xsd:gMonthDay
gw.xml.xsd.types.XSDGYear xsd:gYear
gw.xml.xsd.types.XSDGYearMonth xsd:gYearMonth
gw.xml.xsd.types.XSDTime xsd:time
int xsd:int
java.lang.Boolean xsd:boolean
java.lang.Byte xsd:byte
java.lang.Double xsd:double
java.lang.Float xsd:float
java.lang.Integer xsd:int
java.lang.Long xsd:long
GX models 571
Guidewire PolicyCenter 9.0.6 Integration Guide
java.lang.String xsd:string
java.math.BigDecimal xsd:decimal
java.math.BigInteger xsd:integer
java.net.URI xsd:anyURI
java.net.URL xsd:anyURI
java.util.Calendar xsd:dateTime
java.util.Date xsd:dateTime
javax.xml.namespace.QName xsd:QName
long xsd:long
short xsd:short
Archiving integration
PolicyCenter supports archiving policy terms as serialized streams of data, with one serialized stream per
PolicyPeriod entity in the term. You can store the serialized data in a file, in a document storage system, or in a
database as binary large object. Each serialized stream is an XML document.
IMPORTANT Guidewire strongly recommends that you contact Guidewire Support before
implementing archiving.
See also
• Application Guide
After archiving, PolicyCenter makes the PolicyPeriod data effectively immutable while that period is archived.
However, within one policy term, at any given instant, it is possible that one or more periods are archived but not all.
From the user interface standpoint, PolicyCenter considers a given policy term archived if one or more of the
periods in the term is archived, even if not all are archived.
If the plugin throws exceptions, the application sets the PolicyPeriod.ExcludedFromArchive Boolean property to
true and sets the PolicyPeriod.ExcludeReason to a description String. Check your logs for errors. If you have a
coding problem that sets this property, use the Archive Info screen to reset the PolicyPeriod.ExcludedFromArchive
flag to false.
There are two archiving-related plugin implementations in PolicyCenter. Both demonstration implementations are in
the gw.plugin.archive.impl package. The following table summarizes the role of each interface:
See also
• “Archive source plugin” on page 578
• “Archiving eligibility plugin” on page 586
IMPORTANT Your implementation of this plugin interface must connect to your own archive
backing store.
8. After archiving, PolicyCenter deletes most PolicyPeriod subtypes. However, PolicyCenter retains the
PolicyPeriod entity instance and its associated entity instances of type EffectiveDatedFields and
Document. Additionally, in certain circumstances, PolicyCenter retains certain other entities. See “Overview of
archiving integration” on page 573 for details.
574 chapter 28: Archiving integration
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• Configuration Guide
PolicyCenter then determines if the archive object is from an data model version that is earlier than the current
version. If this is the case, PolicyCenter runs upgrade steps on the object. This includes running any built-in upgrade
triggers as well as running customer-written upgrade steps that extend the built-in upgrade steps, for example:
• PolicyCenter performs built-in upgrade steps such as adding a column to the object.
• PolicyCenter runs customer upgrade steps such as upgrading the data in the data model extension properties.
Only after all upgrade triggers run does PolicyCenter attempt to convert the data object into a real entity instance
that matches the current data model of the application. If this process fails, the entire restore operation fails. If it
succeeds, the application commits the new data to the application database.
See also
• Upgrade Guide
See also
• System Administration Guide
• Configuration Guide
The process of tagging includes setting the ArchivePartition property on the root entity instance to a
non-null value. The tagging process helps the application determine what data to delete at the end of the
archiving process.
c. The worker internally generates a structure that represents an XML document for the archived
PolicyPeriod and its subtypes.
d. The worker serializes the XML structure into a stream of XML data as bytes. The worker outputs these
bytes as an java.io.InputStream object.
e. After archiving, PolicyCenter deletes most PolicyPeriod subtypes. However, PolicyCenter retains the
PolicyPeriod entity instance and its associated entity instances of type EffectiveDatedFields and
Document. Additionally, in certain circumstances, PolicyCenter retains certain other entities. See
“Overview of archiving integration” on page 573 for details.
f. The worker calls the archive source plugin store method. The first argument to the method is the input
stream that contains the serialized XML document. The second argument is the PolicyPeriod entity
instance to archive.
5. The worker commits the database transaction. This ends the database transaction for the preceding database
changes. If any changes before this step threw an exception, PolicyCenter rolls back all changes in the entire
transaction.
6. As the last step in the archiving process for each work item, the worker calls the archive source plugin method
storeFinally. PolicyCenter calls this method independent of whether the archive transaction succeeded. For
example, if some code threw an exception and the archive transaction never committed, PolicyCenter still
calls this method. Use this method to do any final clean up. To make any changes to entity data, you must run
your Gosu code within a call to Transaction.runWithNewBundle(block). That API sets up a bundle for
your changes, and then commits the changes to the database in one transaction. For details, see the Gosu
Reference Guide.
See also
• “Archive source plugin storage methods” on page 580
• “Archive source plugin utility methods” on page 583
• Application Guide
• System Administration Guide
• Configuration Guide
WARNING Do not attempt to modify the retrieved data in the retrieveFinally method.
Guidewire does not recommend, nor does Guidewire support, the use of this method to modify
archive data after you retrieve the data.
Before you delete the returned XML document, first consider whether it is important to compare what the archived
item looked like initially with a subsequent archive of the same item.
If the retrieval process does not complete successfully, then consult the application logs as well as the Server Tools
Archive Info screen. You must have administrative privileges to access this screen.
See also
• “Archiving web services” on page 128
• “Archive source plugin retrieve methods” on page 582
• “Archive source plugin utility methods” on page 583
• Application Guide
• System Administration Guide
gw.plugin.archive.impl.PCArchiveSourcePlugin
To retrieve archival data, PolicyCenter calls ArchiveSource method retrieve. The single argument to the
retrieve method is an entity type that implements the RootInfo delegate. Each RootInfo entity instance
encapsulates a summary of one archived entity.
In PolicyCenter, the archive root info entity is always a PolicyPeriod entity. The interface type RootInfo, in APIs
or in documentation, always refers to PolicyPeriod. Your plugin implementation must store enough information in
the PolicyPeriod entity type and its associated EffectiveDatedFields entity to determine how to retrieve any
archived document from the archive backing store.
In the base configuration, Guidewire provides the means to encrypt PolicyCenter data through the use of encryption
plugins that implement the gw.plugin.util.IEncryption interface. An encryption plugin encrypts data fields
(table columns) that you tag for encryption in the data model.
Each encryption plugin implementation must return a unique ID string from its getEncryptionIdentifier method.
The archival XML document contains the ID of the encryption plugin used to encrypt its tagged fields.
Configuration parameter DefaultXmlExportIEncryptionId sets the ID of the encryption plugin to use to encrypt
the XML data fields, both during the archive process and during the export of XML data. You can use the ID of any
existing encryption plugin for this purpose or create a custom encryption implementation with its own ID
specifically for exporting XML. The plugin implementation that you use for encryption must remain registered as
long as there are archive documents with that key (meaning that the XML documents that use that key have not been
purged from the archive store).
If you want to encrypt more than just the fields tagged as encrypted, leave the value of
DefaultXmlExportIEncryptionId empty and implement any strategy that you like for protecting sensitive
information. You will have to devise your own strategy also if there are no fields tagged as encrypted or if not all of
the sensitive fields are tagged.
In working with archival data, Guidewire recommends the following:
• Use a secure communication channel such as TLS in storing and retrieving the archival XML.
• Encrypt the entire XML document at rest using the facilities of the chosen storage system.
For an example of how to create an encryption class, see Gosu class PBEEncryptionPlugin in the following
Guidewire package:
gw.plugin.encryption.impl
See also
WARNING Be extremely careful that you understand potential failure conditions and the
relationship between each archive method and associated database transactions.
WARNING Do not generate event messages in the Event Fired rules for entity updates in the
archive Transaction bundle. These messages cause the archive transaction to fail.
For details for each plugin method, refer to reference information grouped by purpose of the methods:
• “Archive source plugin storage methods” on page 580
• “Archive source plugin retrieve methods” on page 582
• “Archive source plugin utility methods” on page 583
See also
• Configuration Guide
prepareForArchive
The IArchiveSource.prepareForArchive method has the following signature.
prepareForArchive(info : RootInfo)
The method call for prepareForAchive occurs outside the archive transaction. As such:
• PolicyCenter does not roll back any changes if the archiving operation fails.
• PolicyCenter does not commit changes automatically if the archiving operation succeeds.
You use this method for the (somewhat unusual) case in which you want to prepare some data regardless of whether
a domain graph instance actually archives successfully. The method has no transaction of its own. If you want to
update data, then you must create a bundle and commit that bundle yourself.
In PolicyCenter, the default plugin implementation of this method records the IDs of the UWIssueHistory entities to
delete after the archive operation completes.
updateInfoOnStore
The IArchiveSource.updateInfoOnStore method has the following signature.
updateInfoOnStore(info : RootInfo)
Whenever PolicyCenter receives a request to archive a RootInfo object, it first checks whether the entity instance is
eligible for archiving. After these checks runs, but before PolicyCenter deletes the entity information from the
database, it calls an internal method, updateInfoOnArchive, to prepare the entity for archiving. This internal
method in turn calls the updateInfoOnStore method.
580 chapter 28: Archiving integration
Guidewire PolicyCenter 9.0.6 Integration Guide
PolicyCenter calls the updateInfoOnStore method after the application prepares the data for archive but before
calling the store method. Despite the name of the updateInfoOnStore method, this method is not the only place to
modify the RootInfo entity. See the discussion on the store method.
PolicyCenter calls the updateInfoOnStore method inside the archiving transaction. This enables you to make
additional updates on RootInfo entities.
WARNING Do not create custom code that generates update events for any entity type that can
possibly be part of the archive bundle. Any active event messages in the archive transaction
bundle cause archiving to fail.
Depending on what kind of action undertaken in method updateInfoOnStore, it is possible that you need to
perform similar or complementary changes in plugin methods updateInfoOnRetrieve and updateInfoOnDelete.
WARNING Only modify the RootInfo entity (PolicyPeriod) in the updateInfoOnStore
method. It is dangerous and unsupported to modify any other entity instances in the policy period
graph in this method.
See also
• Configuration Guide
store
The IArchiveSource.store method has the following signature.
The store method is the main configuration point for taking XML data (in the form of an InputStream object) and
transferring it to an archive backing store.
PolicyCenter calls the store method inside the archiving transaction, after deleting rows from the database, but
before performing the database commit. Your implementation of this method must store the archive XML document.
During the method call, the archiving process passes in the java.io.InputStream object that contains the
generated XML document. This is the data that your Archive Source plugin must send to the archive backing store.
The archiving process passes in an instance of the RootInfo entity to the plugin so that it can insert or update
additional reference information to help with restore. Generally speaking, this is not the best place to make changes
to the RootInfo entity instance. Usually, it is best to make those changes in the updateInfoOnStore method.
Generally speaking, it is best to change no entity data at all in the store method. Within the store method (or any
other part of the data base transaction), the only properties that are safe to change are the non-array properties on the
RootInfo entity. The only safe reason to change entity data in the store method is to add a unique retrieval ID to an
extension property on the RootInfo entity. Only make this change from the store method if your archive backing
store requires this data for retrieval and that ID is only available after sending data.
If your plugin is unable to store the XML document, then PolicyCenter expects the plugin to throw an error.
PolicyCenter treats this error as a storage failure and rolls back the transaction. The transaction rollback also rolls
back any changes to entity instances that you set up in your updateInfoOnStore method call.
storeFinally
The IArchiveSource.storeFinally method has the following signature.
PolicyCenter calls this method outside the archiving transaction after completing that transaction. The value of the
finalStatus parameter indicates whether the archiving delete operation was successful. In the rare case in which
the delete transaction fails, it is possible to reverse any changes that were not part of the transaction.
To change any data, you must perform any entity instance modification within a call to
Transaction.runWithNewBundle(block). See the Gosu Reference Guide.
Archiving integration 581
Guidewire PolicyCenter 9.0.6 Integration Guide
If PolicyCenter calls this method with errors, the value of finalStatus is something other than success. The cause
parameter contains a list of String objects that describe the cause of any failures. The String objects are the text
for the exception cause hierarchy.
This permits two different design strategies:
• The recommended technique is to send and commit your data in the external source in the store method. If there
are failure conditions, you can use your implementation of the storeFinally method to back out of any changes
in the external data store. For example, you can delete any temporary files that the archive process created. The
demonstration implementation for this plugin illustrates this process.
• Alternatively, you can perform a two-stage commit. In other words, send the data to the external system in the
store method, but finalize the data in the storeFinally method if and only if parameter finalStatus indicates
success.
It is important to be careful about what kinds of work you perform in the storeFinally method to properly handle
error conditions. If the storeFinally method throws an exception, the application logs the exception, but
PolicyCenter has already completed the main database transaction. Be sure to carefully catch any exception and
handle all error conditions. There is no rollback or recovery that the application can perform if storeFinally does
not complete its actions due to errors or exceptions within the storeFinally implementation.
retrieve
The IArchiveSource.retrieve method has the following signature.
This method is the main configuration point for retrieving XML data from the archive backing store. You must
return the data as an InputStream object. The archiving process passes the RootInfo entity instance to the plugin
method to assist your plugin implementation to identify the correct data in the external system.
For archive retrieval to work correctly, the RootInfo object must store enough information to determine how to
retrieve the XML document from the archive backing store.
updateInfoOnRetrieve
The IArchiveSource.updateInfoOnRetrieve method has the following signature.
updateInfoOnRetrieve(info : RootInfo)
The retrieval process calls this method within the retrieval transaction. This occurs after the archiving process
populates the bundle of the RootInfo entity with the entities produced by parsing the XML returned by the earlier
call to retrieve(RootInfo).
From within the updateInfoOnRetrieve method, you can modify the new entity instances in the archive domain
graph as well as the RootInfo entity instance. For example, you can reset the date on which an entity type is eligible
for archiving again.
retrieveFinally
The IArchiveSource.retrieveFinally method has the following signature.
582 chapter 28: Archiving integration
Guidewire PolicyCenter 9.0.6 Integration Guide
The retrieval process calls this method as the last retrieval step, outside of the retrieve transaction. The value of the
finalStatus parameter indicates whether the retrieve was successful. Use this plugin method to perform other
actions on the storage.
It is up to you to decide what additional handling the retrieved data requires, if any. For example, you can use this
method to perform final clean up on files in the archive backing store.
IMPORTANT Guidewire does not recommend, nor does Guidewire support, the use of this method to
make changes to data after you retrieve the data. Any attempt to commit these changes in the
retrieveFinally method invokes the Preupdate and Validation rules. This is undesirable and
unsupported. As PolicyCenter commits the main transaction for the retrieve process, it does not run
these rules. Therefore, it is possible, for example, to retrieve entity instances that do not pass
validation rules. Committing additional changes in the retrieveFinally method could fail
validation, causing only those changes to be rolled back, not the entire retrieve request.
updateInfoOnDelete
The IArchiveSource.updateInfoOnDelete method has the following signature.
At some later time after archiving, it is possible for a user to decide to delete the archived entity instance entirely,
including the data that remained in the application database. Guidewire calls this process purging. During data
purging, it is possible to delete the archival data from the archive backing store, but Guidewire does not require that
you do so.
During purging, PolicyCenter calls the updateInfoOnDelete method to determine additional entity instances that
PolicyCenter must delete if it deletes the entity instance represented by RootInfo. PolicyCenter never calls this
method during the main archiving step. The delete process calls this method within the transaction in which it
deletes the RootInfo entity instance and related entities from the active database.
If your implementation of the updateInfoOnStore method creates extension entity instances that link to the
RootInfo entity type, return these entity instances using plugin method updateInfoOnDelete during a delete
operation.
The return type is a list of pair (Pair) objects. Each pair object is parameterized on the following:
• An entity type
• A list of Key objects. The Key contains the relevant object.ID value for that object.
Typically, it is inappropriate to make changes to entity instances in this method. If this method does make changes,
the application commits those changes before calling plugin method delete.
If you create entities in the updateInfoOnStore method that link to the RootInfo entity, return those entities in the
return results of this method. Generally speaking, if you mark an entity to delete by returning it from this method,
you must return also all entities that link to those entities.
The order of the types and IDs in the list is important. Deletion happens in the order in the list and deletion is
permanent. If entity type A links to entity type B, which links to the RootInfo entity type, you must return A before
B.
Typically you would determine the correct order of types and then delete all entities of that entity type all at once.
However, although usually unnecessary, Guidewire does support the option to return an entity type more than once
in the return list. Theoretically in complex configuration edge cases, it is possible that this is necessary to enforce
proper ordering of the deletion process. For example, this allows you to enforce the following deletion order:
1. Delete entity instance with ID 100 of type Type1.
2. Delete entity instance with ID 900 of type Type2.
3. Delete entity instance with ID 101 of type Type1, a type already mentioned.
delete
The IArchiveSource.delete method has the following signature.
delete(info : RootInfo)
Your implementation of this method must delete the data identified by the specified RootInfo entity from the
archive backing store. PolicyCenter calls the delete method during the purge process.
IMPORTANT In your implementation of the delete method, you must delete any documents and
associated document metadata linked to the archived entity instance.
The delete process calls this method after PolicyCenter deletes associated entities returned from the
updateInfoOnDelete method. See discussion of updateInfoOnDelete for more information.
getStatus
The IArchiveSource.getStatus method has the following signature.
getStatus()
The getStatus method returns an object that implements the ArchiveSourceInfo interface. The
ArchiveSourceInfo object has the following methods.
Method Returns
getAsOf Returns the date on which PolicyCenter generated the status information.
getDeleteStatus Returns a typekey from the ArchiveSourceStatus typelist. The typecode is one of the following:
getRetrieveStatus • Available ‐ Archiving service is available.
getStoreStatus • Failure ‐ Last attempt to archive failed.
• Manually flagged ‐ Archiving service was manually flagged as unavailable.
584 chapter 28: Archiving integration
Guidewire PolicyCenter 9.0.6 Integration Guide
Method Returns
• Not Configured ‐ Archiving service not configured.
• Not Enabled ‐ Archiving service not enabled.
• Not Started ‐ Archiving service not started.
• Queue Available ‐ Archiving service is not available. But, it is possible to add the request to the
archiving queue.
To retrieve a status value, use syntax similar to the following, with XXX being either Delete, Retrieve, or Store.
ArchiveSourceInfo.getStatus().getAsOf()
ArchiveSourceInfo.getStatus().getXXXStatus()
handleUpgradeIssues
The IArchiveSource.handleUpgradeIssues method has the following signature.
Use this method to mange a set of passed-in issues that occurred during an archive operation. In the base
configuration, the default implementation provides the means to log the archive issues.
refresh
The IArchiveSource.refresh method has the following signature.
refresh()
In the base configuration, this method sets a number of archive-related parameter values. Archive source plugin
method setParameters calls this refresh method.
retrieveSchema
The IArchiveSource.retrieveSchema method has the following signature.
retrieveSchema(platformMajor : int, platformMinor : int, appMajor : int, appMinor : int, extension : int) :
InputStream
This method retrieves the XSD associated with a data model + version number combination as a FileInputStream.
The XSD describes the format of the XML files for that version.
setParameters
The IArchiveSource.setParameters method has the following signature.
setParameters(parameters : Map)
In the base configuration, this method prints a warning in the archive log if the server is in production mode. The
warning indicates that the default sample implementation of the PCArchiveSourcePlugin plugin is not suitable for
production environments.
In addition, this method calls the plugin class “refresh” on page 585 method, which resets a number of archive-
related parameter values.
storeSchema
The IArchiveSource.storeSchema method has the following signature.
Archiving integration 585
Guidewire PolicyCenter 9.0.6 Integration Guide
storeSchema(platformMajor : int, platformMinor : int, appMajor : int, appMinor : int, extension : int,
schema : InputStream)
This method stores the XSD associated with the specified data model + version number combination. The XSD
describes the format of the XML files for that version.
The default implementation of this method checks for open claims and returns the latest date from the following set
of dates:
• Dates of all open claims
• Today’s date
See also
• Configuration Guide
It is possible to implement custom batch processing to supplement the batch processing provided in the base
configuration.
Work queue
A work queue operates on a batch of items in parallel. PolicyCenter distributes work queues across all servers in a
PolicyCenter cluster that have the appropriate role. In the base configuration, Guidewire assigns this functionality to
the workqueue server role.
A work queue comprises the following components:
• A processing thread, known as a writer, that selects a group (batch) of business records to process. For each
business record (a policy record, for example), the writer creates an associated work item.
• A queue of selected work items.
• One or more tasks, known as workers, that process the individual work items to completion. Each worker is a
short-lived task that exists in a thread pool. Each work queue on a cluster member shares the same thread pool.
By default, each work queue starts a single worker on each server with the appropriate role, unless configured
otherwise.
Work queues are suitable for high volume batch processing that requires the parallel processing of items to achieve
an acceptable throughput rate.
Batch process
A batch process operates on a batch of items sequentially. Batch processes are suitable for low volume batch
processing that achieves an acceptable throughput rate as the batch process processes items in sequence. For
example, writers for work queues operate as batch processes because they can select items for a batch and write
them to their work queues relatively quickly.
Custom batch processing 587
Guidewire PolicyCenter 9.0.6 Integration Guide
IMPORTANT Regardless of the volume of items or the duration of the processing window, Guidewire
strongly recommends that you implement all custom batch processing as a custom work queue.
“Nightly batch processing” on Processes business transactions accumulated at the end of specific business periods, such
page 588 as business days, months, quarters, or years.
“Daytime batch processing” on Defers to periodic asynchronous background processing complex transactional processing
page 589 triggered by user actions.
Depending on the category of your custom batch processing, certain implementation details can vary.
See also
See also
that your custom code uses is the Target field. The Target field holds the ID of a unit of work that your writer
selected. The code for your writer and your workers can safely ignore the other properties on work item instances.
However, you can define a custom work item type with additional fields for your custom code to use.
Guidewire recommends that you define your custom work item entities as keyable, rather than retireable. If you
define a custom work item as retireable, then you also need to create a custom batch process to purge the work
items after processes them and they become old and stale. This batch process also needs to clean up failed work
items as well. Any delay in purging failed or stale work items can prevent further operations such as archiving.
This query returns all work items for the process that match the filter criteria. The query includes failed work items
and work items in progress, not just the work items available for selection.
Error: Two work queues cannot use the same work item type
Guidewire does not support creating multiple work queues that use the same work item type, except for the
StandardWorkItem type. If you attempt to do so using a work item type other than StandardWorkItem,
PolicyCenter throws the following error:
Two work queues cannot use the same work item type at runtime: workItemType.Name
It is not possible for workers from different work queues to process work items from the same work item database
table. In this circumstance, it is not possible for the different sets of workers to determine which work items to
process. In any case, it is very likely that there can be database contention issues along with race conditions between
the workers in picking up the work items from the queue.
Start Failed
Create
Available
Checked Out
Delete
End
A work item begins life after the writer selects the units of work for a batch and returns an iterator for the collection.
The framework then creates work items that reference the units of work for a batch. The initial state of a work item
is available. At the time the framework checks out a quota of work items for a worker, the state of the work items
becomes checkedout. The framework then hands the quota of work items to the worker one at a time. After a
worker finishes processing a work item successfully, the framework deletes it from the work queue and updates the
statistics in the process history for the batch.
See also
• For more information on the lifecycle of work queues, see the System Administration Guide.
The following reasons outline why you would want to define a custom work item type:
• Include custom fields on work items not available on the StandardWorkItem entity type
• Avoid table contention with other work queues that typically process large batches at the same time
Whenever you define a custom work item type, you must implement the createWorkItem method that your custom
work queue inherits from WorkQueueBase.
If you create a custom work queue, your writer can pass more fields to the workers than a target field. On
StandardWorkItem, the Target field is an object reference to an entity instance, which represents the unit of work
for the workers. In a custom work item, you can define as many fields as you want to pass to the workers. Your
custom work item itself can be the unit of work.
Guidewire recommends that you use custom work queue types for work queues with typically large batches that
potentially run at the same time as other work queues with large batches. Especially if developing a custom work
queue for nightly batch processing, consider using a custom work queue type instead of using StandardWorkItem. If
you create a custom work item type to avoid table contention, you often define a single field for the writer to set,
much like the Target field on StandardWorkItem. By convention, you name the single field with the same name as
the entity type, not the generic name Target.
IMPORTANT Do not create multiple work queues that use the same work item type other than the
StandardWorkItem type. If you attempt to do so, PolicyCenter throws an error.
In creating a custom work item, you need to create a link from the custom work item table to the entity table that is
the target of the work item. To create this link, add a column element to your custom work item and use the
following parameters.
Name Value
name Target
type softentityreference
nullok false
For Target, enter the name of the entity on which the work items acts. Use softentityreference (a soft link)
rather than foreignkey (a hard link). A softentityreferece is a foreign key for which does not enforce integrity
constraints in the database. The use of a hard foreign key in this context would do the following:
• Require that you delete the work item row from the database before you delete or archive the linked entity row.
• Can force to include the custom work item table in the main domain graph. It is not usually desirable to include
such administrative entities in the domain graph for archiving along with the other data.
Guidewire recommends that you define your custom work item entities as keyable, rather than retireable. If you
define a custom work item as retireable, then you also need to create a custom batch process to purge the work
items after processes them and they become old and stale. This batch process also needs to clean up failed work
items as well. Any delay in purging failed or stale work items can prevent further operations such as archiving.
See also
Procedure
1. Open Guidewire Studio
2. In the Studio Project window, expand configuration→config→Extensions→Typelist.
3. Open BatchProcessType.ttx.
code Specify a code value that uniquely identifies your work queue. This code value identifies the work queue in con‐
figuration files.
name Specify a a human readable identifier for your work queue. This name appears for the work queue writer on the
Server Tools Batch Process Info screen.
desc Provide a short description of what your custom batch processing accomplishes. This description appears for your
batch processing type on the Server Tools Batch Process Info screen.
Procedure
1. Open Guidewire Studio.
2. Add a new entity for your custom work item type:
a. In the Studio Project window, expand configuration→config→Extensions→Entity.
b. Right-click Entity, and then select New→Entity.
c. In the Entity dialog, enter the appropriate values.
For example, if creating a new work item entity called MyWorkItem, enter the following values:
Table myworkitem
Type keyable
type Activity
nullok false
5. (Optional) Add other fields to your custom entity as meets your business needs.
Next steps
Whenever you define a custom work item for a work queue, your custom work queue class must implement the
createWorkItem method to write the work item to the queue.
findTargets Logic for the writer, which selects units of work for a batch and returns an iterator for the result set
processWorkItem Logic for the workers, which operates on a single unit of work selected by the writer
The WorkQueueBase provides other methods that you can override such as shouldProcessItem. However, you can
generally develop a successful custom work queue by overriding the two required methods findTargets and
processWorkItem.
WARNING Do not implement multi-threaded programming in custom work queues derived from
WorkQueueBase.
See also
• “Bulk insert work queues” on page 599
The following example code is the constructor for a custom work queue. It associates the class at runtime with its
batch process typecode MyWorkQueue. The code associates the work queue with the StandardWorkItem entity type.
So, the work queue shares its work queue table with many other work queues. The code associates the work queue
with the Activity entity type as its target unit of work type. So, the writer and the workers operate on Activity
instances.
construct () {
super (typekey.BatchProcessType.TC_MYWORKQUEUE, StandardWorkItem, Activity)
}
Do not include any code in the constructor of your custom work queue other than calling the super class constructor.
See also
• “Define a typecode for a custom work queue” on page 594
In the findTargets method logic, return a query builder iterator with the results you want as targets for the work
items in a batch. PolicyCenter uses the iterator to write the work items to the work queue. The findTargets method
is a template method for which you specify the target entity type, the same type for which you make a query builder
object.
The following example code is a writer for a work queue that operates on Activity instances. The query selects
activities that have not been viewed for five days or more and returns the iterator.
// Query the target type and apply conditions: activities not viewed for 5 days or more
var targetsQuery = Query.make(Activity)
targetsQuery.compare(Activity#LastViewedDate, LessThanOrEquals, java.util.Date.Today.addBusinessDays(-5))
return targetsQuery.select().iterator()
The following Gosu example code creates a new custom work item that has a single custom field, an Activity
instance. The implementation gives the target field in the parameter list the name activity to clarify the code. The
custom work item type is MyWorkItem.
if (activity.AssignedUser.Contact.EmailAddress1 != null) {
// Send an email to the user assigned to the Activity.
mailUtil.sendEmailWithBody(null,
activity.AssignedUser.Contact, // To:
null, // From:
"Activity not viewed for five days", // Subject:
"Take a look at activity " + target.Subject + ", due on " + target.TargetDate + ".") // Body:
}
return
In your override of the base processWorkItem method, specify the same work item entity type that you specified in
the constructor of your custom work queue class.
uses gw.transaction.Transaction
...
override function processWorkItem (WorkItem : StandardWorkItem): void {
// Extract the unit of work: an Activity instance
return
}
See also
• Gosu Reference Guide
Handling exceptions
In your custom work queue class, provide an implementation of the handleException method inherited from
WorkQueueBase to augment the actions taken whenever code in the processWorkItem method throws an exception.
For example, it is possible for your worker code to throw an exception whenever it encounters a logic error that
cannot resolve itself without human intervention.
The following sample code illustrates how to work with the handleException method.
if (ex typeis MyCustomWorkQueueException) { // Fail immediately for a custom work queue exception
workItem.fail(DateUtil.currentDate(), ex.getLocalizedMessage())
return true
} else { // Fail only for other exceptions if attempts exceeds retry count
return super.handleException(workItem, ex, consecutiveExceptions)
}
}
increments the consecutiveExceptions counter every time it encounters a problem. PolicyCenter then resets
the counter every time that it successfully processes a work item.
construct () {
super(BatchProcessType.TC_MYBULKINSERTWORKQUEUE, StandardWorkItem, User)
}
...
}
The following Gosu example code selects the units of work for a batch run, which are activities that no one has
viewed in five days or more. Notice that this implementation of the method uses the extractSourceQuery method
to generate the query result.
The excludeDuplicatesOnStandardWorkItem helper method excludes StandardWorkItem work items only. If you
query on another work item type, use custom code similar to the following to exclude the duplicate work items:
builder.mapColumn(XXWorkItem#Target.PropertyInfo as IEntityPropertyInfo,
XX#Id.PropertyInfo as IEntityPropertyInfo)
The following Gosu example code processes the units of work for a batch run, which are activities that no one has
viewed in five days or more.
if (activity.AssignedByUser.Contact.EmailAddress1 != null) {
// Send an email to the user assigned to the activity
EmailUtil.sendEmailWithBody(null, activity.AssignedUser.Contact, // To:
null, // From:
"Activity not viewed for five days", // Subject:
"See activity" + activity.Subject + ", due on " + activity.TargetDate + ".") // Body:
}
}
uses gw.api.database.Query
uses gw.api.database.Relop
uses gw.api.email.EmailUtil
uses gw.processes.BulkInsertWorkQueueBase
/**
* An example of batch processing implemented as a work queue that sends email
* to assignees of activities that have not been viewed for five days or more.
*/
class MyOptomizedActivityEmailWorkQueue extends BulkInsertWorkQueueBase <Activity, StandardWorkItem> {
/**
* Let the base class register this type of custom batch processing by
* passing the batch processing type, the entity type the work queue item, and
* the target type for the units of work.
*/
construct() {
super ( BatchProcessType.TC_NOTIFYUNVIEWEDACTIVITIES, StandardWorkItem, Activity )
}
/**
* Select the units of work for a batch run: activities that have not been
* viewed for five days or more.
*/
override function buildBulkInsertSelect(builder : Object, args: List<Object>) {
excludeDuplicatesOnStandardWorkItem(builder, true); // if using StandardWorkItem
extractSourceQuery(builder).compare(
Activity#LastViewedDate.PropertyInfo.Name, Relop.LessThanOrEquals,
java.util.Date.Today.addBusinessDays(-5) )
}
/**
* Process a unit of work: an activity not viewed for five days or more
*/
override function processWorkItem(workItem: StandardWorkItem) {
// Extract an object referenct to the unit of work: an Activity instance
var activity = extractTarget(workItem) // Convert the ID of the target to an object reference
if (activity.AssignedByUser.Contact.EmailAddress1 != null) {
uses gw.api.database.Query
uses gw.api.database.Relop
uses gw.api.email.EmailUtil
uses gw.processes.WorkQueueBase
uses java.util.Iterator
/**
* An example of batch processing implemented as a work queue that sends email
* to assignees of activities that have not been viewed for five days or more.
*/
class MyActivityEmailWorkQueue extends WorkQueueBase <Activity, StandardWorkItem> {
/**
* Let the base class register this type of custom batch processing by
* passing the batch processing type, the entity type the work queue item, and
* the target type for the units of work.
*/
construct() {
super ( BatchProcessType.TC_NOTIFYUNVIEWEDACTIVITIES, StandardWorkItem, Activity )
}
/**
* Select the units of work for a batch run: activities that have not been
* viewed for five days or more.
*/
/**
* Process a unit of work: an activity not viewed for five days or more
*/
override function processWorkItem(WorkItem: StandardWorkItem) {
// Extract an object referenct to the unit of work: an Activity instance
var activity = extractTarget(WorkItem) // Convert the ID of the target to an object reference
if (activity.AssignedByUser.Contact.EmailAddress1 != null) {
// Send an email to the user assigned to the activity
EmailUtil.sendEmailWithBody(null,
activity.AssignedUser.Contact, //To:
null, //From:
"Activity not viewed for five days", //Subject:
"See activity" + activity.Subject + ", due on " + activity.TargetDate + ".") //Body:
}
}
}
Notice that this work queue implementation uses a findTargets method to return an iterator of target objects on
which to base the work items.
See also
• “Example work queue that bulk inserts its work items” on page 601
uses gw.api.database.Query
uses gw.api.database.Relop
uses gw.api.email.EmailUtil
uses gw.processes.WorkQueueBase
uses gw.transaction.Transaction
uses java.util.Iterator
/**
* An example of batch processing implemented as a work queue that sends email
* to assignees of activities that have not been viewed for five days or more.
*/
class MyActivityEscalationWorkQueue extends WorkQueueBase <Activity, StandardWorkItem> {
/**
* Let the base class register this type of custom batch processing by
* passing the batch processing type, the entity type the work queue item, and
* the target type for the units of work.
*/
construct () {
super (typekey.BatchProcessType.TC_NOTIFYUNVIEWEDACTIVITIES, StandardWorkItem, Activity)
}
/**
* Select the units of work for a batch run: activities that have not been
* viewed for five days or more.
*/
override function findTargets (): Iterator <Activity> {
// Query the target type and apply conditions: activities not viewed for 5 days or more
var targetsQuery = Query.make(Activity)
targetsQuery.compare(Activity#LastViewedDate, Relop.LessThanOrEquals,
java.util.Date.Today.addBusinessDays(-5))
return targetsQuery.select().iterator()
}
/**
* Process a unit of work: an activity not viewed for five days or more
*/
override function processWorkItem (WorkItem : StandardWorkItem) {
// Extract an object referenct to the unit of work: an Activity instance
var activity = extractTarget(WorkItem)
}
}
See also
• “Custom work queues” on page 590
Procedure
1. Open Guidewire Studio.
2. In the Studio Project window, expand configuration→config→Extensions→Entity.
3. Right-click Entity and select New→Entity.
4. Enter the following information in the Entity dialog and click OK.
Entity MyWorkItem
Type keyable
Note: See “Considerations for developing a custom work queue” on page 592 for a discussion
as to why Guidewire recommends the use of softentityreference instead of foreignkey
here.
For all other fields, accept that dialog defaults.
5. Using the add functionality at the top of the left-hand column (the plus sign), add the following subelements to
the MyWorkItem entity.
Next steps
To use this custom work item, implement custom work queue MyActivitySetEscalationWorkQueue as defined in
“Implement custom work queue MyActivitySetEscalationWorkQueue” on page 605.
604 chapter 29: Custom batch processing
Guidewire PolicyCenter 9.0.6 Integration Guide
Procedure
1. Open Guidewire Studio
2. In the Studio Project window, expand configuration→gsrc.
3. Create a new package directory named workflow.
4. Within the workflow folder, create a new Gosu class named MyActivitySetEscalationWorkQueue.
5. Populate this class with the following code.
package workflow
uses gw.processes.WorkQueueBase
uses gw.api.database.Query
uses gw.api.database.Relop
uses java.util.Iterator
uses gw.transaction.Transaction
uses gw.api.email.EmailUtil
uses gw.pl.persistence.core.Bundle
/**
* An example of batch processing implemented as a work queue that sends email
* to assignees of activities that have not been viewed for five days or more.
*/
class MyActivitySetEscalationWorkQueue extends WorkQueueBase <Activity, MyWorkItem> {
/**
* Let the base class register this type of custom batch processing by
* passing the batch processing type, the entity type the work queue item, and
* the target type for the units of work.
*/
construct () {
super (typekey.BatchProcessType.TC_NOTIFYUNVIEWEDACTIVITIES, MyWorkItem, Activity)
}
/**
* Select the units of work for a batch run: activities that have not been
* viewed for five days or more.
*/
override function findTargets (): Iterator <Activity> {
// Query the target type and apply conditions: activities not viewed for 5 days or more
var targetsQuery = Query.make(Activity)
targetsQuery.compare(Activity#LastViewedDate.PropertyInfo.Name, Relop.LessThanOrEquals,
java.util.Date.Today.addBusinessDays(-5))
return targetsQuery.select().iterator()
}
/**
* Write a custom work item
*/
override function createWorkItem (activity : Activity, safeBundle : Bundle) : MyWorkItem {
var customWorkItem = new MyWorkItem(safeBundle)
customWorkItem.Activity = activity
return customWorkItem
}
/**
* Process a unit of work: an activity not viewed for five days or more
*/
override function processWorkItem (workItem : MyWorkItem): void {
// Get an object reference to the activity
var activity = workItem.Activity
activity.AssignedUser.Contact // To:
null, // From:
"Activity not viewed for five days", // Subject:
"See activity " + activity.Subject + ", due on " +
activity.TargetDate + ".") // Body:
}
return
}
}
IMPORTANT Regardless of the volume of items or the duration of the processing window, Guidewire
strongly recommends implementing any type of custom batch processing as a custom work queue.
See also
• “Examples of custom batch processes” on page 613
• “Categorizing a batch processing typecode” on page 616
Procedure
1. In Studio, edit the BatchProcessType typelist and add a typecode to represent your custom batch process.
Note: Creating this new typecode adds support for the new batch process within the
BatchProcessInfo PCF and the IMaintenanceToolAPI web service.
2. Create a class that extends the BatchProcessBase class (gw.processes.BatchProcessBase). The only
method you must override is the doWork method, which takes no arguments. Do your batch processing work in
this method.
3. In Studio, in the Plugins editor, register your new plugin for the IProcessesPlugin plugin interface.
4. To schedule your custom batch process to run regularly on a schedule instead of on demand, add an entry for
the batch process to the XML file scheduler-config.xml.
See also
• “Batch process base class” on page 608
• “Categorizing a batch processing typecode” on page 616
• “Implementing the processes plugin” on page 617
• System Administration Guide
Procedure
1. Open Guidewire Studio.
2. In the Studio Project window, expand configuration→config→Extensions→Typelist.
3. Open BatchProcessType.ttx.
code Specify a code value that uniquely identifies your type of custom batch processing. This code value identifies the
custom batch processing in configuration files.
name Specify a a human readable identifier for your type of custom batch processing. This name appears for batch
processing type on the Server Tools Batch Process Info screen.
desc Provide a short description of what your custom batch processing accomplishes. This description appears for your
batch processing type on the Server Tools Batch Process Info screen.
6. Select the newly added typecode.
7. Select Add new…→typecode→category from the right-click context menu.
This action adds a new category element under the selected typecode.
8. For this category, define the following fields:
Custom batch processing 607
Guidewire PolicyCenter 9.0.6 Integration Guide
code Select one of the available choices from the drop‐down list. You must add at least one category or your batch
process cannot run.
Result
Creating this new typecode adds support for the new batch processing type within the BatchProcessInfo PCF and
the IMaintenanceToolAPI web service.
IMPORTANT PolicyCenter calls the requestTermination method in a different thread from the
thread that runs the doWork method of your batch process.
See also
• “Useful properties on class BatchProcessBase” on page 608
• “Useful methods on class BatchProcessBase” on page 609
• Gosu Reference Guide
Property Description
DetailStatus Returns the detailed status for the batch type. Class BatchProcessBase defines a simple default im‐
plementation. Override the default property getter to provide more useful detail information about
the status of your batch process for the PolicyCenter Administration screens. The details might be im‐
portant if your class experiences any error conditions.
For Java implementations, you must implement this property getter as the method getDetailStatus,
which takes no arguments.
Exclusive Sets whether another instance of this batch process can start while the current process is still running.
The base class implementation of the isExclusive method always returns true. Override the
isExclusive method if you need to customize this behavior. This value does not affect whether other
batch process classes can run. It only affects the current batch process class.
For maximum performance, be sure to set the property value to false, if possible. For example, if
your batch process takes arguments in its constructor, it might be specific to one entity such as only a
single Policy entity. If you want to permit multiple instances of your batch process to run in parallel,
you must ensure your batch process class implementation returns false. For example,
For Java implementations, implement this property getter as the method isExclusive, which takes
no arguments.
Property Description
Finished Returns a Boolean value to indicate whether the process completed. Completion says nothing about
the errors, if any.
For Java implementations, implement this property getter as the isFinished method.
OperationsCompleted Returns a count of how many operations are complete, as an integer value.
For Java implementations, implement this property getter as the getOperationsCompleted method.
OperationsExpected Returns a count of how many operations PolicyCenter expects the batch process to perform, as an
integer value.
For Java implementations, implement this property as the getOperationsExpected method.
OperationsFailed Returns an internal count for the number of operations that failed.
For Java implementations, implement property getter as the getOperationsFailed method.
Progress Dynamically returns the progress of the batch process. The base class returns text in the form x of y,
with x being the amount of work completed and y being the total amount of work. If the value of y is
unknown, the property merely returns x. PolicyCenter determines the values of x and y from the
OperationsExpected and OperationsCompleted properties.
For Java implementations, implement the property getter as the getProgress method.
TerminateRequested Returns a Boolean value that is the return value from the requestTermination method.
Type Returns the type of the current batch process. There is no need to override the default
BatchProcessBase implementation of this property.
For Java implementations, implement the property getter as the getType method, which takes no ar‐
guments.
checkInitialConditions
The BatchProcessBase.checkInitialConditions method has the following signature.
checkInitialConditions()
The checkInitialConditions method is a no-argument class method. It is possible for the batch process manager
to call this method multiple times for the same batch job as it processes that job.
PolicyCenter instantiates batch process classes at startup on servers with the batch server role. Later, PolicyCenter
calls the checkInitialConditions method to determine whether to start a batch process:
• If the method returns true, PolicyCenter starts the batch process by calling its doWork method.
• If the method returns false, the initial conditions are not met and PolicyCenter does not call the doWork method,
skipping the batch process for the time being.
The base class implementation of the checkInitialConditions method always returns true. You must override
this method if you want to provide a conditional response. If you override the checkInitialConditions method,
be certain your code completes and returns quickly. Do not include long running code, such as queries of the
database. The intent of the method is to determine environmental conditions, such as server run level. If you want to
check initial conditions of data in the database, perform the query in the doWork method.
The batch process base class automatically ensures the server is at the maintenance run level if you configure your
batch process typecode with the MaintenanceOnly category. You can perform additional checks of the current
server run level by overriding the checkInitialConditions method.
If you override the checkInitialConditions method, forward the call to the superclass before returning. If the
superclass returns false, you must return false. If the superclass returns true, then perform your additional checks
of environmental conditions and return true or false appropriately.
Custom batch processing 609
Guidewire PolicyCenter 9.0.6 Integration Guide
For example, suppose that your implementation of the checkInitialConditions method checks whether the
necessary files are available for processing. In some cases, it can be necessary to schedule a batch process to run
more often than the actual schedule of input files arriving for processing. In such a case, it is better for the
checkInitialConditions method to return true to indicate that the batch job is ready to run. You then log an
INFO or WARN message to the effect that the necessary files are missing.
getDescription
The BatchProcessBase.getDescription method has the following signature.
getDescription()
The getDescription method is a no-argument method that retrieves the description of the current batch type. The
base class retrieves this string from the batch type typecode description. Override this method if you need to
customize this behavior.
incrementOperationsCompleted
The BatchProcessBase.incrementOperationsCompleted method has the following signature.
incrementOperationsComplete()
The incrementOperationsCompleted method is a no-argument method that increments an internal counter for how
many operations are complete. For example, suppose your batch process iterates across entities of some type with
special conditions and specially handle each found item. For each entity you modify, call this method once to track
the progress of this batch process.
This method returns the current number of operations that are complete. It is possible to use the returned value in the
following ways:
• In the PolicyCenter user interface to show the progress of the batch process
• In debugging code to track the progress of the batch process
Note: For each entity for which you have an error condition, call this method once to track the
progress of this batch process.
incrementOperationsFailed
The BatchProcessBase.incrementOperationsCompleted method has the following signature.
incrementOperationsFailed()
The incrementOperationsFailed method is a no-argument method that increments an internal counter for how
many operations failed. For example, suppose your batch process iterates across entities of some type with special
610 chapter 29: Custom batch processing
Guidewire PolicyCenter 9.0.6 Integration Guide
conditions and specially handle each found item. For each entity for which you have an error condition, call this
method once to track the progress of this batch process.
This method returns the current number of operations failed. It is possible to use the returned value in the following
ways:
• In the PolicyCenter user interface to show the progress of the batch process
• In debugging code to track the progress of the batch process
IMPORTANT For any operations that fail, call both the incrementOperationsFailed method and the
incrementOperationsCompleted method.
requestTermination
The BatchProcessBase.requestTermination method has the following signature.
requestTermination()
IMPORTANT PolicyCenter calls the requestTermination method in a different thread from the
thread that runs your batch process doWork method.
WARNING Although you can return false from requestTermination, Guidewire strongly
recommends you design your batch process so that you actually can terminate the action. It is
critical to understand that returning either value does not prevent the application from shutting
down or reducing run level. PolicyCenter delays shutdown or change in run level for a period of
time. However, eventually the application shuts down or reduces run level independent of this
batch process setting. For maximum reliability and data integrity, design your code to frequently
check and respect the TerminateRequested property.
PolicyCenter writes a line to the application log to indicate whether it is possible to terminate the batch process. In
other words, the log line includes the result of your requestTermination method.
If your batch process can only run one instance at a time, returning true does not remove the batch process from the
internal table of running batch processes. This means that another instance cannot run until the previous one
completes.
setChunkingById
The BatchProcessBase.setChunkingById method has the following signature.
Custom batch processing 611
Guidewire PolicyCenter 9.0.6 Integration Guide
After processing the returned items, the Gosu query will issue another SQL query:
Unfortunately, this query skips chunksize unprocessed items because processing the first chunk of data alters the
input to the subsequent query.
In general, the use of ID chunking is not useful if the query SELECT statement selects for certain specific columns
only. Row-based chunking is frequently more useful in querying entities, if there is no change to the entities that
affects subsequent queries.
The following code sample illustrates the use of the setChunkingById method.
uses gw.processes.BatchProcessBase
uses gw.processes.ProcessHistoryPurge
uses gw.transaction.Transaction
setChunkingById(query, _batchSize)
OperationsExpected = query.getCount()
}
}
In this code, notice the use of the following BatchProcessBase properties and methods:
• Property OperationsExpected
• Property TerminateRequested
• Method setChunkingById
• Method incrementOperationsCompleted
Notice also that you must create a TestChunking typecode on BatchProcessType.
See also
• “Useful properties on class BatchProcessBase” on page 608
• “incrementOperationsCompleted” on page 610
• “incrementOperationsFailed” on page 610
• Gosu Reference Guide
See also
• “Developing custom batch processing types” on page 606
package gw.processes
uses gw.processes.BatchProcessBase
uses java.lang.Integer
uses gw.api.system.PLConfigParameters
uses gw.api.admin.WorkflowUtil
construct() {
this(null)
}
construct(arguments : Object[]) {
super(typekey.BatchProcessType.TC_PURGEWORKFLOWS)
if (arguments != null) {
_succDays = arguments[0] != null ? (arguments[0] as Integer) : _succDays
}
}
WorkflowUtil.deleteOldWorkflowsFromDatabase( _succDays )
}
IMPORTANT You must use the runWithNewBundle API if want to modify entity data in your custom
batch process.
See also
• “Define a typecode for a custom work queue” on page 594
• Gosu Reference Guide
package sample.processes
uses gw.api.database.Query
uses gw.api.email.Email
uses gw.api.email.EmailContact
uses gw.api.email.EmailUtil
uses gw.api.profiler.Profiler
uses gw.api.profiler.ProfilerTag
uses gw.api.util.DateUtil
uses gw.processes.BatchProcessBase
uses java.lang.StringBuilder
uses java.util.HashMap
uses java.util.Map
//If BatchProcessType typcode TestBatch does not exist, you must create it.
construct() {
super( BatchProcessType.TC_TESTBATCH )
}
try {
if (!haveContact) {
incrementOperationsFailed()
addFragmentToUser(map, User.util.UnrestrictedUser, msgFragment)
}
}
if (not TerminateRequested) {
for (addressee in map.Keys) {
sendMail(addressee, "Urgent activities still open", map.get(addressee).toString())
}
} finally {
Profiler.pop(frame)
}
}
if (sb == null) {
sb = new StringBuilder()
map.put(user.Contact, sb)
}
sb.append(msgFragment)
return true
}
}
return false
}
" </head>\n" +
" <body>\n" +
" <table>\n" +
" <tr><th>Subject</th><th>User</th><th>Group</td><th>Supervisor</th></tr>" +
" </table>" +
" </body>" +
"</html>"
email.addToRecipient(new EmailContact(contact))
EmailUtil.sendEmailWithBody(null, email);
}
}
To use this entry point, create the following PCF entry point file with name Activity.
<PCF>
<EntryPoint authenticationRequired="true" id="Activity" location="ActivityForward(actvtIdNum)">
<EntryPointParameter locationParam="actvtIdNum" type="int"/>
</EntryPoint>
</PCF>
<PCF>
<Forward id="ActivityForward">
<LocationEntryPoint signature="ActivityForward(actvtIdNum : int)"/>
<Variable name="actvtIdNum" type="int"/>
<Variable name="actvt" type="Activity">initialValue="find(a in Activity
where a.ID == new Key(Activity, actvtIdNum))"</>
<ForwardCondition action="PolicyForward.go(actvt.Policys);
ActivityDetailWorksheet.goInWorkspace(actvt)"/>
</Forward>
</PCF>
IMPORTANT You must use the runWithNewBundle transaction method to modify entity data in your
custom batch process. For more information, see the Gosu Reference Guide.
See also
• System Administration Guide
UIRunnable The process is runnable both from the user interface and from the web service APIs.
The Work Queue Info screen shows your custom work queue, regardless how you categorize your batch processing
type code. Categorizing a batch processing type code affects only whether the Batch Process Info screen displays
custom batch processes and writers for work queues and their runnable characteristics.
See also
• “Define a typecode for a custom work queue” on page 594
• “Define a typecode for a custom batch process” on page 607
• To learn how to add categories to a typecode, see the Configuration Guide.
See also
• System Administration Guide
configuration→config→gsrc→gw→plugin→processes
For each typecode in the BatchProcessType that represents a custom batch process, PolicyCenter calls the
createBatchProcess method of the Processes plugin. The createBatchProcess method takes a typecode from
the BatchProcessType as a parameter. The method uses a switch statement and a case clause to determine which
batch processing type to instantiate.
The following example code demonstrates how to implement the IProcessesPlugin plugin. The code instantiates
the individual custom batch process in the switch case statements.
uses gw.plugin.processing.IProcessesPlugin
uses gw.processes.BatchProcess
@Export
class ProcessesPlugin implements IProcessesPlugin {
construct() { }
construct() {
this({PCConfigParameters.KeepCompletedMessagesForDays.Value})
}
construct(arguments : Object[]) {
super(BatchProcessType.TC_PURGEMESSAGEHISTORY)
if (arguments.length == 1 and arguments[0] typeis Integer) {
_ageInDays = Coercions.makeIntFrom(arguments[0])
} else {
_ageInDays = PCConfigParameters.KeepCompletedMessagesForDays.Value
}
}
...
}
Notice, however, that the constructor with arguments performs no actual programming logic. It simply determines
the value to use in initializing the batch process.
Starting a batch process with initialization parameters from the command prompt
Use the -startprocess command, available with the maintenance_tools command prompt utility, to start a batch
process. Using this command, it is possible to start the batch process with, or without, initialization parameters. Use
the following syntax.
To use arguments in instantiating custom batch processing, use the createBatchProcess(type, args) method on
the ProcessesPlugin class. In this way, you can pass initialization parameters to the batch process constructor
called by the new operation.
Use this method to start a batch process with initialization parameters, for example:
The typecode for the batch processing type must include the APIRunnable category in order to start your custom
batch process with the MaintenanceToolsAPI web service.
See also
• “Categorizing a batch processing typecode” on page 616
• “Implementing the processes plugin” on page 617
• “Running batch processes by using web services” on page 98
• System Administration Guide
See also
• System Administration Guide
Custom batch processing 619
Guidewire PolicyCenter 9.0.6 Integration Guide
In your implementation of this interface, override the completed method to perform specific actions after a work
queue or batch process completes a batch of work. Add a case clause to the method for your type of custom batch
processing by specifying its typecode from the BatchProcessType typelist, for example:
switch(type) {
case BatchProcessType.TC_ACTIVITYESC:
return new ActivityEscalationWorkQueue()
case BatchProcessType.TC_MYCUSTOMBATCHPROCESS:
return new MyCustomBatchProcess()
...
default:
return null
}
See also
• System Administration Guide
See also
• “Maintenance tools web service” on page 98
• System Administration Guide
For details of the batch processes that you can use to purge outdated data, see the following:
• System Administration Guide
See also
If you need to set the User.ExternalUser field in a batch process, Guidewire recommends that you take the
following steps to manage this process.
Procedure
See also
PolicyCenter free-text search is an alternative to database search that can return results faster for certain search
requests than database search. Free-text search depends on an external full-text search engine, the Guidewire Solr
Extension. Free-text search provides two plugins that connect free-text search in PolicyCenter with the
Guidewire Solr Extension.
See also
• Configuration Guide
• Installation Guide
In the base configuration, the host parameter specifies localhost, which generally is correct for development
environments. For production environments however, Guidewire requires that you set up the application server
instance for the Guidewire Solr Extension on a host separate from the one that hosts PolicyCenter. For production
environments, you must modify the host parameter to specify the remote host where the Guidewire Solr Extension
runs.
If you configure free-text search for embedded operation, the plugins connect to the Guidewire Solr Extension
without using the HTTP protocol. With embedded operation, the Guidewire Solr Extension runs as part of the
PolicyCenter application, not as an external application. With embedded operation, the plugins ignore any host name
and port number parameters specified in solrserver-config.xml. Free-text search does not support embedded
operation in production environments.
IMPORTANT You must set the debug parameters to false in a production environment.
See also
• “Messaging and events” on page 295
624 chapter 30: Free‐text search integration
Guidewire PolicyCenter 9.0.6 Integration Guide
Field Value
Enabled The checkbox is selected.
Destination ID 69
Name Java.MessageDestination.SolrMessageTransport.Policy.Name
Events • ContactChanged
• ContactAdded
• ContactRemoved
• JobPurged
• PolicyAddressChanged
• PolicyPeriodAdded
• PolicyPeriodChanged
• PolicyPeriodPurged
• PolicyPeriodRemoved
• PolicyPurged
• PreemptedPeriod
Max Retries 3
gw.solr.PCSolrSearchPlugin
If you add or remove free-text search fields from your configuration, you must modify the implementation of
PCSolrSearchPlugin.
To edit the Plugins Registry item for the ISolrSearchPlugin interface, in the Project window in Studio, navigate to
configuration→config→Plugins→registry, and then open ISolrSearchPlugin.gwp.
See also
• Configuration Guide
Servlets
The @Servlet annotation lets you define simple web servlets for your PolicyCenter application. A servlet is a small
program that runs on a web server to process and answer client requests.
Implementing servlets
You can define simple web servlets inside your PolicyCenter application. Using this approach, you can define
extremely simple HTTP entry points to custom code. Use this technique to define arbitrary Gosu code that a user or
tool can call from a configurable URL. The URL stem for a servlet appends /service to the base URL for your
PolicyCenter application, for example:
http://serverName:8180/pc/service/servletQueryPath
A Gosu block determines from the URL whether your servlet owns the HTTP request. The Gosu annotation
@Servlet identifies the class as a servlet. You register your servlet with PolicyCenter by adding an entry in the file
PolicyCenter/configuration/config/servlet/servlets.xml.
Servlets are separate from web services that use the SOAP protocol. Servlets are also separate from the Guidewire
PCF entry points feature.
Note: Servlets provide no built-in object serialization or deserialization, such as the SOAP protocol
supports.
The PolicyCenter servlet implementation uses standard Java classes in the package javax.servlet.http to define
the servlet request and response. The base class for your servlet must extend javax.servlet.http.HttpServlet
directly, or extend a subclass of it. The typical servlet methods that you implement have
javax.servlet.http.HttpServletRequest and javax.servlet.http.HttpServletResponse objects as
parameters. Extending the base class javax.servlet.http.HttpServlet provides no inherent security for the
servlet.
By default, users can trigger servlet code without authenticating. Accessing PolicyCenter without authentication is
dangerous in a production system.
WARNING You must add your own authentication system for servlets to protect information and
data integrity. Carefully read “Implementing servlet authentication” on page 631. If you have
any questions about server security, contact Guidewire Customer Support.
PolicyCenter includes abstract classes that you can extend to provide authentication in the gw.servlet package. If
you need your servlet to perform tasks other than simple authentication, you can use static methods on the utility
class, gw.servlet.ServletUtils.
Servlets 627
Guidewire PolicyCenter 9.0.6 Integration Guide
During the development of your servlet, you can send debug messages to the Studio console by using the print
method. When your development is complete, you can log information about the servlet usage by retrieving the
desired logger by calling the forCategory method in the gw.api.system.PCLoggerCategory class.
Procedure
1. Write a Gosu class that extends the class javax.servlet.http.HttpServlet.
2. Add the @Servlet annotation on the line before your class definition:
3. Override the service method to do your actual work. Your service method takes a servlet request object
(HttpServletRequest) and a servlet response object (HttpServletResponse) as parameters.
4. In your service method, determine what work to do using the servlet request object.
WARNING You must add your own authentication system for servlets to protect information
and data integrity. If you have questions about server security, contact Guidewire Customer
Support.
In your service method, write an HTTP response using the servlet response object. The following simple
response sets the content MIME type and the status of the response (OK):
resp.ContentType = "text/plain"
resp.setStatus(HttpServletResponse.SC_OK)
To write output text or binary data, use the Writer property of the response object.
PolicyCenter/configuration/config/servlet/servlets.xml
Add one <servlet> element that references the fully qualified name of your class.
<servlets xmlns="http://guidewire.com/servlet">
<servlet class="mycompany.test.servlets.TestingServlet"/>
</servlets>
See also
• “Example of a basic servlet” on page 629
• “Implementing servlet authentication” on page 631
Procedure
1. Run the QuickStart server with the following command:
gwb runServer
http://localhost:8180/pc/service/test
The text "/test" in the URL is the part that matches the servlet string. Change the port number and the server
name to match your PolicyCenter application.
The following text appears on the page:
package mycompany.test.servlets
uses gw.servlet.Servlet
uses javax.servlet.http.HttpServletRequest
uses javax.servlet.http.HttpServletResponse
uses javax.servlet.http.HttpServlet
// ** SECURITY WARNING - FOR REAL PRODUCTION CODE, ADD AUTHENTICATION CHECKS HERE!
See also
• “Implementing servlet authentication” on page 631
@Servlet annotation
You must pass arguments to the @Servlet annotation to specify the URLs that your servlet handles. You provide a
search pattern to test against the servlet query path. The servlet query path is every character after the computer
name, the port, the web application name, and the word "/service". Multiple versions of the annotation constructor
support different use cases.
• @Servlet(pathPattern : String)
Use this annotation constructor syntax for high-performance pattern matching, with less flexibility than full
regular expressions.
This annotation constructor declares the servlet URL pattern matching to use Apache
org.apache.commons.io.FilenameUtils wildcard syntax. Apache FilenameUtils syntax supports Unix and
Windows file names with limited wild card support for ? (single character match) and * (multiple character
Servlets 629
Guidewire PolicyCenter 9.0.6 Integration Guide
match) similar to DOS file name syntax. The syntax also supports the Unix meaning of the ~ symbol. Matches
are always case sensitive.
• @Servlet(pathMatcher : block( path : String ) : boolean)
Use this annotation constructor syntax for highly flexible pattern matching.
You pass a Gosu block that can do arbitrary matching on the servlet query path. Performance depends greatly on
what you do in your block. As a parameter for the annotation, pass a Gosu block that takes a URL String. Write
the block such that the block returns true if and only if the URL matches what your servlet handles.
If you only use the startsWith method of the String argument, for example path.startsWith("myprefix"),
the servlet URL checking code is high performance.
You could use other methods to do more flexible pattern matching, such as full regular expressions. Using full
regular expressions lowers performance for high volumes of servlet calls. The following example uses regular
expressions with the matches method on the String type:
This example servlet responds to URLs that start with the text "/test" in the servlet query path, and optionally a
slash followed by other text:
◦ A single page URL:
http://localhost:8180/pc/service/test
http://localhost:8180/pc/service/test/is/this/working
To match multiple page URLs that are not described in traditional hierarchies as a single root directory with
subdirectories, you could intercept URLs with the regular expression:
http://localhost:8180/pc/service/test1/my_magic_subfolder_one_level_down
http://localhost:8180/pc/service/test2/my_magic_subfolder_one_level_down
http://localhost:8180/pc/service/test3/my_magic_subfolder_one_level_down
The package gw.servlet provides abstract classes that you extend to create a servlet that provides user
authentication. The class AbstractGWAuthServlet translates the security headers in the request and authenticates
with the Guidewire server. The subclass AbstractBasicAuthenticationServlet authenticates using HTTP basic
authentication. These classes support using only one type of authentication at run time. To support both HTTP basic
authentication and Guidewire authentication in the same servlet, extend HTTPServlet and use utility methods from
the ServletUtils class. By using ServletUtils, you can use the session key if available and if not you can use
HTTP Basic authentication headers or custom headers.
For security reasons, a servlet saves the connection's session ID only if the HTTP connection is secure (HTTPS).
This behavior can be changed for network topologies that secure the connection through other means, such as by not
allowing external access to the server. To force the saving of the connection's session ID, set the system property
gw.servlet.ServletUtils.BypassIsSecure to true.
Guidewire recommends that your servlets use HTTP basic authentication, which is supported by the
AbstractBasicAuthenticationServlet class.
Procedure
1. Write a Gosu class that extends the class gw.servlet.AbstractBasicAuthenticationServlet.
2. Add the @Servlet annotation on the line before your class definition:
3. Override the applicable REST method, for example, the doGet method, to do your actual work. Your method
takes a servlet request object (HttpServletRequest) and a servlet response object (HttpServletResponse)
as parameters.
4. In your method, determine what work to do using the servlet request object.
In your doGet method, write an HTTP response using the servlet response object. The following simple
response sets the content MIME type and the status of the response (OK):
resp.ContentType = "text/plain"
resp.setStatus(HttpServletResponse.SC_OK)
To write output text or binary data, use the Writer property of the response object.
PolicyCenter/configuration/config/servlet/servlets.xml
Add one <servlet> element that references the fully qualified name of your class:
servlets xmlns="http://guidewire.com/servlet">
<servlet class="mycompany.test.servlets.TestingServlet"/>
servlets>
Servlets 631
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• “Example of a basic authentication servlet” on page 632
Procedure
1. Run the QuickStart server with the following command:
gwb runServer
http://localhost:8180/pc/service/test
The text "/test" in the URL is the part that matches the servlet string. Change the port number and the server
name to match your PolicyCenter application.
3. In the authentication dialog box that appears, type valid login credentials.
The following text appears on the page:
http://localhost:8180/pc/service/test/is/this/working?param=value
5. To test the HTTP basic authentication without using the default login dialog:
a. Close your browser to remove the session context.
b. Re-test your servlet, using a tool that supports adding HTTP headers for HTTP basic authentication.
pattern, the servlet displays the PathInfo property of the response object, which contains the path. This servlet also
sends debug messages to the Studio console when you run the Quickstart server.
package mycompany.test.servlets
uses gw.servlet.Servlet
uses gw.servlet.AbstractBasicAuthenticationServlet
uses javax.servlet.http.HttpServletRequest
uses javax.servlet.http.HttpServletResponse
resp.ContentType = "text/plain"
resp.setStatus(HttpServletResponse.SC_OK)
resp.Writer.append("I am the page " + req.PathInfo)
}
// -- TODO -------------
// Read the headers and return false if user is already authenticated
// ---------------------
return true
}
}
This servlet responds to URLs with the word test in the service query path, such as the URL:
http://localhost:8180/pc/service/test/is/this/working
For full documentation on the HTTPServlet class, refer to this Oracle Javadoc page:
http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html
To use the session key created from a Guidewire application that shares the same application context, you can write
your servlet to extend the class gw.servlet.AbstractGWAuthServlet. You can use methods on the ServletUtils
class to check the current authentication status of the session. You must override the following methods:
• service – Your main task is to override the service method to do your required work. To check the HTTP
request type, call the getMethod method on the servlet request object. PolicyCenter already authenticates the
session key if it exists before calling your method.
• authenticate – Create and return a session ID.
• storeToken – You can store the session token in this method, or you can leave your method implementation
empty.
• invalidAuthentication – Return a response for invalid authentication. For example:
Arbitrary user login Use the login method to pass an arbitrary user • HttpServletRequest
name / pass‐ and password as String values and authenti‐ object
word pair cate with PolicyCenter. For example, you might • Username as a String
use a corporate implementation of single sign‐ • Password as a String
on (SSO) authentication that stores information
in HTTP headers other than the HTTP basic
headers. You can get the user name and pass‐
word and call this method. This method forces
creation of a new session.
In a single sign‐on environment, get the current
session before calling login. Then, if necessary,
do HTTP basic authentication.
Always check the return value. The method re‐
turns null if authentication failed.
For login problems, this method might throw
the exception
gw.api.webservice.exception.LoginExcepti
on.
See also
• “Example of a servlet using multiple authentication types” on page 635
package mycompany.test
uses gw.servlet.Servlet
uses javax.servlet.http.HttpServletRequest
uses javax.servlet.http.HttpServletResponse
uses javax.servlet.http.HttpServlet
Servlets 635
Guidewire PolicyCenter 9.0.6 Integration Guide
// SESSION AUTH : Get user from session if the client is already signed in.
var user = gw.servlet.ServletUtils.getAuthenticatedUser(req, true)
//print("Session user result = " + user?.DisplayName)
// HTTP BASIC AUTH : If the session user cannot be authenticated, try HTTP Basic
if (user == null) {
try {
user = gw.servlet.ServletUtils.getBasicAuthenticatedUser(req)
//print("HTTP Basic user result = " + user?.DisplayName)
} catch (e) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Unauthorized. HTTP Basic authentication error.")
return // Be sure to RETURN early because authentication failed!
}
}
if (user == null) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Unauthorized. No valid user with session context or HTTP Basic.")
return // Be sure to RETURN early because authentication failed!
}
// IMPORTANT: Execution reaches here only if a user succeeds with authentication.
// Insert main servlet code here before end of function, which ends servlet request
doMain(req, response, user )
}
// This method is called by our servlet AFTER successful authentication
private function doMain(req: HttpServletRequest, response: HttpServletResponse, user : User) {
assert(user != null)
Procedure
1. Register this servlet in servlets.xml.
2. Run the QuickStart server at the command prompt:
gwb runServer
http://localhost:8180/pc/service/test
http://localhost:8180/pc/service/test
REQUEST SUCCEEDED
req.RequestURI: '/pc/service/test'
req.PathInfo: '/test'
req.RequestURL: 'http://localhost:8180/pc/service/test'
authenticated user name: 'Super User'
Servlets 637
Guidewire PolicyCenter 9.0.6 Integration Guide
Connections to the database connection pool can be automatic or, to improve performance, reserved.
See also
• “<dbcp-connection-pool> database configuration element” in the System Administration Guide
executeTransactionsWithReservedConnection(Runnable runnable)
The runnable argument is a Runnable object that implements a run method that will use the single database
connection for its queries. The method has no return value.
The executeTransactionsWithReservedConnection method retrieves the database connection prior to executing
the argument's run method. It releases the connection when the run method has finished. The run method can
retrieve the reserved connection by calling the getActiveConnection method of the ConnectionHandlerFactory
class.
/* Reserve a database connection from the pool and run the block object */
executeTransactionsWithReservedConnection(block);
A web service can reserve and release a single database connection for its own use by specifying the
@WsiReduceDBConnections annotation.
See also
• For information about the web service @WsiReduceDBConnections annotation, see “Web service publishing
annotation reference” on page 48.
PolicyCenter provides several mechanisms to generate messages, forms, and letters in custom text-based formats
from PolicyCenter data. If an external system needs information from PolicyCenter about a policy, it can send
requests to the PolicyCenter server by using the HTTP protocol.
The major techniques to extract data from PolicyCenter using templates are described below.
• For user interaction, write a custom servlet that uses templates. Create a custom servlet. A servlet generates
HTML or other format pages for predefined URLs and you do not implement with PCF configuration. Your
servlet implementation can use Gosu templates to extra data from the PolicyCenter database.
• For programmatic access, write a custom web service that uses templates. Write a custom web service. Custom
web services let you address each integration point in your network. Follow the design principles described
below.
◦ Write a different web service API for each integration point, rather than writing a single, general purpose web
service API.
◦ Name the methods in your web service APIs appropriately for each integration point. For example, if a method
generates notification emails, name your method getNotificationEmailText.
◦ Design your web service APIs to use method arguments with types that are specific to each integration point.
◦ Use Gosu templates to implement data extraction. However, do not pass template data or anything with Gosu
code directly to PolicyCenter for execution. Instead, store template data only on the server and pass only
typesafe parameters to your web service APIs.
Application Server
Every data extraction request includes a parameter indicating which Gosu template to use to format the response.
You can add an unlimited number of templates to provide different responses for different types of root objects. For
example, given a policy as a root object for a template, you could design different templates to export policy data,
such as the following examples.
• A list of all notes on the policy
• A list of all open activities on the policy
• A summarized view of a policy
To provide programmatic access to PolicyCenter data, PolicyCenter uses Gosu, the basis of Guidewire Studio
business rules. Gosu templates allow you to embed Gosu code that generates dynamic text from evaluating the code.
Wrap your code with <% and %> characters for Gosu blocks and <%= and %> for Gosu expressions.
Once you know the root object, refer to properties on the root object or related objects just as you do as you write
rules in Studio.
Before writing a template, decide which data you want to pass to the template.
642 chapter 33: Data extraction integration
Guidewire PolicyCenter 9.0.6 Integration Guide
For example, from a policy, refer to the properties using Gosu expressions as follows.
• policy.Account – Account associated with this policy
• policy.Periods – List of policy periods associated with this policy
• policy.PolicyType – Policy type
The simplest Gosu expressions only extract data object properties, such as policy.PolicyNumber. For instance,
suppose you want to export the policy number, use the following short template.
At run time, Gosu runs the code in the template block “<%= ... %>” and evaluates it dynamically.
HTML results must be a well-formed HTML, ensuring that all properties contain no characters that might invalidate
the HTML specification, such as unescaped “<” or “&” characters. This is particularly relevant for especially user-
entered text such as descriptions and notes.
Systems that process XML often are very strict about syntax and well-formedness. Be careful not to generate text
that might invalidate the XML or confuse the recipient. For instance, beware of unescaped “<” or “&” characters in a
notes field. If possible, you could export data within an XML <CDATA> tag, which allows more types of characters
and character strings without problems of unescaped characters.
Logging in templates
Messages can be sent to a particular PolicyCenter log file by using the gw.api.system.PCLoggerCategory object.
Retrieve the desired Logger object by calling the object's forCategory method and specifying the relevant log
category. Text messages can be sent to the returned Logger object.
This $typecode API works only within Gosu templates, not Gosu in general.
In addition, you can use the TypecodeMapperUtil Gosu utility class.
Proxy servers
Guidewire recommends deploying proxy servers to insulate PolicyCenter from the external Internet. This is
recommended for any other outgoing requests to computers on the external Internet and to insulate PolicyCenter
from incoming requests from the Internet.
See also
• For configuring web services URLs to support proxy servers, see the Configuration Guide.
This section describes the high-level Apache installation and security instructions. A full detailed set of Apache
instructions is outside the scope of this Guidewire documentation.
Procedure
See also
See also
• “Upstream (reverse) proxy with encryption for user connections” on page 650
• For information about managing secure communications, see the System Administration Guide.
Listen $PROXY_PORT_NUMBER_HERE
The dollar sign ($) appears in configuration building blocks to indicate values that must be substituted with hard-
coded values. Replace all these values and leave no “$” characters in the final file.
Replace the line with the following configuration setting to listen on port 1234.
Listen 1234
#The reverse proxy listens to the source system on the reverse proxy port.
Listen $PROXY_PORT_NUMBER_HERE
<VirtualHost *:$PROXY_PORT_NUMBER_HERE>
<Proxy *>
Order Deny,Allow
Deny from all
# The Virtual Host accepts requests only from the source system
Allow from $SourceSystem
</Proxy>
</VirtualHost>
Replace the $SOURCE_URL value with the source URL. To redirect all HTTP traffic on all URLs on the source IP
address and port, use the string “/”, which is just the forward slash, with no quotes around it.
Replace the $DESTINATION_URL value with the destination domain name or URL.
648 chapter 34: Proxy servers
Guidewire PolicyCenter 9.0.6 Integration Guide
#The reverse proxy listens to the source system on the reverse proxy port.
Listen $PROXY_PORT_NUMBER_HERE
<VirtualHost *:$PROXY_PORT_NUMBER_HERE>
<Proxy *>
Order Deny,Allow
Deny from all
# The Virtual Host accepts requests only from the source system
Allow from $SourceSystem
</Proxy>
</VirtualHost>
#The reverse proxy listens to the source system on the reverse proxy port.
Listen $REVERSEPROXY_PORT_NUMBER_HERE
<VirtualHost *:$REVERSEPROXY_PORT_NUMBER_HERE>
<Proxy *>
Order Deny,Allow
Deny from all
# The Virtual Host accepts requests only from the source system
Allow from $SourceSystem
</Proxy>
ProxyPass / $DestinationURL
#The Virtual Host authenticates to the source system providing its certificate
SSLCertificateFile $ReverseProxyTrustedCertFile
</VirtualHost>
#Access is allowed to the pc directory and its subdirectories for the authorized sites only
<Directory /pc>
Order Deny,Allow
Allow from all
#The communication security is achieved using the PrivateKey, which is secured through
#a pass-phrase script.
SSLCertificateKeyFile conf/<certificate_filename>-secured.pem
#The Virtual Host associates the request to the internal Guidewire product instance
ProxyPass /<product>400 <url of the product server>
ProxyPassReverse /<product>400 <url of the product server>
</VirtualHost>
<!-- Define a non-SSL HTTP/1.1 Connector on port <port number> to receive decrypted
communication from Apache reverse proxy on port 11410 -->
<Connector acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true"
enableLookups="false"maxHttpHeaderSize="8192" maxSpareThreads="75" maxThreads="150"
minSpareThreads="25" port="portnumber" redirectPort="8443" scheme="https" proxyName="hostname"
proxyPort="portnumber">
</Connector>
port Specifies the port number for the additional connector for access through the proxy.
proxyName Identifies the deployment server’s name.
scheme Identifies the protocol used by the client to access the server.
This topic describes ways to write and deploy Java code in PolicyCenter, including accessing entity data. For
example, you can implement PolicyCenter plugin interfaces using a Java class instead of a Gosu class. If you
implement a plugin interface in Java, optionally you can write your plugin implementation as an OSGi bundle. The
OSGi framework is a Java module system and service platform that helps cleanly isolate code modules and any
necessary Java libraries. Guidewire recommends OSGi for all new Java plugin development.
See also
• Gosu Reference Guide
See also
• “Using reflection to access Gosu classes from Java” on page 659
Java and OSGi support 653
Guidewire PolicyCenter 9.0.6 Integration Guide
See also
• Gosu Reference Guide
Guidewire recommends using IntelliJ IDEA with OSGi Editor. The included plugin editor configures OSGi
configuration files such as the bundle manifest.
• Other Java IDEs, such as Eclipse – You can use other Java IDEs such as Eclipse or your own version of IntelliJ
IDEA. However, you must manually configure OSGi files and bundle manifest manually according to the OSGi
standard.
The following table summarizes options for development environments for plugin development in Java.
Procedure
1. Open your separate instance of IntelliJ IDEA.
2. Navigate to Settings→Plugins.
3. Click Install from disk.
4. Navigate to the following directory.
PolicyCenter/studio/configstudio/internal-api-idea-plugin/lib/
Procedure
1. In Windows, open a command prompt.
2. From the PolicyCenter installation directory, run the following command.
gwb genJavaApi
Result
The command generates Java entity interfaces and typelist classes in libraries in the following location.
PolicyCenter/java-api/lib
Note that the command does not regenerate the Java API Reference documentation.
PolicyCenter/javadoc/
address.setFirstName("John");
lastName = address.getLastName();
tested = someEntity.isFieldname();
policy.addEvent("MyCustomEventName");
However, neither Gosu enhancement properties nor Gosu enhancement methods are available directly on the Java
entity class. To access Gosu enhancements, you must use reflection APIs.
To get a specific typecode instance from the typelist, use the static properties on a typelist that represent a typecode.
The typecode static instances have the TC_ name prefix, just like from Gosu. You do not need to instantiate any
typecode object or call any special methods to access the instance from Java.
In the rare cases where you need to get a typecode reference from a String value known only at run time, use the
getTypeKey method on the typelist class.
tc = typekey.ExampleTypelist.getTypeKey(typeCodeString)
Because the getTypeKey method uses reflection to access data at run time, the Gosu editor cannot validate typecode
code values at compile time. For this reason, it is best if possible to avoid using reflection for accessing typekey
instances.
To compare typecode instances for equality, you can either use the equals method or use the == (double equals)
operator.
gw.pl.persistence.core.Bundle b = gw.transaction.Transaction.getCurrent();
If there is no current bundle, you must create a bundle before creating entity instances or updating entity instances
that you get from a database query.
import gw.pl.persistence.core.Bundle;
import gw.transaction.Transaction;
...
Bundle bundle = Transaction.newBundle();
Additionally, you can use the runWithNewBundle method, which is the same as in Gosu for this task. However, the
corresponding Gosu method takes a Gosu block as an argument. From Java, the syntax is slightly different, using an
anonymous class instead of a Gosu block.
gw.transaction.Transaction.runWithNewBundle(new Transaction.BlockRunnable() {
@Override
public void run(Bundle bundle) {
// Your code here...
// The bundle commits automatically if no exceptions occur before the end of the run method
}
});
import gw.pl.persistence.core.Bundle;
import entity.Address;
import gw.transaction.Transaction;
...
Bundle b = Transaction.getCurrent();
Address a = new Address(b);
See also
• Gosu Reference Guide
package test1
class MyGosuClass {
public static function myMethod(input : String) : String {
return "MyGosuClass returns the value ${input} as the result!"
}
}
The Java code calls the Gosu static method by using the ReflectUtil method invokeStaticMethod.
package test1;
import gw.lang.reflect.ReflectUtil;
import gw.transaction.Bundle;
}
}
If you write your own Gosu class and you want to call methods on it from Java, the following pattern increases the
degree of type safety.
1. Create a Java interface containing only the set of methods that you need to call from Java. For getting and
setting properties, define the interface using getter and setter methods, such as getMyField and setMyField.
2. Create a Gosu class that implements that interface. It can contain additional methods if desired if they are not
needed from Java.
3. In code that needs to get a reference to the object, use ReflectUtil to create an instance of the desired Gosu
class. There are several approaches.
• Create an instance using ReflectUtil.
• Alternatively, define a method on an object that creates an instance. Next, call that method with
ReflectUtil.
In both cases, at compile time any new object instances returned by ReflectUtil have the type Object. At
run time, downcast to your new Java interface and assign to a new variable of that interface type.
4. You now have an instance of an object that conforms to your interface. Call methods on it as you normally
would from Gosu. The getters, setters, and other method names are defined in your interface, so the method
calls are typesafe. For example, the Java compiler can protect against misspelled method names.
If the class name starts with com.guidewire, PolicyCenter delegate loads in general, but there are some
internal classes that locally load.
Java code that you deploy must never access any internal classes other than supported classes and documented
APIs. Using internal classes is dangerous and unsupported. If in doubt about whether a class is supported,
immediately ask Customer Support. Never use classes in the com.guidewire.* packages.
3. All your classes
Any remaining non-internal classes load locally.
Java classes that you deploy must not have a fully-qualified package name that starts with com.guidewire.
Additionally, never rely on classes with that prefix because they are internal and unsupported.
PolicyCenter/modules/configuration/plugins/PLUGIN_DIR/classes
The following example references a class file using the fully qualified name mycompany.MyClass.
PolicyCenter/modules/configuration/plugins/PLUGIN_DIR/classes/mycompany/MyClass.class
Place your JAR file libraries and any third-party libraries in the following locations.
PolicyCenter/modules/configuration/plugins/PLUGIN_DIR/lib
Procedure
1. Launch IntelliJ IDEA with OSGi Editor by running the following command at a command prompt.
gwb pluginStudio
package example.docs.java;
PROJECT\out\production\JavaFerriteTest1\example\docs\java\SimpleClass.class
PolicyCenter\modules\configuration\plugins\shared\basic\classes\example\docs\java\MyClass.class
print (methodResult)
gwb pluginStudio
If you use other Guidewire applications, such as Guidewire ContactManager, each Guidewire application includes
its own version of IntelliJ IDEA with OSGi Editor. Be sure to run this command prompt from the correct application
product directory.
Procedure
1. To create a new project, perform the following steps:
a. To create the first project in IntelliJ IDEA with OSGi Editor, click Create New Project. If IntelliJ starts with
an existing project, click File→ New Project.
b. In the list of module types, click Guidewire and then, in the main panel of the dialog box, click
OSGi Plugin Module.
c. Click Next.
d. In the Project name field, type the project name. In the Project location field, type the project location. Do not
yet click Finish.
2. To add or import an OSGi module to an existing empty project, perform the following steps:
a. In the Project Structure dialog, select Empty Project and set the Project name field.
b. Add a module in the Project Structure dialog by clicking the plus sign (+).
c. For a new module, choose New Module, and then select the module type OSGi Plugin Module. In the Module
name field, type the module name. Go to step 3.
d. To select an existing module to import, choose Import Module. Click Next repeatedly and confirm the
settings for the imported module. Click Finish. Click OK. You do not do the remaining steps in this
procedure.
3. Open the More Settings pane, if it is not already open. Set the name of the new module as appropriate. By
default, the Bundle Symbolic Name field matches the name of the module. The bundle symbolic name defines the
main part of the output JAR file name before the version number. You can optionally change the symbolic
name to a different value. You can also optionally change the version of the bundle in the Bundle Version field.
4. Click Finish. If IntelliJ started with an existing project, you must choose whether to replace that project in the
current window or open a new IntelliJ window.
5. If this is a new project, you must set the project JDK.
a. Click File→Project Structure→ Project Settings. In the Project section, set the Project SDK picker to your Java
JDK.
b. If there is no Java JDK listed, click the New. button. Click JDK, and then navigate to and select the Java
JDK that you want to use. Next, set the Project SDK picker to your newly created Java JDK configuration.
c. Click OK.
Java and OSGi support 663
Guidewire PolicyCenter 9.0.6 Integration Guide
Next steps
After creating a new project, to deploy an OSGi plugin, you perform the following tasks:
• “Create an OSGi-compliant class that implements a plugin interface” on page 664
• “Compile and install your OSGi plugin as an OSGi bundle” on page 666
• “Configuring third-party libraries in an OSGi plugin” on page 667
Procedure
1. Regenerate the Java libraries.
2. In IntelliJ IDEA with OSGi Editor, navigate under your OSGi module to the src directory.
3. Create new subpackages as necessary. Right-click src and choose New→Package.
The following steps show an example of a simple startable plugin in a mycompany package that contains the
new classes.
4. Right-click the package for your class.
5. Choose New→New OSGi plugin. IntelliJ IDEA with OSGi Editor opens a dialog.
6. In the Plugin class name field, enter the name of the Java class that you want to create.
For our example, type DemoStartablePlugin.
7. In the Plugin interface field, enter the fully qualified name of the plugin interface that you want to implement.
Alternatively, to choose from a list, click the ellipsis (...) button. Type some of the name or scroll to the
required plugin interface. Select the interface and then click OK.
8. IntelliJ IDEA with OSGi Editor displays a dialog Select Methods to Implement. By default, all methods are
selected. Click OK.
9. IntelliJ IDEA with OSGi Editor displays your new class with stub versions of all required methods.
10. If the top of the Java class editor has a yellow banner that says Project SDK is not defined, you must set your
project SDK to a JDK. If the SDK settings are uninitialized or incorrect, your project shows many compilation
errors in your new Java class.
11. If you have several tightly related OSGi plugin implementations, you can optionally deploy them in the same
OSGi bundle. If you have additional plugins to implement in this same project, repeat this procedure for each
plugin implementation class.
A messaging destination implements the MessageTransport interface. A single messaging destination
optionally also implements the MessageReply plugin interface. If these related plugin implementations have
shared code and third-party libraries, you could deploy them in the same OSGi bundle that encapsulates
messaging code for a messaging destination.
Example
See “Example startable plugin in Java using OSGi” on page 665.
Next steps
After creating a new project, to deploy an OSGi plugin, you perform the following tasks:
• “Compile and install your OSGi plugin as an OSGi bundle” on page 666
• “Configuring third-party libraries in an OSGi plugin” on page 667
664 chapter 35: Java and OSGi support
Guidewire PolicyCenter 9.0.6 Integration Guide
package mycompany;
import aQute.bnd.annotation.component.Activate;
import aQute.bnd.annotation.component.Component;
import aQute.bnd.annotation.component.ConfigurationPolicy;
import aQute.bnd.annotation.component.Deactivate;
import gw.api.startable.IStartablePlugin;
import gw.api.startable.StartablePluginCallbackHandler;
import gw.api.startable.StartablePluginState;
import java.util.Map;
@Activate
public void activate(Map<String, Object> config) {
printMessageToGuidewireConsole("activate -- OSGi plugin init");
// The Map contains the plugin parameters defined in the Plugins registry in Studio
// There are additional OSGi-specific parameters in this Map if you want them.
}
@Deactivate
public void deactivate() {
printMessageToGuidewireConsole("deactivate -- OSGi plugin shutdown");
}
@Override
public void start(StartablePluginCallbackHandler startablePluginCallbackHandler, boolean b)
throws Exception {
printMessageToGuidewireConsole("start");
}
@Override
public void stop(boolean b) {
printMessageToGuidewireConsole("stop");
}
@Override
public StartablePluginState getState() {
printMessageToGuidewireConsole("getState");
return _state;
}
}
PolicyCenter/modules/configuration/deploy/bundles
Procedure
1. Open a command prompt in the directory that contains your OSGi plugin module.
2. Type the following command.
ant install
The command generates messages about compiling source files, generating files, copying files, and building a
JAR file. If the command succeeds, the following output appears.
BUILD SUCCESSFUL
3. Switch to or open the regular PolicyCenter Studio application, not the IntelliJ IDEA with OSGi Editor.
Navigate in the Project pane to the path configuration→deploy→bundles. Confirm that you see the newly-
deployed file YOUR_JAR_NAME.jar. The JAR name is based on the module symbolic name followed by the
version.
If the JAR file is not present at that location, check the Ant console output for the directory path that the script
copied the JAR file. If you recently installed a new version of PolicyCenter at a different path, or moved your
Guidewire product directory, you must immediately update your OSGi settings in your OSGi project.
4. In PolicyCenter Studio, register your OSGi plugin implementation. Registering a plugin implementation
defines where to find a plugin implementation class and what interface the class implements.
a. In the Project window, navigate to configuration→config→Plugins→registry. Right-click the item registry, and
choose New→Plugin.
b. In the plugin dialog, enter the plugin name in the Name field. For this example, use
DemoStartablePlugin.
For plugin interfaces that support only one implementation, enter the interface name without the package.
For example: IStartablePlugin. The text that you enter becomes the basis for the file name that ends
in .gwp. The .gwp file represents one item in the Plugins registry.
If the plugin interface supports multiple implementations, like messaging plugins or startable plugins, this
name can be any arbitrary name. If you are registering a messaging plugin, the plugin name must match
the plugin name in fields in the separate Messaging editor in Studio.
For this demonstration implementation of the IStartablePlugin interface, enter the plugin name
DemoStartablePlugin.
c. In the plugin dialog, next to the Interface field, click the ellipsis (...), find the interface class, and select it.
If you want to type the name, enter the interface name without the package.
For this demonstration implementation of the IStartablePlugin interface, find or type the plugin name
IStartablePlugin.
d. Click OK.
666 chapter 35: Java and OSGi support
Guidewire PolicyCenter 9.0.6 Integration Guide
e. In the Plugins registry main pane for that .gwp file, click the plus sign (+) and select Add OSGi Plugin.
f. In the Service PID field, type the fully qualified Java class name for your OSGi implementation class. Note
that this name is different from the bundle name or the bundle symbolic name. The ellipsis (...) button
does not display a picker to find available OSGi classes, so you must type the class name in the field.
For this demonstration implementation of the IStartablePlugin interface, type the fully-qualified class
name mycompany.DemoStartablePlugin.
g. Set any other fields that your plugin implementation needs, such as plugin parameters.
h. Make whatever other changes you need to make in the PolicyCenter Studio application. For example, if
your plugin is a messaging plugin, configure a new messaging destination. You might need to make other
changes such as changes to your rule sets or other related Gosu code.
i. Start the server.
To run the server from Studio, if PolicyCenter Studio was already running when you installed or re-
installed the bundle, there is an extra required step before running the server. Open a command prompt in
the root application directory and run the following command.
gwb syncWebApp
Next, start the server from Studio, such as by clicking the Run or Debug menu items or buttons.
Alternatively, run the QuickStart server from the command prompt. Open a command prompt in the root
application directory and run the following command.
gwb runServer
Example
“Example startable plugin in Java using OSGi” on page 665 shows an example startable plugin. If you used that
example, closely read the console messages during server start-up. The example OSGi startable plugin prints
messages during server start-up. These messages prove that PolicyCenter successfully called your OSGi plugin
implementation.
Next steps
After creating a new project, to deploy an OSGi plugin, you perform the action described in the following topic:
• “Configuring third-party libraries in an OSGi plugin” on page 667
Procedure
1. Put any third-party OSGi JAR files in the lib (not inline-lib) folder inside your OSGi module in IntelliJ
IDEA with OSGi Editor.
2. Write code that uses the third-party JAR.
3. Confirm that there are no compilation errors.
4. Open a command prompt at the root of your module and run the following command.
ant install
The tool generates various messages, and concludes with the following output.
BUILD SUCCESSFUL
Result
The ant install script copies your bundle JAR files to the PolicyCenter/deploy/bundles directory.
Procedure
1. Put any third-party JAR files in the inline-lib folder inside your OSGi module in IntelliJ IDEA with OSGi
Editor.
2. Write code that uses the third-party JAR.
3. Confirm there are no compilation errors.
4. Open a command prompt at the root of your module and run the following command.
ant dist
The tool generates various messages, and concludes with the following output.
BUILD SUCCESSFUL
7. If you see unexpected imports, change the import package instruction in the bnd.bnd file, rather than
modifying the MANIFEST.MF file. Never directly change the file MANIFEST.MF. This manifest file is
automatically generated.
In the bnd.bnd file, set the Import-Package instruction to a comma-delimited list of Java packages to ignore
by including each with the exclamation point (!) prefix. The exclamation point means “not,” or, in this
context, it means “exclude.” At the end of the line, add an asterisk (*) character as the last item in the list to
import all other packages.
To ignore only the packages javax.inject and sun.misc, use the following line.
Import-Package=!javax.inject,!sun.misc,*
10. If there are errors, repeat this procedure and add more Java packages to the Import-Package line in bnd.bnd.
Procedure
1. Download guava-22.0.jar from the Guava project web site. Next, move the guava-22.0.jar file to the
inline-lib folder in your OSGi project in IntelliJ IDEA with OSGi Editor.
2. Write some Java code that uses this library.
import com.google.common.escape.Escaper;
...
s = escaper.escape(s);
3. From a command prompt, run the following command, to generate OSGi metadata.
ant dist
Various messages appear. If the generation succeeded, the final output is shown below.
BUILD SUCCESSFUL
Manifest-Version: 1.0
Service-Component: OSGI-INF/com.qa.MessageTransportOSGiImpl.xml
Private-Package: com.google.common.html,com.google.common.net,com.google.common.collect,
com.google.common.primitives,com.google.common.base,com.google.common.escape,com.qa,
com.google.common.base.internal,com.google.common.cache,com.google.common.eventbus,
com.google.common.util.concurrent,com.google.common.hash,com.google.common.io,
com.google.common.xml,com.google.common.reflect,com.google.common.math,
com.google.common.annotations
Bundle-Version: 1.0.0
Tool: Bnd-1.50.0
Bundle-Name: messaging-OSGi-plugins
Bnd-LastModified: 1382994235749
Created-By: 1.8.0_45 (Oracle Corporation)
Bundle-ManifestVersion: 2
Bundle-SymbolicName: messaging-OSGi-plugins
Import-Package: gw.pl.messaging.entity,gw.plugin.messaging,javax.annotation,javax.inject,sun.misc
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: gw.pl.messaging.entity,gw.plugin.messaging,javax.annotation,javax.inject,sun.misc
By default, the packages javax.inject and sun.misc are unavailable at run time. The package
javax.inject is a JavaEE package that is not exported by default. If you install the generated OSGi bundle in
its current form and start the server, the server generates the following error.
Import-Package=!javax.inject,!sun.misc,*
Manifest-Version: 1.0
Service-Component: OSGI-INF/com.qa.MessageTransportOSGiImpl.xml
Private-Package: com.google.common.html,com.google.common.net,com.google.common.collect,
com.google.common.primitives,com.google.common.base,com.google.common.escape,com.qa,
com.google.common.base.internal,com.google.common.cache,com.google.common.eventbus,
com.google.common.util.concurrent,com.google.common.hash,com.google.common.io,
com.google.common.xml,com.google.common.reflect,com.google.common.math,
com.google.common.annotations
Ignore-Package: javax.inject,sun.misc
Tool: Bnd-1.50.0
Bundle-Name: messaging-OSGi-plugins
Created-By: 1.8.0_45 (Oracle Corporation)
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-Version: 1.0.0
Bnd-LastModified: 1382995392983
Bundle-ManifestVersion: 2
Import-Package: gw.pl.messaging.entity,gw.plugin.messaging,javax.annotation
Bundle-SymbolicName: messaging-OSGi-plugins
You can edit these files directly in the file system if necessary without harming OSGi module settings. The only file
that IntelliJ IDEA with OSGi Editor modifies is build.properties, to edit the bundle symbolic name and version.
OSGi dependencies
The IntelliJ IDEA with OSGi Editor creates the following dependencies.
• PROJECT/MODULE/inline-lib directory – Directory for third-party Java libraries to embed in your OSGi bundle.
• PROJECT/MODULE/lib directory – Directory for third-party OSGi-compliant libraries to use but deploy into a
separate OSGi bundle.
• PolicyCenter/java-api/lib – The PolicyCenter Java API files that the regenJavaApi tool creates.
If you require any JAR files, put them in the lib or inline-lib directories as discussed earlier. You do not need to
modify any build scripts to add JAR files.
If you add dependencies in the IntelliJ project from other directories, change the associated build.xml (Ant build
script) to include those directories.
Bundle-SymbolicName=messaging-OSGi-plugins
Bundle-Version=1.0.0
-gw-dist-directory=C:/PolicyCenter/
Import-Package=*
DynamicImport-Package=
Export-Package=
Service-Component=*
Bundle-DocURL=
Bundle-License=
Bundle-Vendor=
Bundle-RequiredExecutionEnvironment=JavaSE-1.8
-consumer-policy=${range;[==,+)}
-include=build.properties
For the format of this file, refer to the following online third-party documentation.
http://bnd.bndtools.org/chapters/790-format.html
However, for the Bundle-SymbolicName and Bundle-Version properties, you must set or change those settings in
the build.properties file. Both the bnd.bnd and build.xml file use those properties from the build.properties
file.
You typically edit this file if you need to export some Java packages from your bundle, or you need to customize the
Import-Package header generation.
For advanced OSGi configuration, you can modify the build.xml build script.
Procedure
1. If you need to move your OSGi project on disk, quit IntelliJ IDEA with OSGi Editor and move the files on
disk.
2. Launch IntelliJ IDEA with OSGi Editor from your new Guidewire product location.
3. In IntelliJ IDEA with OSGi Editor, open your OSGi plugin project.
4. In IntelliJ IDEA with OSGi Editor, update the module dependency for your OSGi module.
a. Open the Project Structure window.
b. Click the Modules item in the left navigation.
c. In the list of modules to the right, under the name of your module, click OSGi Bundle Facet.
d. To the right of the Guidewire product directory text field, click the Change button.
e. Set the new disk path and click OK.
f. Click OK in the dialog. The tool updates IDE library dependencies and the build.properties file.
5. Test your new configuration.