> For the complete documentation index, see [llms.txt](https://developer.collibra.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.collibra.com/workflows/designing-workflows/processes/process-execution/upgrading-your-scripts-for-groovy-3-compatibility/adjusting-for-groovy-javabeans-specification-compatibility-changes.md).

# Adjusting for Groovy JavaBeans specification compatibility changes

Groovy 3 is more compliant with the JavaBeans specification for one edge case scenario involving any field having a name starting with an uppercase letter. This change has an impact on the handling of properties.

## Groovy properties

The definition of properties according to the [Groovy public documentation](https://docs.groovy-lang.org/latest/html/documentation/#properties) is:

A property is an externally visible feature of a class. Rather than just using a public field to represent such features (which provides a more limited abstraction and would restrict refactoring possibilities), the typical approach in Java is to follow the conventions outlined in the JavaBeans Specification, i.e. represent the property using a combination of a private backing field and getters/setters. Groovy follows these same conventions but provides a simpler way to define the property.

The code sample below will generate the following:

* A backing `private String name` field, a **getName** and a **setName** method.
* A backing `private int age` field, a **getAge** and a **setAge** method.

```groovy
class Person {
    String name                             
    int age                                 
}
```

By convention, Groovy also recognizes properties even if there is no backing field, provided there are getters or setters that follow the Java Beans specification.

```groovy
class PseudoProperties {
    //1. a pseudo property "name"
    void setName(String name) {}
    String getName() {}

    //2. a pseudo read-only property "age"
    int getAge() { 42 }

    //3. a pseudo write-only property "groovy"
    void setGroovy(boolean groovy) {  }
}
def p = new PseudoProperties()
p.name = 'Foo' // uses (1)                     
assert p.age == 42 // uses (2)                 
p.groovy = true // uses (3)
```

## Groovy 3 breaking change

In Groovy 3 the handling of properties that start with an uppercase letter has changed to be more compliant with the JavaBeans specification.

The way how properties are mapped to the accessor method has changed. In groovy 2 it was possible to access the field instead of the accessor methods in some scenarios as shown below:

<table data-header-hidden><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><p>Groovy 2</p><pre><code>class A {
  private String X = 'fieldX'
  private String Prop = 'fieldProp'
  String getProp() { 'Prop' }
  String getX() { 'X' }
}
new A().with {
  assert prop == 'Prop' // uses getProp() accessor
  assert Prop == 'fieldProp' // uses field directly
  assert x == 'X' // uses getX() accessor
  assert X == 'fieldX' // uses field direclty
}
</code></pre></td><td><p>Groovy 3</p><pre><code>class A {
  private String X = 'fieldX'
  private String Prop = 'fieldProp'
  String getProp() { 'Prop' }
  String getX() { 'X' }
}
new A().with {
  assert prop == 'Prop' // use getProp() accessor
  assert Prop == 'Prop' // use getProp() accessor
  assert x == 'X' // uses getX() accessor
  assert X == 'X' // uses getX() accessor
}
</code></pre></td></tr></tbody></table>

A similar situation occurs when you use static properties:

<table data-header-hidden><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><p>Groovy 2</p><pre><code>class A {
  private static String X = 'fieldX'
  private static String Prop = 'fieldProp'
  static String getProp() { 'Prop' }
  static String getX() { 'X' }
}
A.with {
  assert prop == 'Prop' // uses static getProp() accessor
  assert Prop == 'fieldProp' // uses field directly
  assert x == 'X' // uses static getX() accessor
  assert X == 'fieldX' // uses field directly
}
</code></pre></td><td><p>Groovy 3</p><pre><code>class A {
  private static String X = 'fieldX'
  private static String Prop = 'fieldProp'
  static String getProp() { 'Prop' }
  static String getX() { 'X' }
}
A.with {
  assert prop == 'Prop' // uses static getProp() accessor
  assert Prop == 'Prop' // uses static getProp() accessoor
  assert x == 'X' // uses static getX() accessor
  assert X == 'X' // uses static getX() accessor
}
</code></pre></td></tr></tbody></table>

{% hint style="info" %}
This breaking change doesn’t affect classes where accessor methods are not overwritten.
{% endhint %}

## Recommendation

To make existing workflow scripts compatible with Groovy 3, we recommend using lowercase property names, except in when the property name is all uppercase:

```groovy
class A {
  private String X = 'fieldX'
  private String XML = 'fieldXML'
  
  String getX() { 'X' }
  String getXML() { 'XML' }
}
new A().with {
  assert x == 'X' // instead of using uppercase X property 
  assert XML == 'XML' // in this case using XML property is the only way
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.collibra.com/workflows/designing-workflows/processes/process-execution/upgrading-your-scripts-for-groovy-3-compatibility/adjusting-for-groovy-javabeans-specification-compatibility-changes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
