Let me provide a comprehensive solution for implementing central contract splits based on custom fields using Business Rules Framework, covering the central contract split logic, custom field support requirements, and proper Business Rules Framework integration.
Understanding Central Contract Split Architecture:
SAP CX central contract splitting uses a three-layer architecture:
- Contract Data Layer: Source contract with all fields (standard + custom)
- Business Rules Evaluation Layer: Rules engine that determines split criteria
- Contract Creation Layer: Generates child contracts based on split results
Custom fields exist in Layer 1 but aren’t automatically available in Layer 2. You need to bridge this gap.
Solution: Custom Attribute Provider Implementation
Step 1: Create Custom Attribute Provider Class
Create a Java class that exposes custom fields to the Business Rules Framework:
public class ContractCustomFieldProvider implements AttributeProvider {
@Override
public Map<String, Object> getAttributes(Object entity) {
Map<String, Object> attributes = new HashMap<>();
if (entity instanceof Contract) {
Contract contract = (Contract) entity;
attributes.put("ServiceRegion",
contract.getCustomField("ServiceRegion"));
}
return attributes;
}
}
Step 2: Register Provider in Business Rules Configuration
Add provider registration to your Business Rules Framework configuration XML:
<rule-configuration>
<attribute-providers>
<provider class="com.custom.ContractCustomFieldProvider"
entity-type="Contract"
priority="100"/>
</attribute-providers>
</rule-configuration>
Step 3: Update Business Rule Definition
Modify your contract split rule to use the exposed custom field:
<rule id="CONTRACT_SPLIT_BY_REGION">
<condition>
<expression>contract.ServiceRegion != null</expression>
</condition>
<actions>
<split-contract>
<split-criteria field="ServiceRegion"/>
<child-contract-template>REGION_CONTRACT</child-contract-template>
</split-contract>
</actions>
</rule>
Step 4: Custom Field Type Considerations
Business Rules Framework supports these custom field types for split criteria:
- Picklist/Enumeration: Best for categorical splits (like your ServiceRegion)
- Text Fields: Supported but requires exact string matching
- Numeric Fields: Supported with range-based split logic
- Date Fields: Supported with date range splits
- Boolean Fields: Supported for binary splits
NOT Supported:
- Multi-select picklists (ambiguous split logic)
- Rich text fields (too complex for rule evaluation)
- Related object fields (requires join logic)
Complete Implementation for ServiceRegion Split:
Here’s the full implementation addressing your specific use case:
1. Enhanced Attribute Provider with Validation:
public class ContractRegionAttributeProvider implements AttributeProvider {
private static final Set<String> VALID_REGIONS =
Set.of("EMEA", "APAC", "AMERICAS");
@Override
public Map<String, Object> getAttributes(Object entity) {
Map<String, Object> attributes = new HashMap<>();
if (entity instanceof Contract) {
Contract contract = (Contract) entity;
String region = contract.getCustomField("ServiceRegion");
// Validate region value before exposing
if (VALID_REGIONS.contains(region)) {
attributes.put("ServiceRegion", region);
attributes.put("isValidRegion", true);
} else {
attributes.put("ServiceRegion", "INVALID");
attributes.put("isValidRegion", false);
}
}
return attributes;
}
}
2. Business Rule with Error Handling:
<rule id="CONTRACT_SPLIT_BY_REGION" priority="10">
<condition>
<and>
<expression>contract.ServiceRegion != null</expression>
<expression>contract.isValidRegion == true</expression>
<expression>contract.status == 'ACTIVE'</expression>
</and>
</condition>
<actions>
<split-contract>
<split-criteria field="ServiceRegion"/>
<child-contract-properties>
<inherit-fields>true</inherit-fields>
<override-field name="contractType">REGIONAL_CONTRACT</override-field>
<copy-custom-field source="ServiceRegion" target="ServiceRegion"/>
</child-contract-properties>
<split-mode>CREATE_CHILDREN</split-mode>
</split-contract>
</actions>
<on-error>
<log-message>Contract split failed for contract {contract.id}: Invalid ServiceRegion value</log-message>
<set-field name="splitStatus" value="FAILED"/>
</on-error>
</rule>
3. Deployment Configuration:
Update your SAP CX deployment descriptor to load the custom provider:
<extension name="customcontractsplit">
<classes>
<class>com.custom.ContractRegionAttributeProvider</class>
</classes>
<business-rules>
<rule-file>contract-split-rules.xml</rule-file>
</business-rules>
</extension>
Testing the Implementation:
-
Unit Test Custom Attribute Provider:
- Create test contract with ServiceRegion = “EMEA”
- Call getAttributes() and verify ServiceRegion is returned
- Test with invalid region value, verify validation logic
-
Integration Test Business Rule:
- Create central contract with line items for multiple regions
- Trigger contract split process
- Verify child contracts created for each unique ServiceRegion value
- Confirm custom field values copied to child contracts
-
End-to-End Test:
- Create contract with mixed region line items
- Execute split via UI or API
- Validate:
- Central contract status updated to SPLIT
- Three child contracts created (one per region)
- Each child contract has correct ServiceRegion value
- Line items distributed correctly to regional contracts
Common Issues and Resolutions:
Issue 1: “Custom field not accessible” error persists
Resolution: Verify attribute provider is registered BEFORE Business Rules Framework initialization. Check deployment order in extension configuration.
Issue 2: Split creates empty child contracts
Resolution: Ensure split-criteria field matches EXACTLY the attribute name exposed by provider (case-sensitive).
Issue 3: Some line items not included in split
Resolution: Add line-item-distribution logic to rule actions specifying how to distribute items based on their individual ServiceRegion values.
Issue 4: Performance degradation with large contracts
Resolution: Implement caching in attribute provider - cache custom field values during provider initialization rather than fetching on every attribute access.
Best Practices for Custom Field-Based Splits:
- Validation: Always validate custom field values before split execution
- Logging: Add detailed logging in attribute provider for troubleshooting
- Error Handling: Implement on-error handlers in rules to prevent partial splits
- Testing: Test with edge cases (null values, empty strings, invalid enumerations)
- Documentation: Document which custom fields are exposed and their expected formats
- Performance: Cache custom field metadata to avoid repeated database queries
- Versioning: Version your attribute providers to handle schema changes
Alternative Approach: Pre-Processing Extension
If attribute provider approach proves too complex, consider a pre-processing extension:
- Create a custom contract split service that reads custom fields
- Map custom field values to standard contract attributes (like contract category)
- Use standard Business Rules Framework split logic on mapped attributes
- Post-process child contracts to restore original custom field values
This approach avoids Business Rules Framework custom field limitations but requires more custom code.
Verification of Success:
Your implementation is working correctly when:
- Business Rule evaluation logs show ServiceRegion attribute available
- Contract split creates correct number of child contracts (one per unique region)
- Each child contract has appropriate ServiceRegion value
- No manual intervention required for region-based splits
- Split execution time remains under 5 seconds for contracts with up to 100 line items
This draft is based on general SAP Customer Experience (SAP CX) knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.