Equals

See also: Compare with

images/download/attachments/201667939/image-2025-4-8_12-32-33-version-1-modificationdate-1744108353146-api-v2.png

The Equals compare type checks whether the values determined as the Check value (value configuration on the left) and the Compare value (value configuration on the right) are considered to match according to the applicable criteria.

The Deep compare option should only be enabled to perform a 'deep comparison' (in terms of matching all features) of two complex data objects. Details are described in the 'Configuration' section (below).

►IMPORTANT◄ Compare values of different types?


If the Check value and the Compare value are not the same data type, automatic type conversion rules will apply to allow the values to be compared:

  • An automatic type conversion always tries to convert the Compare value (right) to the Check value type (left) and not the other way around.
    To illustrate:

    • The Check value '0815' (String) is not equal to the Compare value 815 (Long), because the Compare value is interpreted as String '815' by type conversion.

    • The Check value 815 (Long), on the other hand, is equal to a Compare value '0815' (String), since the Compare value is interpreted as Long 815 by type conversion.

  • Whether a type conversion succeeds may also depend on the execution context (server/client). Comparisons may turn out differently in Association criteria, Event handling, etc. than in a Client workflow.

To prevent uncertainties and 'surprises', it is recommended to explicitly define the type of Check value and Compare value for the comparison as far as necessary, e.g. via a concatenated Input object (type safe) resolver.

IMPORTANT◄ The Deep compare option should not be selected if the comparison of contents concerns two 'lists' (as a Check value and a Compare value).

  • In the server context, the 'content' comparison otherwise only considers the length field of the list, which means that differences between list entries are ignored as long as their number matches.

  • In a Client workflow, two lists are compared independently of the Deep compare option in terms of content – i.e. taking into account the individual list entries and their order.

Configuration

The value configurations for Check value (left) and Compare value (right) are not optional for the Endet mit comparison type.

The Deep compare option should be used only if the comparison of complex data objects requires it:

images/download/attachments/201667939/image-2025-4-8_12-32-46-version-1-modificationdate-1744108365686-api-v2.png

The Deep compare option is off (OFF) by default. Then the Equals comparison for complex data objects is passed only in the following cases:

    • The Check value and Compare value refer to the same data object. They must not be two 'clones' of the same entity (see examples below).

    • The Check value and Compare value are two 'client objects' with identical content and the comparison is performed in the server context (i.e. not in a Client workflow behaviour).

images/download/attachments/201667939/image-2025-4-8_12-32-59-version-1-modificationdate-1744108378667-api-v2.png

If the Deep compare option is activated, then all characteristics (such as fields, attributes, etc.) of the data objects passed as Check value and Compare value are compared (recursively if necessary) in order to determine whether the same object is described in the same sense and form. However, the check does not take into account whether the object is technically the same. This content check is generally more time-consuming than the simple comparison of the identity of two objects performed by default (see above).

The images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/warning.svg icon (see screenshot) appears when the option is turned on to indicate that comparing the object contents may have an unfavorable effect on performance.

Examples

Checking the match between two strings

To confirm a 'critical' operation in a workflow, a code word will be prompted from the user.

The string entered should match a Compare value (defined statically here as an exception) without regard to upper/lower case in order for the operation to be triggered.

Configuration:

The Entity property rule shown on the right can be used in the Validating rule of an event handler or in an If then else event action to conditionally perform the critical operation:

  • The value configuration for the Check value (left) uses the User prompt value resolver, whose return value is converted to a sequence of uppercase letters by the concatenated Upper case resolver.

  • In the value configuration for the Compare value, the Secret Code is statically stored as the chatGptMeIfYouCan string (see Static values). The concatenated Upper case value resolver below ensures that the Compare value in the comparison is also compared only as a sequence of uppercase letters.

NOTE◄ Typing a string like CHATGPTMEIFYOUCAN without errors is much easier for people if the sequence is broken up by alternating between lowercase and uppercase letters.

images/download/attachments/201667939/image-2025-4-8_12-33-59-version-1-modificationdate-1744108439563-api-v2.png

Compare integer part of a calculated 'Unit number' with a specific target value

An Entity property rule should apply exactly when the calculated weight of a liquid cargo is in the target range for a transport container (between 8 and 9 tons).

  • The liquid volume is specified with a selectable Volume unit. A volume_in_cbm variable provides the scalar for the number of corresponding cubic meters (cbm).

  • A weight_per_cbm variable is used to provide the weight of one cubic meter of the fluid in question in a selectable mass unit (Weight & mass units).

Configuration:

NOTE◄ For a comparison between numerical values, the Compare with comparison type should preferably be used and not Equals. Nevertheless, the successful use of the Equals comparison type in terms of the task is first demonstrated here.
The red shaded area of the table uses a configuration variant to explain possible misunderstandings and problems when comparing numerical values, which, however, should not play a role when using the Compare with comparison type.

The Entity property rule shown on the right offsets the input variables, checks the condition ('Load weight in target range'), and stores the charge weight in a weight variable for further use:

  • The Check value (left) defines the static default value for the integer portion of the load weight in tons.

  • The Compare value (right) includes the calculation in a Calculate value resolver. The weight of the liquid (number of cubic meters x weight of a cubic meter) is converted back to tons (t).

    • The primary calculated 'Unit number' is assigned to the weight variable by the concatenated Store value as variable resolver.

    • The concatenated Object property value resolver then accesses the 'Value' (value) of the unit number, which defines the Compare value in BigDecimal format (decimal number).

images/download/attachments/201667939/image-2025-4-8_12-35-47-version-1-modificationdate-1744108546624-api-v2.png

IMPORTANT◄ The Equals comparison type converts the Compare value data type (on the right) to the Check value type (on the left). In the configuration on the right, the Long data type that is relevant for the comparison appears in the hexagonal symbol for the Matchers. When converting decimals to integers, no rounding is done. The decimals are simply truncated.

NOTE◄ In the configuration on the right, 'only' the value configurations for Check value and Compare value are interchanged.

It could be assumed that such a 'change of sides' cannot affect an Equals comparison. After all, 'equality' intuitively sounds like 'symmetry' and 'interchangeability'.

However, this is not always the case:

  • Unlike the configuration shown above, in the variant on the right the Compare value is of the Long type and the Check value is of the BigDecimal type. So the type conversion of the Long value 8 into the BigDecimal value 8 takes place while the numerical value of the calculated load weight (left) maintains its decimal places differently than above. Therefore, the Entity property rule is now no longer fulfilled for weights > 8t.

  • Even if the lower limit of 8t would be matched exactly (e.g. with a volume_in_cbm of 10 and a weight_per_cbm of 800kg), it is not necessarily guaranteed that the Equals comparison and thus the Entity property rule will be passed.

images/download/attachments/201667939/image-2025-4-8_12-36-28-version-1-modificationdate-1744108587978-api-v2.png

IMPORTANT◄ Even if the calculated Check value (number of tons for the load weight in the 'Value' field on the left) corresponds mathematically exactly to the Compare value, an Equals comparison of the values as BigDecimal objects may not result in a match, as the display of the values actually compared in the comparison illustrates:

{ "class": "java.math.BigDecimal", "value": "8.000"} /* Calculated Check value */
{ "class": "java.math.BigDecimal", "value": "8" } /* BigDecimal-Conversion of the Compare value */

The calculated Check value contains three zeros as appended decimals, which are not relevant for a numerical comparison but nevertheless interfere with the agreement with the Compare value, which represents the same numerical value without the appended 'worthless' decimals.

NOTE◄ Whether decimals are added to the Check value in the course of the calculation depends on the specific numerical values and the calculation operations performed. In this specific case, the liquid volume was specified in liters (l) and then converted to cubic meters ((m3) (see Volume unit). By multiplying by 0.001, the 'worthless' decimals come into play here.

Conclusion:

An Input object (type safe) value resolver could be appended to the left side of the Compare value at the bottom of the value resolver chain for the Check value, which converts the 'value' of BigDecimal to the type of the Compare value (Long). Then the configuration shows the runtime behaviour of the original version, although the Check value and Compare value are reversed.

Using the floor()function for rounding the calculation result (in an additional instance of the Calculate value resolver would have the same effect for the Entity property rule.

In any case, a more robust comparison of numerical values is provided by using the Compare with comparison type instead of the Equals comparison type.

Compare lists

An association criteria (see Association criteria) should be considered passed if the company account (see Company accounts), which is considered the 'owner' of an entity given as input in the context, is associated with the same 'Company types' (types) as the Company of session.

Configuration:

The association criteria shown on the right defines a two-stage check within an AND conjunction (see Junction):

  • First, a Check type ensures that there is an 'entity' as a reference object in the context.

  • The following Entity property rule below is only evaluated in the context of an 'Entity'. It compares the 'Company types' (types) list field of the owning company and the Company of session using the Equals comparison type.

    • The Check value (left) is determined using a value resolution chain (see Chained resolver). Starting from the 'owner' (ownerId) field of the reference object, the relevant company account is first taken as the Input object (type safe). The concatenated Object property value resolver returns the list of the 'Company types' (see Company type) assigned there (see Company type), which is then sorted by the Sort list value resolver.

    • As a Compare value (right), the 'Company types' (types) list field is processed in the same way, based on the Company of session.

NOTE◄ The Sort list value resolver must use a sort criteria acting in the same sense in the Check value and in the Compare value in both cases. Only then is it guaranteed that the compared company type lists are evaluated as matching even if they contain the same entries in a different order.

Runtime example: (Rule is considered passed)

  • 'Company types' of the owner-company:

    • 'Bill-to party' (INV), 'Consignee' (CNE)

  • 'Company types' of Company of session:

    • 'Consignee' (CNE), 'Bill-to party' (INV)

images/download/attachments/201667939/image-2025-4-8_12-37-33-version-1-modificationdate-1744108652747-api-v2.png

Compare data objects

A tour list variable describes waypoints along a planned transport by unique combinations for the characteristics 'Country' (country), 'Area' (area) and optionally 'Zone' (zone). Each waypoint within the list is mapped as a 'client object' with the named fields, without any persistent entities facing these entries (so far).

  • By default, the first three characters from the postal code of a specific destination address are used as the identifier for an 'Area'.

  • Special destinations (e.g. industrial parks or logistic hubs) can additionally be identified by a text key 'Zone', which must be unique for the country/area combination.

For a given address, a check is made whether the assigned waypoint is contained in an existing tour. For this comparison, another 'client object' is created, to which field values for 'Country', 'Area' and possibly 'Zone' are assigned based on the address data. Afterwards, the tour list is searched for a waypoint with the same combination of characteristics.

Runtime example: Specific tour...

Destination
(Plain text)

Waypoint (fields)

List variable tour
in JSON notation

Country

Area

Zone

■ Prague,
Czech Republic

CZ
360

n/a

{
"class": "set",
"data": [
{
"area": "360",
"country": {
"class": "de.lobster.scm.denum.DynamicEnumDto",
"enumName": "de.lobster.scm.localization.Country",
"name": "CZ"
}
},
{
"area": "930",
"country": {
"class": "de.lobster.scm.denum.DynamicEnumDto",
"enumName": "de.lobster.scm.localization.Country",
"name": "DE"
}
},
{
"area": "844",
"country": {
"class": "de.lobster.scm.denum.DynamicEnumDto",
"enumName": "de.lobster.scm.localization.Country",
"name": "DE"
},
"zone": "CTR"
},
{
"area": "950",
"country": {
"class": "de.lobster.scm.denum.DynamicEnumDto",
"enumName": "de.lobster.scm.localization.Country",
"name": "AT"
}
},
{
"area": "137",
"country": {
"class": "de.lobster.scm.denum.DynamicEnumDto",
"enumName": "de.lobster.scm.localization.Country",
"name": "SI"
}
}
]
}

▼ Regensburg,
Germany

DE
930

n/a

▼ Burghausen,
Germany,
Zone 'CTR'

DE

844

CTR

▼ Rennstein,
Austria

AT

950

n/a

■ Logatec,
Slovenia

SI
137

n/a

Configuration:

The value resolver chain shown on the right examines the list of client objects representing waypoints provided in per tour variable:

  • The concatenated Rule list resolver defines the check condition per Entity property rule:

    • The Check value (left) is taken from a candidateWpt variable. This contains a 'Client object' that was created in advance and filled with the destination data to be checked.

    • The list entry of the tour to be evaluated should be used as the Compare value (right), i.e. the data object that represents an already present waypoint in the tour. This is returned by an Object property value resolver without specifying a field.

IMPORTANT◄ For the Equals comparison type (below) the Deep compare option has been set here, since the question is not whether the 'client object' in the candidateWpt variable has already been added to the tour list. Rather, the goal is to determine whether the tour list contains a waypoint that matches the 'candidate' in the candidateWpt variable in all fields (see runtime example below).

images/download/attachments/201667939/image-2025-4-8_12-39-15-version-1-modificationdate-1744108755004-api-v2.png

NOTE◄ If the check is limited to whether the tour list contains at least one waypoint 'client object' matching the 'candidate', the In list comparison type could in principle also be used in a simple Entity property rule (without the Rule list resolver). However, this approach only works in the server context, because 'client objects' are always compared by object content on the server side. Therefore, the Deep compare option in the above configuration can be omitted if it is guaranteed that the configuration will only be used in the server context and will never be copied to a Client workflow. In a Client workflow, the In list comparison type (like the Equals matcher with the Deep compare option turned off) only accepts truly identical objects as matches, which would not be appropriate for this example.

Runtime example:

Additional destination address
('Candidate')

'Candidate' transformed as waypoint 'client' object
candidateWpt

Check result
for tour as above

FROSTRANS KG
DE-84419 Schwindegg
{
"area": "844",
"country": {
"class": "de.lobster.scm.denum.DynamicEnumDto",
"enumName": "de.lobster.scm.localization.Country",
"name": "DE"
}
}

Candidate is considered a new waypoint, although the third waypoint ('Burghausen') refers to the same country (DE) and the same area (844).

The candidate lacks the 'Zone' (zone) feature.

FROSTRANS KG
DE-84419 Schwindegg
via
Combi Terminal Rail (CTR)
{
"area": "844",
"country": {
"class": "de.lobster.scm.denum.DynamicEnumDto",
"enumName": "de.lobster.scm.localization.Country",
"name": "DE"
},
"zone": "CTR"
}

The reference to the 'Combi Terminal Rail' (see destination address) is systematically reflected in the zone field of the waypoint.

This now also recognizes that the destination is covered by the third waypoint of the tour.

Compare entities

For the comparison of two entities, it is not sufficient for the Equals comparison type if the Check value and Compare value refer to the same entity type and ID (id).

  • If the Deep compare option is disabled (default), then it must be the same data object for the same entity for the comparison to pass.

  • If the Deep compare option is enabled (default), then the comparison is considered to have passed as long as the Check value and the Compare value completely match in terms of content (with regard to all field values).

IMPORTANT◄ Whether an Entity property rule with the Equals comparison type evaluates as expected when comparing two entities depends largely on the extent to which this expectation and the understanding of the runtime behaviour of involved value resolvers are correct in the client-side or server-side context.

The following table shows some simple but potentially 'common' examples, which are hardly relevant to practice in terms of content, but are intended to sensitize for the stumbling blocks of an Equals check of entities:

Check value

Compare value

Result for Equals
└ Option 'Deep compare' ...

Reason

... turned off

... turned on

images/download/attachments/201667939/image-2025-4-8_12-40-36-version-1-modificationdate-1744108835648-api-v2.png

images/download/attachments/201667939/image-2025-4-8_12-40-36-version-1-modificationdate-1744108835648-api-v2.png

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/error.svg not passed

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/check.svg passed

As a Check value and as a Compare value, one instance each of the Create instance value resolver returns a 'new' entity of the 'User' type (see Users). Although they do not differ in content immediately after creation, they are considered to be non-matching for Equals as long as the Deep compare option is turned off. If the option is enabled, however, they will pass the comparison of object contents.

images/download/attachments/201667939/image-2025-4-8_12-41-7-version-1-modificationdate-1744108867113-api-v2.png

images/download/attachments/201667939/image-2025-4-8_12-41-7-version-1-modificationdate-1744108867113-api-v2.png

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/error.svg not passed

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/check.svg passed

As a Check value and as a Compare value, one instance each of the Role of session value resolver returns an individual 'clone' of the role used in the session (see Roles). Although these two clones do not differ in content, they are considered non-matching for Equals as long as the Deep compare option is disabled. However, they pass the comparison performed with the option enabled.

images/download/attachments/201667939/image-2025-4-8_12-42-1-version-1-modificationdate-1744108920874-api-v2.png

images/download/attachments/201667939/image-2025-4-8_12-42-18-version-1-modificationdate-1744108938251-api-v2.png

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/check.svg passed

images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/check.svg passed

The entity variable provided by the system is specified as the Check value, which refers to the current reference object in the context. The concatenated Store value as variable value resolver assigns a reference to this reference object to a second variable entity2 as value.

The value configuration for the Compare value refers to the entity2 variable. Since this variable contains a reference to the reference object and not a 'clone' as in the previous example, the Check value and the Compare value are considered to match regardless of the Deep compare option.

images/download/attachments/201667939/image-2025-4-8_12-43-19-version-1-modificationdate-1744108999154-api-v2.png

images/download/attachments/201667939/image-2025-4-8_12-43-19-version-1-modificationdate-1744108999154-api-v2.png

in server context:
images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/check.svg passed


in Client workflow:
images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/error.svg
not passed

in server context:
images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/check.svg passed


in Client workflow:
images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/check.svg passed
but only by chance
(see notes right)

For the Check value and Compare value, the Role of session is first accessed. Since this value resolver returns two 'clones' of the actual role (see above), we access the 'ID' (id) field of the respective clone via concatenation, thereby using the Input object (type safe) value resolver to include the role in question in the current context without cloning it. In case of a server-side execution (e.g. in Event handling) the Equals comparison is therefore considered as passed.

NOTE◄ The Input object (type safe) value resolver only really returns the data of the role referenced by ID in the server context. In a Client workflow, it instead returns a data object for which only the class and id fields are filled. In the specific use case, the compared data objects are considered identical only because their IDs match.

images/download/attachments/201667939/image-2025-4-8_12-41-7-version-1-modificationdate-1744108867113-api-v2.png

images/download/attachments/201667939/image-2025-4-8_12-43-19-version-1-modificationdate-1744108999154-api-v2.png

in server context:
images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/error.svg not passed
(because of the 'clone' left)


in Client workflow:
images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/error.svg
not passed
(because of the 'clone' left)

in server context:
images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/error.svg not passed
(Details see right)

in Client workflow:
images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/error.svg not passed
(Details see right)

In the Check value, the Role of session value resolver provides a 'clone' of the role used in the session.

As in the previous example, the same role is added as an 'input object' as a Compare value via the ID found in the Role of session.

The Equals check fails in this configuration in all cases for different reasons:

  • Without the content comparison, the original and 'clone' are considered different for server and client.

  • The content comparison encounters specific differences on the server and client side:

    • The return value of the Role of session does not contain any data about the permissions of a role. The state provided on the server side as 'input object' contains this data.

    • On the client side, the Input object (type safe) value resolver returns only the ID field of a role.