Skip to main content

Rygen Help Center

Translators

A translator is a Groovy script that translates source documents into target documents.

After the translator translates a document, it saves the document in the proper collection based on the document type. In X1, the Documents section stores the collections of document types.

The Translators page is where you can view and add your translators.

  1. On the Translators page, view the list of translators.

Search for a translator
  1. On the Translators page, you can search for a specific endpoint using the default search fields.

    search_translators.png
  1. In the top right corner of the page, select New Translator.

    new_translator.png
  2. In the Create New Translator dialog box, enter the initial router information, and select Next.

    create_translator.png
  3. Continue entering the additional translator information and then selecting Next until you reach the final step.

  4. Select Create Translator. The Translator Details page displays as a draft version of the router.

  5. In the top right corner of the page, select Approve > Yes to approve the draft.

    If the Peer Review feature is enabled in General Settings, the processor must be approved by a peer with the Manager role or higher before it can be activated.

    The translator has the name you gave it and an ID that X1 automatically assigned to it, based on the name.

    The ID is lowercase and replaces spaces with dashes, and it's also permanent and can't be edited.

    Note

    If you want to delete the draft before approving it, select delete_icon_2.png.

See the "New Translator Field Descriptions" below for more information about the translator fields.

New Translator Field Descriptions

Field

Description

Name

Enter a relevant name for the translator.

Type

  • MESSAGE - Translates messages from one format to another. It accepts an input document and returns an output document.

  • ENRICHMENT - Enriches messages with additional data. It accepts an input document that can be modified and the external data used to enrich the document.

  • ERROR - Translates error messages into a format that can be understood by the external system. It accepts a document and an error message and it returns an output document to the external system.

Adapter

The name of the context that the translator runs in.

Adapters provide the runtime environment for components to execute in. They're siloed from each other so that components running in one adapter cannot access components running in another adapter.

Adapters provide the ability to scale contexts independently. This can be useful in high-volume scenarios, where one adapter can be scaled up to handle more load while another can be scaled down to save resources. It also allows one adapter to fail without affecting the other adapters. This type of isolation isn't necessary unless there are specific performance or isolation requirements. In most cases, a single adapter is sufficient to handle high volumes of messages.

If multiple adapters are available, you must select the adapter in which each component you create runs. If only a single adapter is available, each component is automatically assigned to that adapter and cannot be changed.

Source Type

The document that the translator expects to receive.

Target Type

The document the translator expects to produce.

Note

After you create the translator, its details page displays where you can add additional information about the translator.

If the Peer Review feature is enabled in General Settings, the translator must be approved by a peer with the Manager role or higher before it can be activated.

See the procedures below for more information about creating each type of translator.

Refer to the table below for guidance after you've completed the initial steps in the Create a translator procedure above.

Field and tab

Description

Name

The name you entered when you created the message translator.

Type

The type you assigned to the translator when you created it.

Source Type

The source type you assigned to the translator when you created it.

Target Type

The target type you assigned to the translator when you created it.

Visual Mapper tab

The visual mapper enables you to create translator scripts by visually mapping a source to a target. You can upload any JSON or XML example document or schema, and the visual mapper generates a visual representation of the data structure.

You can then drag and drop elements to create mappings between the source and target structures. You can also add mapping rules for transformations and conversions in natural language. After you complete the mappings, you can sync the mapping to the translator script, automatically generating the script based on the visual representation.

Note

It is important to note that the Visual Mapper is not intended to replace the need for understanding the underlying data structures and the logic behind the mappings. You must still have a basic understanding of the source and target data formats to create effective mappings. You must also be aware that the translator script generated from the visual mapper may require further refinement and testing to ensure it meets your specific needs.

To create a visual mapper mapping

  1. Select the Visual Mapper tab. The Visual Mapper interface displays.

  2. Create the source schema.

  3. Create the target schema.

  4. Create mappings between the source and target schemas.

  5. Sync the mappings to the translator script.

To create a source or target schema in the visual mapper, select the Upload Source or Upload Target button and browse for the desired JSON or XML file. The visual mapper parses the file and displays the structure in a tree format.

  • Schemas consist of nodes that represent the document's properties, with names, data types, and descriptions.

  • The data types include string, number, boolean, array, and object and are visible beside the property's name in the schema view in abbreviated format (e.g., S, N, B, A, O). Note that you must be in draft mode in order to create schemas, and remember to save your work frequently.

Note

You must be in draft mode to create schemas, so remember to save your work frequently.

  • Sync From Script - Generally, the visual mapper is used to create mappings but can also be used to sync from an existing translator script. This is useful if the visual mapper is used to create the initial script, but the script is changed from then on, getting out of sync with the mapping.

    To sync the script with the mapping, select Sync from Script. The visual mapper analyzes the existing script and visually represents the mappings. You can then edit the mappings as needed and sync back to the script.

    Note

    • You must be in draft mode.

    • There must be a source and target schema.

    • Any existing mappings will be overwritten.

    • When you generate mappings for a complex script, the generated mappings may not be perfect and may require further refinement.

  • Sync To Script - Select Sync to Script to generate a translator script from the visual mapping. The visual mapper automatically generates the script based on the mappings created in the visual representation and displays the generated script.

    Note

    • You must be in draft mode to sync to the script.

    • Remember to save the generated script after syncing.

    • Approve the translator draft so that your changes can be published. This overwrites any existing script, so keep that in mind before syncing and saving.

Document Translation tab

Contains on-screen instructions and the Code Editor Guide to assist you in creating a Groovy script to translate the source document to the target document.

Add your Groovy script in the text space provided.

Header Translation tab

Contains on-screen instructions and the Code Editor Guide to assist you in creating a Groovy script to map and translate between the message headers and the envelope.

Add your Groovy script in the text space provided.

Test Document tab

Create a test document to be translated and evaluated against the test script during testing.

Note

After you enter or upload the test document, you can test it by selecting Test in the top right corner of the page.

The Test Result dialog box displays to inform you if the test passed or failed. If the tests pass, select View Output to view the translated document.

Test Headers tab

Test your Camel message headers.

Type Maps tab

  1. Select Add Type Maps. The Add Type Maps dialog box displays.

  2. Select one or more type maps from the drop-down list, and select Add.

Options tab

Log Message Headers

You can log the message headers of the message for any events that the translator logs.

If yes, you can enter an optional "Include Headers" regular expression to specify which headers to include in the flow run event. All headers are logged if you don't provide the regular expression.

Note

Logging message headers can be helpful in troubleshooting, but be aware that this can expose sensitive information in the flow run events.

Flows tab

Displays all the integrations and integration flows that use this translator.

Double-select a flow to view its details.

Refer to the table below for guidance after you've completed the initial steps in the Create a translator procedure above.

Field and tab

Description

Name

The name you assigned to the translator when you created it.

Type

The type you assigned to the translator when you created it.

Source Type

The source type you assigned to the translator when you created it.

Target Type

The target type you assigned to the translator when you created it.

Document Enrichment tab

Contains on-screen instructions and the Code Editor Guide to assist you in creating a Groovy script to enrich the source document with external data.

Add your Groovy script in the text space provided.

Test Document tab

Create a test document to be translated and evaluated against the test script during testing.

Note

After you enter or upload the test document, you can test it by selecting Test in the top right corner of the page.

The Test Result dialog box displays to inform you if the test passed or failed. If the tests pass, select View Output to view the translated document.

Test Data tab

Contains the Code Editor Guide to assist you in creating a JSON document to use as the external data when testing.

Add your JSON document in the text space provided.

Test Headers tab

Enter test headers.

Type Maps tab

  1. Select Add Type Maps. The Add Type Maps dialog box displays.

  2. Select one or more type maps from the drop-down list, and select Add.

Options tab

Log Message Headers

You can log the message headers of the message for any events that the translator logs.

If yes, you can enter an optional "Include Headers" regular expression to specify which headers to include in the flow run event. All headers are logged if you don't provide the regular expression.

Note

Logging message headers can be helpful in troubleshooting, but be aware that this can expose sensitive information in the flow run events.

Flows tab

Displays all the integrations and integration flows that use this translator.

Double-select a flow to view its details.

Error translators enable you to translate error messages from one format to another. You can use them as custom error handlers in any component that supports error handling.

Like message translators, error translators accept the document of the envelope being processed (the message payload) and the message headers. The output from the translator is the result of the translation script.

Error information is stored in message headers before passing the headers to the error translator. The headers include the following:

  • Error - The error message that occurred.

  • Original Document - The document that was being processed when the error occurred.

Error Translator Document - The document sent to the error translator is either the document being processed at the time of the error, or (in the case of an HTTP error) the error response body. If the error response body is set as the document, then the original document is stored in the message headers as `original_document`.

Error Translator Output - The output from an error translator is the result of the translation script. The document is returned and flow execution stops. If the flow was initiated as part of a request/response flow, such as an HTTP request, the translated document is returned as the response to the request.

Refer to the table below for guidance after you've completed the initial steps in the Create a translator procedure above.

Field and tab

Description

Name

The name you assigned to the translator when you created it.

Type

The type you assigned to the translator when you created it.

Source Type

The source type you assigned to the translator when you created it.

Target Type

The target type you assigned to the translator when you created it.

Document Translation tab

Contains on-screen instructions and the Code Editor Guide to assist you in creating a Groovy script to translate the source document to the target document.

Add your Groovy script in the text space provided.

Header Translation tab

Contains on-screen instructions and the Code Editor Guide to assist you in creating a Groovy script to map and translate between the message headers and the envelope.

Add your Groovy script in the text space provided.

Test Document tab

Create a test document to be translated and evaluated against the test script during testing.

Note

After you enter or upload the test document, you can test it by selecting Test in the top right corner of the page.

The Test Result dialog box displays to inform you if the test passed or failed. If the tests pass, select View Output to view the translated document.

Test Headers tab

Enter test headers.

Type Maps tab

Add a type map to a translator

  1. Select Add Type Maps. The Add Type Maps dialog box displays.

  2. Select one or more type maps from the drop-down list, and select Add.

Delete a type map in a translator

  1. Next to the Type Key column for a type map, select delete_icon.png. The Confirm Type Map Removal dialog box displays.

  2. Select Yes.

Options tab

Log Message Headers

You can log the message headers of the message for any events that the translator logs.

If yes, you can enter an optional "Include Headers" regular expression to specify which headers to include in the flow run event. All headers are logged if you don't provide the regular expression.

Note

Logging message headers can be helpful in troubleshooting, but be aware that this can expose sensitive information in the flow run events.

Flows tab

Displays all the integrations and integration flows that use this translator.

Double-select a flow to view its details.

  1. In the top right corner of the page, select Import Translator. The Import Translator dialog box displays.

  2. Drag and drop a document, or select Choose and browse to it.

  3. Select Upload. The imported translator information is added to the Translators table.

  1. Edit the translator information.

  2. In the top right corner of the page, select Save > Approve.

  1. Next to a translator, select export_icon2.png. The Confirm Export dialog box displays.

  2. Select either Export with Type Maps or Export without Type Maps.

  1. In the top right corner of the page, select Restart. The Confirm Restart dialog box displays.

  2. Select Yes.

  1. Next to a translator, select delete_icon.png. The Delete Translator dialog box displays.

  2. Select Delete.

This guide provides basic Groovy scripting techniques that you can use with message translators.

Note

To add a script to a translator, the translator must be in edit mode. See Edit a translator.

The X1 script editor provides syntax highlighting, static autocompletion, and error checking to help you write your script.

Static autocompletion is activated when you type something that matches predefined suggestions.

The autocompletion feature is enhanced with the following context-sensitive behavior:

  • Document suggestions - When the word preceding the cursor is _document_, the editor suggests options only related to the source document.

  • Source document suggestions - If a property starts with the word _source_, the editor suggests only source document options.

  • Target document suggestions - If a property starts with the word _target_, the editor suggests only target document options.

  • General suggestions - For all other cases, the editor provides a comprehensive list of available suggestions.

Groovy map syntax

It's a best practice to use maps for document messages in X1.

In Groovy, a map is defined using the following syntax:

def document = [
  id: '1',
  name: 'foobar',
  items: [
    [id: '1', name: 'item1'],
    [id: '2', name: 'item2']
  ]
]

In this example, a document is defined as a map with an id, name, and items key. The items key is a list of maps, each with an id and name key.

To access a value in a map, use the following syntax:

def id = document.id

To assign a value to a key in a map, use the following syntax:

document.age = 30

Script input

To quickly review, message translator scripts translate a source document into a target document.

The source document passed to the translator can be of any type, but 99% of the time in X1 it'll be a map. The header of the envelope that enclosed the document as well as the Camel message headers are variables available for the script context.

  • document - The document message that's being processed. The document can be any object, but typically it is a map. This is the variable holding the document to be translated.

  • header - The header of the envelope that contains the document. The header can be any object, but typically it is a map. It's read-only in the document translation script and can be null or empty.

  • messageHeaders - The Camel message headers that are available to the script. These headers are set on the message when it's received by X1 and change as the message is processed. Document translation scripts can read from and write to the messageHeaders.

Script output

Groovy translator scripts must output a new document. In Groovy, this can be achieved with a return statement placed at the end of the script.

// script code

return [
	shipmentId: document.id,
	number: document.poNumber
]

Summary

  • Document translation scripts are expected to return a map of the translated data.

  • The output type is expected to represent the document type specified in the output type of the translator.

Validate document messages

You can validate document messages directly within translators using either of the following methods:

  • Assertions - You can use the Groovy 'assert' statement or the Assert class provided by Spring, which is available in X1 translator scripts.

  • Exceptions - Throw an exception if the message doesn't meet the expected criteria.

Both of these methods cause the message to fail validation and get routed to the default error handling processor, which results in a failed flow run and an email alert message (if email alerts are enabled).

Another method is to use the `validate` or `validationFailed` utilities provided by X1. You can use these methods to perform validation in your script and specify error messages, similar to the other validation methods, but without generating an error alert email. This is useful if you want to perform validation but don't want to trigger an email alert for every validation failure. The `validate` method can also cause the Flow Run to result in a Dead Letter when validation fails.

  • To use the `validate` method to create an error when validation fails in a translator script: Pass in a boolean expression or closure that evaluates to true if the document is valid and false if not, along with an error message to use if invalid. If the expression is evaluated as false, an exception will be thrown with the specified error message from the method.

    ```groovy
    validate(document.value > 0, "Value must be greater than 0")
    ```
  • To use the `validate` method to create a Dead Letter when validation fails in a translator script: Pass in a boolean expression or closure that evaluates to true if the document is valid and false if not, an error message to use if invalid, and a boolean that specifies if the validation should result in a Dead Letter. If the expression evaluates to false but the third argument is true, a Dead Letter is created with the specified error message from the method.

    ```groovy
    validate(document.value > 0, "Value must be greater than 0", true)
    ```
  • To use the 'validationFailed' method:

    ```groovy
    if (document.value <= 0) {
        validationFailed("Value must be greater than 0")
    }
    ```

Envelope headers are available for the document translation scripts of translators in the `header` variable.

To test a translator script that uses envelope headers, you can create a test document that's a JSON representation of an X1 envelope that consists of `header` and `document` properties, such as the following example:

```json
{
    "header": {
        "header1": "value1",
        "header2": "value2"
    },
    "document": {
        "field1": "value1",
        "field2": "value2"
    }
}
```

In Groovy, you can declare top-level variables that can be accessed from anywhere in the script. These variables are also known as script-level variables or global variables. Top-level variables are useful when you need to share data across different parts of the script or when you want to create convenience variables that simplify the code.

To declare a top-level variable in a Groovy script, assign a value to a variable without using the def keyword:

shipment = document

In this example, shipment is a top-level variable that refers to document. Now, you can use shipment anywhere in the script to refer to document.

Note

Top-level variables in Groovy scripts are dynamic and don't have a static type. This means that you can assign values of any type to them, and their type can change during the execution of the script.

While this dynamic nature provides flexibility, it also means you should be careful when using top-level variables. It's a good practice to use descriptive names for top-level variables and to keep their scope as limited as possible to avoid potential issues with variable name clashes or unexpected type changes.

Groovy provides powerful mechanisms for declaring methods (also called operations or functions) that can be used to encapsulate logic for transforming data. These methods can be called multiple times throughout your script, helping you avoid code repetition and keep your scripts clean and readable.

To declare a method in Groovy, use the def keyword followed by the method name, parentheses for parameters, and then the method body enclosed in curly braces.

Here's an example:

def transformData(data) {
    // Transformation logic goes here
    return transformedData
}

In this example, transformData is a method that takes one parameter, data, and returns transformedData.

These methods are dynamic, meaning they are not bound to a specific type, and can therefore handle data of any type and return any type of result. This dynamic nature allows for great flexibility but also requires that you manage the types of data passed to and returned from these methods.

It's important to note that all method declarations should be placed before the final return statement of the script. This is because Groovy scripts are executed sequentially from top to bottom. If a method is declared after it's called or after the return statement, Groovy won't be able to find the method at runtime, leading to a MissingMethodException.

Here's an example of a script structure with methods:

shipment = document

def transform(shipmentLines) {
    // Transformation logic
    return transformedShipment
}
// Other script code

return transform(shipment.lines)

In this example, the transformData and processData methods are declared at the top of the script, and the actual script logic is below these declarations, ensuring that the methods are defined before they are called.

Introduction to GStrings

A GString, or Groovy String, is an advanced form of a string that can contain expressions that are evaluated and interpolated (embedded) into the string. This feature allows you to construct dynamic strings in a very readable manner.

def name = 'Alice'
def greeting = "Hello, ${name}!" // 'Hello, Alice!'

In this example, ${name} is an expression within the GString. When the GString is evaluated, ${name} is replaced with the value of the name variable.

GStrings can be particularly useful when working with maps. You can embed map values in a GString:

def shipment = [
    id: 12345, 
    sender: 'John Doe', 
    receiver: 'Jane Smith', 
    status: 'In Transit'
]

def message = "Shipment ${shipment.id} is ${shipment.status}"

In this example, the message GString includes the id and status values from the shipment map.

If you need to include a literal ${ in a GString, you can escape it with a backslash:

def amount = 100
def message = "You won \$${amount}"  // 'You won $100'

In this example, the first dollar sign is escaped and therefore is treated as a literal character, not the start of an expression.

GStrings can also be multiline, which can be very useful when you need to construct complex strings:

def shipment = [
    id: 12345, 
    sender: 'John Doe', 
    receiver: 'Jane Smith', 
    status: 'In Transit'
]

def message = """Shipment Details:
ID: ${shipment.id}
Sender: ${shipment.sender}
Receiver: ${shipment.receiver}
Status: ${shipment.status}"""

In this example, the message GString spans multiple lines and includes several values from the shipment map. Each ${} expression is replaced with the corresponding map value when the GString is evaluated.

X1 documents (individual message payloads processed during flow run execution) are maps of data. Translator scripts operate on these maps of data (the document variable) and are expected to output a new map (the translated document).

Declare a map literal

A map literal in Groovy allows storing key-value pairs, providing fast and direct retrieval of values based on unique keys. Declaring a map literal is straightforward, and for better readability, the map can be spread over multiple lines.

Here's an example:

def shipment = [
    id: 12345, 
    sender: 'John Doe', 
    receiver: 'Jane Smith', 
    status: 'In Transit'
]

Access map keys using dot notation

Groovy allows retrieving values in a map by using dot notation. This approach provides a clear and direct way to access a value associated with a key.

Here's how you can do it:

def sender = shipment.sender 

Set map values using dot notation

To update or set a value for a key in a map, you can use dot notation.

Here's how you can change a shipment status:

shipment.status = 'Delivered'

Alternative notations for accessing and setting map values using brackets

Groovy provides alternative ways to access and set map values using brackets, which can be handy for dynamic keys or keys containing special characters.

Here's how you can do it:

def receiver = shipment['receiver-code']
shipment['status-code'] = 'Collected'

Merge two maps using << notation

In Groovy, the << operator allows merging two maps. The operator adds all key-value pairs from the second map to the first one. If there are duplicate keys, the values from the second map will overwrite those in the first map.

Here's an example:

def shipment1 = [
    id: 12345, 
    sender: 'John Doe', 
    receiver: 'Jane Smith', 
    status: 'In Transit'
]

def shipment2 = [
    id: 67890, 
    sender: 'Alice Johnson', 
    receiver: 'Bob Brown', 
    status: 'Delivered'
]

shipment1 << shipment2

In the above example, shipment1 will now have the key-value pairs of shipment2.

Safely access map keys that may be null

In Groovy, accessing a key that does not exist in a map will return a null value. However, attempting to call a method or access a property on null will result in a NullPointerException. To prevent this, Groovy provides the safe navigation operator (?.), which returns null instead of throwing an exception when a null value is encountered.

def status = shipment?.status // Returns 'In Transit' if status exists, null otherwise

In the above code, if the shipment map does not have a status key, status will be assigned null instead of causing a NullPointerException. This can be particularly useful when chaining method calls or property access on the result of map key access.

For example, if you want to transform the status value to uppercase, you might be tempted to do something like this:

def status = shipment.status.toUpperCase() // Throws NullPointerException if status does not exist

However, if the status key does not exist in the shipment map, you'll get a NullPointerException.

You can avoid this by using the safe navigation operator:

def status = shipment?.status?.toUpperCase() // Returns null if status does not exist

This code safely calls toUpperCase on shipment.status only if shipment.status is not null. Otherwise, it returns null. This helps in preventing NullPointerException from being thrown in your Groovy scripts and makes them more robust.

Set default values in case of null using the Elvis operator

In Groovy, the Elvis operator (?:) is a handy feature that enables you to specify a default value when the expression on its left-hand side is evaluated to be false or null. This operator is particularly useful when working with map values that may be null, as it allows you to provide a default value.

def status = shipment?.status ?: 'Unknown' 

In the above code, if the status key doesn't exist or its value is null in the shipment map, status will be assigned the string 'Unknown'. If the status key exists and its value is not null, status will be assigned that value.

Here's an example of how you could use it to set default values when transforming map values:

def status = (shipment?.status ?: 'Unknown').toUpperCase()

In this case, if the status key doesn't exist or its value is null in the shipment map, 'Unknown' will be used as the default value, and toUpperCase() will be called on 'Unknown'. If the status key exists and its value is not null, toUpperCase() will be called on the actual status value.

The Elvis operator can help in writing more robust Groovy scripts that can handle null and missing values gracefully.

Declare a list

Declaring a list in Groovy is straightforward.

Here's an example of how to declare a list named lineItems:

def lineItems = ['item1', 'item2', 'item3']

Access list elements

You can access elements in a Groovy list using their index, which starts from zero.

Here's how you can retrieve the first item from lineItems:

def firstItem = lineItems[0]

Set list elements

To update the value of a list element using its index, you can do:

lineItems[0] = 'newItem1'

After this operation, the first element of lineItems will be 'newItem1'.

Add elements to a list

You can add elements to a list using the << operator or the add method:

lineItems << 'item4'
lineItems.add('item5')

Remove elements from a list

To remove an element from a list, you can use the remove method with the element's value or index as the parameter:

lineItems.remove('item4') 
lineItems.remove(0) 

Check list size

To get the number of elements in a list, you can use the size method:

int size = lineItems.size()

Iterate over a list

You can iterate over a list using the each method:

lineItems.each { item ->
    println item
}

Find elements in a list

You can find elements in a list that meet certain conditions using the find method:

def firstItemOverFiveChars = myList.find { it.length() > 5 }

A common use-case in Groovy (and many other languages) is to create a list of maps. This structure is particularly useful for storing complex data, like a list of objects where each object has several properties.

Here's an example where we create a list called shipments, where each shipment is a map with id, sender, receiver, and status keys:

def shipments = [
    [
        id: 12345, 
        sender: 'John Doe', 
        receiver: 'Jane Smith', 
        status: 'In Transit'
    ],
    [
        id: 67890, 
        sender: 'Alice Johnson', 
        receiver: 'Bob Brown', 
        status: 'Delivered'
    ]
]

Access maps in the list

You can access individual shipments in the list using their index:

def firstShipment = shipments[0]  // firstShipment will be the first map in the list

Modify maps in the list

You can modify the properties of individual shipments in the list:

shipments[0].status = 'Delivered'  // The status of the first shipment is now 'Delivered'

Iterate over the list of maps

You can iterate over the list of maps using the each method:

shipments.each { shipment ->
    println "Shipment ID: ${shipment.id}, Status: ${shipment.status}"
}

In this code, each shipment is a map, and you can access its properties using dot notation. This will print the id and status of each shipment in the list.

Collect list elements into a new list of maps

Groovy's collect method is a powerful feature that allows you to transform each element in a list and returns a new list with the transformed elements. This is particularly useful when you want to create a new list of maps based on an existing list.

For example, suppose we have a list of shipments and we want to create a new list containing only the id and status of each shipment.

Here's how you can do it:

def simpleShipments = shipments.collect { shipment ->
    [id: shipment.id, status: shipment.status]
}

In this example, simpleShipments will be a new list of maps. Each map in the list will contain only the id and status of the corresponding shipment in the original shipments list.

The collect method is useful for situations where you want to transform a list of complex objects (like maps or custom classes) into a simpler format for processing or displaying.

Introduction to closures

A closure in Groovy is an open, anonymous, block of code that can take arguments, return a value and be assigned to a variable. A closure may reference variables declared in its surrounding scope. In essence, it’s like a “code block” or a method pointer. It’s defined within curly braces {}.

Use closures with collect

collect is a method that transforms each element in a collection based on the logic defined in a closure and returns a new collection with the transformed elements.

def shipmentLines = [
    ['id': '001', 'quantity': 10, 'price': 5.0],
    ['id': '002', 'quantity': 15, 'price': 3.5],
    ['id': '003', 'quantity': 8, 'price': 7.0]
]

def totalPrices = shipmentLines.collect { line -> line.quantity * line.price }

In this example, the closure { line -> line.quantity * line.price } is applied to each element in the shipmentLines list. The result is a new list where each line is replaced with the total price for that line.

Use closures with each

The each method applies a closure to each item in a collection. This is useful for performing an operation on each item.

def shipmentLines = ['item1', 'item2', 'item3']
shipmentLines.each { line -> println(line) }

In this example, the closure { line -> println(line) } is applied to each element in the shipmentLines list. Each line is printed to the console.

Use closures with find

The find method applies a closure to the items in a collection and returns the first item for which the closure returns true.

def shipmentLines = [
    ['id': '001', 'quantity': 10, 'price': 5.0],
    ['id': '002', 'quantity': 15, 'price': 3.5],
    ['id': '003', 'quantity': 8, 'price': 7.0]
]

def firstExpensiveLine = shipmentLines.find { line -> line.price > 6.0 }

In this example, the closure { line -> line.price > 6.0 } is applied to each element in the shipmentLines list. The find method returns the first line where the price is greater than 6.0.

In Groovy, certain values are considered "falsy" or represent "untruth", while all other values are considered "truthy". This is commonly referred to as Groovy Truth. It's a core concept in Groovy and is widely used in conditional statements, looping, and so on.

The following values are considered "falsy" in Groovy:

  • false (the boolean value)

  • null

  • Empty collections and maps ([], {})

  • Empty strings and arrays ("", '', [])

  • Zero (0, 0.0)

  • The special value NaN (Not-a-Number)

Everything else is considered "truthy".

This feature allows you to write clear and concise code when checking for null or empty values.

For example, to check if a shipment has line items, you can write:

if (shipment.lineItems) {
    // Process the line items
}

In this example, if shipment.lineItems is null, an empty collection, or any other "falsy" value, the code inside the if block won't be executed. On the other hand, if shipment.lineItems contains at least one item, the code inside the if block will be executed.

This reduces the need for more verbose null or emptiness checks, such as if (shipment.lineItems != null && !shipment.lineItems.isEmpty()). With Groovy Truth, your code becomes more readable and maintainable.

X1 endpoints can be configured to send and receive XML messages. These endpoints automatically convert the document message to XML.

When writing a translator script that produces a document message that'll be converted to XML, create the schema that the XML document should conform to. The X1 endpoint will automatically convert the document to XML using the schema.

Scripting XML attributes

To create an XML attribute, use the @ symbol in the key of the map.

For example:

def document = [
  person: [
    id: '1',
    name: 'foobar',
    '@age': 30
  ]
]

This produces the following XML:

<person age="30">
  <id>1</id>
  <name>foobar</name>
</person>

Script XML Elements with a single literal value

Some XML elements consist of multiple attributes and a single literal value. To create an XML element with attributes and a single literal value, use the value key in the map alongside the '@' attribute keys.

For example:

def document = [
  person: [
    @id: '1',
    @age: 30,
    value: 'foobar'
  ]
]

This produces the following XML:

<person id="1" age="30">foobar</person>