-
Notifications
You must be signed in to change notification settings - Fork 268
Description
Description
The mi-module-gen tool currently supports generating synapse artifacts for:
- Public functions: Regular Ballerina functions
- Remote functions: Functions marked with the
remotequalifier
Support for resource functions is being added as per GitHub Issue #4362.
Problem Statement
Current Behavior (Remote Functions)
For remote functions, the synapse template name can be directly derived from the function name:
remote function getUsers() returns User[]|error {
// function implementation
}Synapse Name: getUsers (uses function name directly)
This works because remote function names are simple identifiers that are:
- Unique within the client class
- Valid XML identifiers
- Descriptive and meaningful
Issue with Resource Functions
Resource functions have a different structure:
resource isolated function get users/[string userId]/drafts(
map<string|string[]> headers = {},
*GmailUsersDraftsListQueries queries
) returns ListDraftsResponse|error {
oas:ListDraftsResponse draftList = check self.genClient->/users/[userId]/drafts(headers, queries);
return convertOASListDraftsResponseToListDraftsResponse(draftList);
}Current Behavior: The tool extracts only the HTTP method name (get) from methodSymbol.getName().get(), which results in:
- Synapse Name:
get(not unique or descriptive)
Problems:
- Non-unique names: Multiple resource functions with the same HTTP method (e.g.,
get users/...,get posts/...) would all generate the same synapse nameget, causing conflicts - Not descriptive: The name doesn't reflect the resource path, making it difficult to identify which resource the synapse template represents
- Invalid XML names: Resource paths contain special characters like
/,[,]that are not valid in XML element names
Technical Details
Current Implementation
In BalConnectorAnalyzer.java (line 110):
String functionName = methodSymbol.getName().get();
// ...
Component component = new Component(functionName, ...);For resource functions, methodSymbol.getName().get() returns only the HTTP method verb (e.g., "get", "post", "put", "delete"), not the full resource path.
Resource Function Structure in Ballerina
Resource functions in Ballerina have the following signature pattern:
resource [isolated] function <HTTP_METHOD> <resource_path>([parameters]) [returns <type>]
Where:
<HTTP_METHOD>: HTTP verb (get, post, put, delete, patch, head, options)<resource_path>: Path segments with optional path parameters (e.g.,users/[string userId]/drafts)- Path parameters are enclosed in square brackets:
[string paramName]
Proposed Solution Approach
1. Extract Resource Path from Function Signature
Need to extract the complete resource path from the resource function signature. This may require:
- Accessing the syntax tree node for the resource function
- Parsing the resource path segments
- Identifying path parameters
Investigation Needed:
- How to access the resource path from
MethodSymbolorFunctionSymbol? - Does the Ballerina Compiler API provide methods to extract resource paths?
- Alternative: Parse the function signature string representation
2. Generate Synapse Name from HTTP Method + Resource Path
Combine the HTTP method with the resource path to create a unique, descriptive name:
Example Transformations:
get users/[string userId]/drafts
→ getUsersDrafts
post users/[string userId]/messages
→ postUsersMessages
get users/[string userId]/messages/[string messageId]
→ getUsersMessages
Naming Strategy Options:
CamelCase with Path Segments
- Convert HTTP method to lowercase
- Convert each path segment to PascalCase
- Remove path parameter brackets and types
- Concatenate:
get+Users+Drafts=getUsersDrafts
3. Handle Edge Cases
Duplicate Names:
If two resource functions generate the same synapse name:
get users/drafts
get users/drafts
Solution: Append a numeric suffix: getUsersDrafts, getUsersDrafts2
Special Characters:
- Path segments may contain hyphens:
user-profiles→UserProfiles - Path segments may be numeric:
v1/users→V1UsersorgetV1Users
Path Parameters:
- Remove type information:
[string userId]→ use onlyuserIdfor naming context - Multiple parameters:
users/[string userId]/messages/[string msgId]→getUsersMessages
Empty Path Segments:
- Root resource:
get /→getRootorget
4. XML Name Validation
Ensure generated names are valid XML identifiers:
- Must start with a letter or underscore
- Can contain letters, digits, underscores, hyphens, periods
- Cannot contain spaces or special characters like
/,[,]
Sanitization Rules:
- Replace invalid characters with underscores or remove them
- Ensure first character is valid
- Handle consecutive special characters
Implementation Tasks
-
Research Ballerina Compiler API
- Identify how to extract resource path from
MethodSymbol/FunctionSymbol - Check if
ResourceMethodSymbolor similar specialized symbol exists - Explore syntax tree access for resource functions
- Identify how to extract resource path from
-
Create Resource Path Extraction Utility
- Implement method to extract HTTP method and resource path
- Handle different resource function signatures
- Support both isolated and non-isolated resource functions
-
Implement Synapse Name Generation
- Create utility method:
generateSynapseNameForResource(String httpMethod, String resourcePath) - Apply naming strategy (CamelCase recommended)
- Handle path parameter extraction and removal
- Sanitize for XML validity
- Create utility method:
-
Update Component Creation Logic
- Modify
BalConnectorAnalyzer.javato use new naming logic for resource functions - Keep existing logic for remote and public functions
- Add validation to ensure unique names within a connection
- Modify
-
Add Tests
- Test various resource path patterns
- Test edge cases (special characters, duplicates, etc.)
- Verify XML name validity
- Ensure backward compatibility with remote functions
Example Scenarios
Scenario 1: Simple Resource Path
resource isolated function get users/drafts() returns Draft[]|errorGenerated Synapse Name: getUsersDrafts
Scenario 2: Resource Path with Parameters
resource isolated function get users/[string userId]/drafts(...) returns Draft[]|errorGenerated Synapse Name: getUsersDrafts
(Path parameter [string userId] is used for parameter extraction but removed from name)
Scenario 3: Multiple Path Segments
resource isolated function post users/[string userId]/messages/[string messageId]/replies(...) returns Reply|errorGenerated Synapse Name: postUsersMessagesReplies
Scenario 4: Root Resource
resource isolated function get /() returns RootResource|errorGenerated Synapse Name: getRoot or get
Scenario 5: Conflicting Names
resource isolated function get users/drafts(...) returns Draft[]|error
resource isolated function get users/drafts(...) returns Draft[]|error // Different signature but same pathGenerated Synapse Names: getUsersDrafts, getUsersDrafts2
References
- GitHub Issue #4362 - Support for resource functions in mi-module-gen tool
- Ballerina Language Specification - Resource Functions
- Apache Synapse XML Template Naming Conventions
Notes
- The current implementation in
BalConnectorAnalyzer.javaline 120 creates components withfunctionNamedirectly - The synapse template XML uses
{{name}}from the component (seefunctions_template.xmlline 19) - Need to ensure the generated name is compatible with Synapse template naming requirements
- Consider impact on existing connectors that may already use resource functions (if any)
Version
No response