Constraint Modeling Language (CML) – Step-by-Step Implementation Guide
A practical guide to configuring a simple CML use case in Salesforce Revenue Cloud using table-based constraints, dynamic attribute visibility, mandatory field rules, and user guidance messages.
Constraint Modeling Language (CML) helps teams define product configuration logic declaratively within Salesforce Revenue Cloud. Instead of relying on extensive custom code, teams can use CML to control valid combinations, enforce requirements, and shape the configuration experience in Product Configurator with a cleaner and more maintainable design.
Functional Use Case
For this guide, we will configure a simple Payment Service product. The user selects a Payment Type, and based on that selection the configurator should dynamically control which attributes are visible, which values are valid, and which fields must be completed.
| Condition | Expected System Behavior |
|---|---|
| Payment Type = Credit Card | Show EMI Option |
| Payment Type = UPI | Hide EMI Option |
| Payment Type = Credit Card | Show Card Type |
| Payment Type = UPI | Hide Card Type |
| Credit Card selected | Card Type becomes mandatory |
| UPI selected | Show guidance message that EMI is not available |
Product and Attribute Setup
Product
| Field | Value |
|---|---|
| Product Name | Payment Service |
| Product Code | PAY-001 |
| Type | Service |
Attributes
| Attribute Name | Type | Values |
|---|---|---|
| Payment Type | Picklist | Credit Card, Debit Card, UPI |
| EMI Option | Picklist | Yes, No |
| Card Type | Picklist | Visa, MasterCard, RuPay |
Constraint Model Setup
- Create a Constraint Model for the Payment Service product.
- Create a Constraint Version under that model.
- Open the CML Editor.
- Configure the Type Association so the product maps correctly to the CML type.
Base Type Definition
type PaymentService {
@(nullAssignable = true)
string PT_D = ["Credit Card", "Debit Card", "UPI"];
@(nullAssignable = true)
string CT_D = ["Visa", "MasterCard", "RuPay"];
@(nullAssignable = true)
string EMI_Def = ["No", "Yes"];
}
Rule Configuration
1. Table Constraint
Use a table constraint to define valid combinations of Payment Type, EMI Option, and Card Type. This prevents unsupported combinations from being selected.
constraint(
table(
PT_D,
EMI_Def,
PT_D,
{"Credit Card", "Yes", "Visa"},
{"Credit Card", "Yes", "MasterCard"},
{"Debit Card", "No", "RuPay"},
{"UPI", "No", "RuPay"}
),
"Selected combination is not valid."
);
2. Hide Rules
Hide EMI Option and Card Type when UPI is selected, because those fields are not relevant in that scenario.
rule(
PT_D == "UPI",
"hide",
"attribute",
"EMI_Def"
);
rule(
PT_D == "UPI",
"hide",
"attribute",
"CT_D"
);
3. Message Rule
Guide the user with a contextual message so the behavior is clear and not confusing.
message(
PT_D == "UPI",
"EMI is not available for UPI payments."
);
Complete CML Example
type PaymentService {
@(nullAssignable = true)
string PT_D = ["Credit Card", "Debit Card", "UPI"];
@(nullAssignable = true)
string CT_D = ["Visa", "MasterCard", "RuPay"];
@(nullAssignable = true)
string EMI_Def = ["No", "Yes"];
constraint(PT_D != null, "Select Payment Type");
constraint(CT_D != null, "Select Card Type");
constraint(EMI_Def != null, "Select EMI Option");
message(PT_D == "UPI", "EMI is not available for UPI payments.");
rule(PT_D == "UPI", "hide", "attribute", "EMI_Def");
rule(PT_D == "UPI", "hide", "attribute", "CT_D");
// Force user selection
constraint( table(PT_D,EMI_Def,CT_D,{"Credit Card","Yes","Visa"},{"Credit Card","Yes","MasterCard"},{"Debit Card","No","RuPay"},{"UPI","No","RuPay"}) , "Selected combination is not valid.");
}
Testing Scenarios
| Scenario | Input | Expected Output |
|---|---|---|
| Scenario 1 | Payment Type = UPI | EMI Option hidden, Card Type hidden, message displayed |
| Scenario 2 | Payment Type = Credit Card | EMI Option visible, Card Type visible, Card Type required, EMI Option defaulted to Yes |
| Scenario 3 | Credit Card + EMI = No | Configuration error shown because the combination is not in the valid table |
Optional Upgrade: Use SalesforceTable
If you want to make the logic business-maintainable, move valid combinations into a Salesforce object and use SalesforceTable instead of hardcoding rows in CML.
SalesforceTable(
"PaymentRule__c",
"PaymentType__c,EMIOption__c,CardType__c"
)
This pattern is useful when business rules change frequently and should be maintained in data rather than code.
Key Takeaways
- CML provides a structured way to control product configuration behavior in Revenue Cloud.
- Table constraints are ideal for validating supported combinations across multiple attributes.
- Require rules help enforce mandatory inputs only when relevant.
- Hide rules improve user experience by removing unnecessary fields dynamically.
- Message rules make the configuration experience easier to understand.
- SalesforceTable can be used to shift logic from code to data-driven administration.
Conclusion
This use case is intentionally simple, but it demonstrates the most important CML concepts in a highly practical way. Once a team understands this pattern, it becomes much easier to extend the same approach to more advanced configuration scenarios such as attribute filtering, bundled product behavior, recommendation rules, and context-driven configuration.
For teams starting their Revenue Cloud journey, this is an excellent foundational example because it connects business behavior directly to CML logic in a way that is easy to configure, test, and explain.