Dynamic Types In Gosu (objects ala JavaScript)

In version 10+, Guidewire has added a new intrinsic datatype to Gosu which allows objects to be created and used very much like javascript. The functionality, while very nice, is not as complete as it is in javascript but may be in future releases.

This style is mostly used for integrations but can be very useful for dynamic style programming.

Problem

I need to ship a property bag from xCenter to a 3rd party, or receive a property bag from a 3rd party.

Solution

Dynamic and Expando

The datatype is Dynamic. The magic is Expando. When used together, you can do some really cool things.

Let’s say we get a property bag from a 3rd party and want to pass those properties to a function. With this new type, we can create an object on the fly and use it either directly or dynamically.

uses com.guidewire.pl.system.util.DateTimeUtil
uses com.guidewire.pl.system.util.DateTimeUtil.Difference
uses gw.lang.reflect.Expando

var dynamic : Dynamic = new Expando()

//We get a property bag from a 3rd party
var propertyBag = new HashMap<String, Object>()
propertyBag.put("FirstName", "Tom")
propertyBag.put("LastName", "Cruise")
propertyBag.put("NumberOfCars", 5)
propertyBag.put("Cost", 56674.12)

//we build an object on the fly
propertyBag.eachKeyAndValue(k, val -> {
  dynamic[k] = val
})

print("**** Start ****")
var key = "Cost"
//we can access it one of 3 ways
print("FirstName: ${dynamic["FirstName"]}")
print("LastName: ${dynamic.LastName}")
print("Cost: ${dynamic[key]}")

print("n**** Additional Dynamic ****")
//we can add functions
dynamic.print = -> print(dynamic)
dynamic.Age = birthday : String -> {
  var age : Difference = DateTimeUtil.getDifference(new Date(), new Date(birthday))
  return age.Days / 365

}
dynamic.Birthdate = "12/01/1975"
//and then call that function
print("Age: ${dynamic.Age(dynamic.Birthdate)}")
//just for fun - notice, this is the same as a HashMap
dynamic.put("Address", "123 Main St")
//but I can access it like a property
print("Address: ${dynamic.Address}")

//finally I can add an object
dynamic.Me = dynamic

print("n**** Looping dynamically ****")
//If I want to access the properties, I need to know them ahead of time (shortcoming)
var array = new ArrayList(){"Birthdate", "Age", "FirstName", "LastName", "NumberOfCars", "Cost",  "printMe"}
//in javascript, I can look over the properties without knowing the names

array.each(elt -> {
try {
  //this is where javascript has an advantage by allowing us to check for a function
  //We can however, parse the type looking for block
  var myType = typeof dynamic[elt]

  if (myType.toString().startsWith("block")) {

    //try and create a dynamic string to call
    var dyna = "dynamic.${elt}('${dynamic.Birthdate}')"

    print("I want to call this: n ${dyna}nBut don't have an Eval function")
    //let's print the guts of the function at least
    print("Function ${elt} = n******* n ${dynamic[elt]} n*******")

    //another issue is that function calls cannot be called with hashmap notation
    //dynamic[elt]() -- will die at runtime so we resort to Explicit
    print("Age: ${dynamic.Age(dynamic.Birthdate)}")
   } else {
    //If the property is not defined, you will get a null
    if (dynamic[elt] == null) {
      print("${elt} not supported")
    } else {
      print("${elt}: ${dynamic[elt]}")
    }
   }
  } catch (e : Exception) {
    print(e)
  }
})

Here is the output from scratchpad

**** Start ****
FirstName: Tom
LastName: Cruise
Cost: 56674.12

**** Additional Dynamic ****
Age: 45
Address: 123 Main St

**** Looping dynamically ****
Birthdate: 12/01/1975
I want to call this: dynamic.Age('12/01/1975')
But don't have an Eval function
Function Age = ******* birthday : java.lang.String -> { var age : com.guidewire.pl.system.util.DateTimeUtil.Difference = com.guidewire.pl.system.util.DateTimeUtil.getDifference( new java.util.Date(), new java.util.Date( birthday ) ) return age.Days/365 }

*******
Age: 45
FirstName: Tom
LastName: Cruise
NumberOfCars: 5
Cost: 56674.12
printMe not supported

When I first started playing with this, I thought… Ooh I do this in javascript and it works well and gives me lots of flexibility. But with limited support in Gosu, I have yet to find a practical use for it.

Maybe you can find it and if so, I would love to hear from you.

Troy Stauffer
Senior Software Architect

Explore CenterTest

CenterTest Generators

Automatically generate test framework assets directly from Guidewire source code. Your tests stay synchronized with your configuration.

Restart Points

Resume failed or suspended scenarios from clearly identified Restart Points to eliminate false failures and optimize test suite execution time.

Role & Session Management

Optimize execution through intelligent session management, and test realistic workflows where multiple users interact with the same transaction.

Time Travel

Automate date-sensitive workflows like renewals, delinquencies, and claims processing. Hassle-free testing of complete policy lifecycles.

Data-Driven Testing

One scenario, hundreds of test variations. Simplify maintenance and scale coverage through data – without duplicating test code.

Document Testing

Automatically validate document generation and verify document content for policy documents, invoices, or claims correspondence.

CenterTest Data Studio

Let analysts own the test data. Business and test analysts change CenterTest test data without development knowledge, on their own machine.

CenterTest Recorder

Record once. Everyone benefits. An analyst walks through the process once in PolicyCenter, BillingCenter or ClaimCenter, and the team gets a video, written steps, the clicks and the checks.

Frequently Asked Questions

Understanding CenterTest

Browse all questions

Ready to elevate your QA practice?

Guidewire test automation,

without the headaches.

that's easy to maintain.

in just two weeks.

future-proofed for cloud.

  • Guidewire test automation, that's easy to maintain.
  • Guidewire test automation, in just two weeks.
  • Guidewire test automation, future-proofed for cloud.
Get Started