๐Ÿ“… let's chat! explore the endless possibilities creating industries that don't exist. click here

guidewire-sdk-patterns

Master Guidewire SDK patterns including Digital SDK, REST API Client, and Gosu best practices. Use when implementing integrations, building frontends with Jutro, or writing server-side Gosu code. Trigger with phrases like "guidewire sdk", "digital sdk", "jutro sdk", "guidewire patterns", "gosu best practices", "rest api client". allowed-tools: Read, Write, Edit, Bash(npm:*), Bash(gradle:*), Grep version: 1.0.0 license: MIT author: Jeremy Longshore <jeremy@intentsolutions.io>

Allowed Tools

No tools specified

Provided by Plugin

guidewire-pack

Claude Code skill pack for Guidewire InsuranceSuite (24 skills)

saas packs v1.0.0
View Plugin

Installation

This skill is included in the guidewire-pack plugin:

/plugin install guidewire-pack@claude-code-plugins-plus

Click to copy

Instructions

# Guidewire SDK Patterns ## Overview Master the key SDK patterns for Guidewire development: Digital SDK for frontends, REST API Client for integrations, and Gosu patterns for server-side development. ## Prerequisites - Completed `guidewire-install-auth` and `guidewire-hello-world` - Understanding of TypeScript/JavaScript (for Digital SDK) - Familiarity with Gosu basics (for server-side patterns) ## Digital SDK (Frontend) ### Installation and Setup ```bash # Initialize Jutro project with Digital SDK npx @guidewire/jutro-cli@latest create my-portal --template agent-portal cd my-portal # Generate Digital SDK from your Cloud API npx jutro-cli generate-sdk \ --api-url https://your-tenant.cloud.guidewire.com/pc \ --output src/sdk ``` ### SDK Configuration ```typescript // src/sdk/config.ts import { createSdkConfig } from '@guidewire/digital-sdk'; export const sdkConfig = createSdkConfig({ baseUrl: process.env.REACT_APP_API_URL, auth: { type: 'oauth2', clientId: process.env.REACT_APP_CLIENT_ID, redirectUri: `${window.location.origin}/callback`, scope: 'pc.policies' }, headers: { 'Accept-Language': 'en-US' }, timeout: 30000 }); ``` ### Entity Operations ```typescript // Using Digital SDK for CRUD operations import { useAccount, useAccounts, createAccount } from '../sdk/account'; // Read single entity function AccountDetail({ accountId }: { accountId: string }) { const { data: account, loading, error } = useAccount(accountId, { include: ['accountHolder', 'primaryLocation'] }); if (loading) return ; if (error) return ; return (

{account.accountHolder.displayName}

Account #: {account.accountNumber}

Status: {account.accountStatus.name}

); } // List entities with filtering function AccountList() { const { data: accounts, loading, pagination } = useAccounts({ filter: { accountStatus: 'Active' }, pageSize: 25, sort: '-createdDate' }); return ( ); } // Create entity async function handleCreateAccount(formData: AccountFormData) { try { const newAccount = await createAccount({ accountHolder: { firstName: formData.firstName, lastName: formData.lastName, dateOfBirth: formData.dob }, primaryLocation: { addressLine1: formData.address, city: formData.city, state: { code: formData.state }, postalCode: formData.zip } }); console.log('Created account:', newAccount.accountNumber); return newAccount; } catch (error) { handleApiError(error); } } ``` ### Schema Validation ```typescript // Using SDK-generated schema validation import { accountSchema, validateAccount } from '../sdk/account'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; function AccountForm() { const { register, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(accountSchema) }); return (
{/* Additional fields */}
); } ``` ## REST API Client (Integration) ### Client Plugin Setup ```groovy // build.gradle - REST API Client plugin plugins { id 'com.guidewire.rest-api-client' version '3.0.0' } restApiClient { clients { externalRating { specFile = file('specs/rating-service.yaml') packageName = 'gw.integration.rating' generateSync = true faultTolerance { retryAttempts = 3 retryDelay = 1000 circuitBreakerThreshold = 5 } } } } ``` ### Generated Client Usage ```gosu // Using generated REST API client package gw.integration.rating uses gw.integration.rating.api.RatingApi uses gw.integration.rating.model.RatingRequest uses gw.integration.rating.model.RatingResponse uses gw.api.util.Logger class RatingService { private static final var LOG = Logger.forCategory("RatingService") private static final var _api = new RatingApi() static function getRating(policy : Policy) : RatingResponse { var request = new RatingRequest() request.PolicyNumber = policy.PolicyNumber request.EffectiveDate = policy.EffectiveDate request.CoverageType = policy.Product.Code request.State = policy.PrimaryLocation.State.Code try { var response = _api.calculateRating(request) LOG.info("Rating calculated: ${response.PremiumAmount}") return response } catch (e : FaultToleranceException) { LOG.error("Rating service unavailable", e) throw new RatingServiceException("Unable to calculate rating", e) } } } ``` ### Custom REST Client ```gosu // Custom REST client implementation package gw.integration.external uses gw.api.rest.RestClient uses gw.api.rest.RestClientBuilder uses gw.api.rest.Response uses gw.api.util.Logger class ExternalServiceClient { private static final var LOG = Logger.forCategory("ExternalServiceClient") private var _client : RestClient construct() { _client = RestClientBuilder.create() .withBaseUrl(ScriptParameters.ExternalServiceUrl) .withTimeout(30000) .withHeader("Authorization", "Bearer ${getToken()}") .withHeader("Content-Type", "application/json") .build() } function getResource(resourceId : String) : ExternalResource { var response = _client.get("/resources/${resourceId}") validateResponse(response) return parseResponse(response, ExternalResource) } function createResource(resource : ExternalResource) : ExternalResource { var response = _client.post("/resources", toJson(resource)) validateResponse(response) return parseResponse(response, ExternalResource) } private function validateResponse(response : Response) { if (response.StatusCode >= 400) { LOG.error("API error: ${response.StatusCode} - ${response.Body}") throw new ExternalServiceException( "External service error: ${response.StatusCode}" ) } } private function getToken() : String { // Token retrieval logic return ScriptParameters.ExternalServiceToken } } ``` ## Gosu Patterns (Server-Side) ### Entity Query Patterns ```gosu // Efficient querying with Query API package gw.custom.query uses gw.api.database.Query uses gw.api.database.Relop uses gw.api.path.Paths class PolicyQueryService { // Simple query static function findByPolicyNumber(policyNumber : String) : Policy { return Query.make(Policy) .compare(Policy#PolicyNumber, Equals, policyNumber) .select() .AtMostOneRow } // Query with joins static function findPoliciesByProducerCode(producerCode : String) : List { return Query.make(Policy) .join(Policy#ProducerCodeOfRecord) .compare(ProducerCode#Code, Equals, producerCode) .select() .toList() } // Complex query with subqueries static function findActiveHighValuePolicies(minPremium : java.math.BigDecimal) : List { var query = Query.make(Policy) query.compare(Policy#Status, Equals, PolicyStatus.TC_INFORCE) query.compare(Policy#TotalPremiumRPT, GreaterThanOrEquals, minPremium) query.compare(Policy#ExpirationDate, GreaterThan, Date.Today) // Add subquery for specific coverage var subquery = query.subselect(Policy#ID, CompareIn, PolicyPeriod#Policy) subquery.join(PolicyPeriod#PersonalAutoLine) .compare(PersonalAutoLine#PAVehicles, IsNotNull, null) return query.select() .orderBy(\p -> p.TotalPremiumRPT) .toList() } // Batch processing pattern static function processInBatches( query : Query, batchSize : int, processor(batch : List) ) { var iterator = query.select().iterator() var batch = new ArrayList() while (iterator.hasNext()) { batch.add(iterator.next()) if (batch.size() >= batchSize) { processor(batch) batch.clear() } } if (!batch.Empty) { processor(batch) } } } ``` ### Transaction Patterns ```gosu // Transaction management patterns package gw.custom.transaction uses gw.api.database.Transaction uses gw.transaction.Transaction as GWTransaction class TransactionService { // Basic transaction static function createAccountWithPolicy(accountData : AccountData) : Policy { return GWTransaction.runWithNewBundle(\bundle -> { var account = new Account(bundle) account.AccountNumber = accountData.AccountNumber var contact = new Person(bundle) contact.FirstName = accountData.FirstName contact.LastName = accountData.LastName account.AccountHolderContact = contact // Create submission var submission = new Submission(bundle) submission.Account = account submission.Product = accountData.Product return submission.Policy }) } // Transaction with savepoint static function complexOperation(policy : Policy) { GWTransaction.runWithNewBundle(\bundle -> { policy = bundle.add(policy) try { // Risky operation 1 updateCoverages(policy) // Risky operation 2 applyEndorsement(policy) } catch (e : Exception) { // Bundle will rollback automatically on exception throw e } }) } // Async transaction static function queueAsyncWork(policyId : Key) { gw.api.async.AsyncProcess.schedule( "ProcessPolicy", \-> processPolicy(policyId), Date.Now ) } } ``` ### Plugin Patterns ```gosu // Plugin implementation pattern package gw.plugin.rating uses gw.plugin.rating.IRatingPlugin uses gw.api.util.Logger class CustomRatingPlugin implements IRatingPlugin { private static final var LOG = Logger.forCategory("CustomRatingPlugin") override function calculatePremium(period : PolicyPeriod) : Money { LOG.info("Calculating premium for policy: ${period.PolicyNumber}") var basePremium = calculateBasePremium(period) var discounts = applyDiscounts(period, basePremium) var taxes = calculateTaxes(period, basePremium - discounts) return basePremium - discounts + taxes } private function calculateBasePremium(period : PolicyPeriod) : Money { // Base premium calculation logic return period.Lines .map(\line -> line.calculatePremium()) .sum() } private function applyDiscounts(period : PolicyPeriod, base : Money) : Money { var totalDiscount = Money.ZERO // Multi-policy discount if (period.Account.Policies.Count > 1) { totalDiscount += base * 0.10 } // Good driver discount if (hasGoodDriverDiscount(period)) { totalDiscount += base * 0.15 } return totalDiscount } } ``` ## Output - Configured Digital SDK with type-safe API calls - REST API Client with fault tolerance - Gosu patterns following Guidewire best practices ## Error Handling | Error | Cause | Solution | |-------|-------|----------| | SDK generation failed | Invalid API spec | Verify OpenAPI spec URL and access | | Type mismatch | Schema changed | Regenerate SDK | | Transaction timeout | Long-running operation | Optimize or use async | | Client timeout | Network issues | Increase timeout, add retry | ## Resources - [Digital SDK Documentation](https://docs.guidewire.com/jutro/documentation/10.12/working-with-cloud-apis/) - [REST API Client Guide](https://developer.guidewire.com/rest-api-client/) - [Gosu Language Reference](https://gosu-lang.github.io/) - [Query API Documentation](https://docs.guidewire.com/cloud/pc/202503/cloudapica/) ## Next Steps For core insurance workflows, see `guidewire-core-workflow-a` and `guidewire-core-workflow-b`.

Skill file: plugins/saas-packs/guidewire-pack/skills/guidewire-sdk-patterns/SKILL.md