Skip to content

Add REST API resource for AI-assisted SDK generation with Application Code Generation #13121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 37 commits into
base: ai-sdk-generator
Choose a base branch
from

Conversation

HabeebaMinhar
Copy link

Purpose

Introduce a new API resource to support AI-assisted SDK generation for multiple APIs, including generation of application code in either Java or JavaScript based on the provided use case.

Description

This pull request introduces a new REST API resource and implements the following core functionality:

  • Retrieves OpenAPI specifications for the selected API IDs.
  • Sends the retrieved specifications to the AI service for merging into a unified specification.
  • If a use case is provided by the user:
    • Sends the specification, SDK methods file, use case, and preferred programming language (Java or JavaScript) to the AI service.
    • Receives and returns application code tailored to the provided use case.

@CLAassistant
Copy link

CLAassistant commented May 26, 2025

CLA assistant check
All committers have signed the CLA.

Copy link

coderabbitai bot commented May 26, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

This change introduces a new AI-assisted SDK generation feature to the API Manager. It adds configuration support, DTOs, and REST API endpoints for generating SDKs for multiple APIs associated with an application, optionally including application code generation based on a use case description. The implementation includes backend logic, configuration templates, and OpenAPI documentation updates.

Changes

File(s) / Area Change Summary
APIConstants.java Added new string constants for SDK generation configuration under the nested AI class.
APIManagerConfiguration.java Added support for SDK generation configuration: new DTO, getter, setter, and XML parsing logic for <SdkGeneration> configuration.
dto/ai/SDKGenerationConfigurationDTO.java Introduced new DTO class encapsulating SDK generation configuration properties and corresponding getters/setters.
devportal-api.yaml (common, store.v1) Added new POST endpoint /applications/{applicationId}/generate-sdk/{language} for SDK generation, with supporting schemas (SDKGenerationRequest, APIIdsList, APIId). Updated API documentation and security scopes.
ApplicationsApiServiceImpl.java Implemented backend logic for the new SDK generation endpoint: validates API subscriptions, retrieves/merges OpenAPI specs, invokes AI service for merging/generation, handles code generation with use case, and packages the final ZIP response. Added several helper methods for these steps.
org.wso2.carbon.apimgt.core.default.json Added new configuration keys for SDK generation resource endpoints under the AI namespace.
api-manager.xml.j2 Added new <SdkGeneration> configuration block for enabling and configuring AI-assisted SDK generation, including resource endpoints, authentication, and feature toggles.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant StoreAPI
    participant APIConsumer
    participant AIService
    participant SDKManager

    Client->>StoreAPI: POST /applications/{applicationId}/generate-sdk/{language}
    StoreAPI->>APIConsumer: Validate API subscriptions
    APIConsumer-->>StoreAPI: API subscription info
    StoreAPI->>APIConsumer: Retrieve OpenAPI specs for API IDs
    APIConsumer-->>StoreAPI: OpenAPI specs
    StoreAPI->>AIService: Merge OpenAPI specs (if multiple APIs)
    AIService-->>StoreAPI: Merged OpenAPI spec
    StoreAPI->>SDKManager: Generate SDK ZIP for merged spec and language
    SDKManager-->>StoreAPI: SDK ZIP
    alt useCaseDescription provided
        StoreAPI->>AIService: Generate application code (spec, SDK methods, use case)
        AIService-->>StoreAPI: Application code
        StoreAPI->>Client: Return ZIP (SDK + application code)
    else
        StoreAPI->>Client: Return SDK ZIP
    end
Loading

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Arshardh
Copy link
Contributor

@coderabbitai review

Copy link

coderabbitai bot commented May 27, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (4)
components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml (1)

4388-4412: Simplify APIIdsList for request payloads
The APIIdsList schema currently mimics a paginated response (count + list), which is counter-intuitive for a request. For clarity and ease of use, consider changing it to a simple array of APIId or even a string UUID array:

# Option A: array of UUID strings
SDKGenerationRequest:
  type: object
  required:
    - apiIds
  properties:
    apiIds:
      type: array
      items:
        type: string
        format: uuid

# Option B: array of APIId objects
APIIdsList:
  type: array
  items:
    $ref: '#/components/schemas/APIId'

This reduces boilerplate in client payloads.

components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java (3)

815-892: Consider refactoring this method for better maintainability.

The method is well-implemented but quite long (77 lines) and handles multiple responsibilities. While functional, it could benefit from further decomposition for better maintainability and testability.

Consider extracting validation logic into separate methods:

private void validateApiSubscriptions(List<APIIdDTO> apiIdList, Set<String> subscribedApiIds) {
    // Extract validation logic from lines 844-856
}

private Response handleUseCaseGeneration(Response sdkResponse, String apiSpec, String useCase, String language, String appName) {
    // Extract use case handling logic from lines 866-883
}

This would make the main method more focused and easier to test individual components.


1012-1039: Good resource management, consider improving path construction.

The method properly uses try-with-resources for ZIP handling. However, the hardcoded language-specific paths could be more maintainable.

Consider extracting path construction to a separate method or configuration:

private String getMethodsFilePath(String language, String applicationName) {
    switch (language.toLowerCase()) {
        case "java":
            return "/src/main/java/org/wso2/client/api/" + applicationName + "/DefaultApi.java";
        case "javascript":
            return "/src/org.wso2.client.api." + applicationName + "/DefaultApi.js";
        default:
            throw new IllegalArgumentException("Unsupported language: " + language);
    }
}

1101-1145: Improve resource cleanup for temporary files.

The method creates temporary files and relies on deleteOnExit(), which may not execute in all JVM shutdown scenarios. Consider more robust cleanup.

Use try-with-resources or explicit cleanup:

private Response packageSDKAndApplicationCode(File sdkFile, String applicationCode, String language) throws IOException {
    Path tempDir = Files.createTempDirectory("sdk_code_package");
    try {
        File zipFile = tempDir.resolve("SDK_CODE.zip").toFile();
        // ... processing logic ...
        return Response.ok(zipFile, MediaType.APPLICATION_OCTET_STREAM_TYPE)
                .header("Content-Disposition", "attachment; filename=\"SDK_CODE.zip\"")
                .build();
    } finally {
        // Explicit cleanup
        Files.walk(tempDir)
                .sorted(Comparator.reverseOrder())
                .map(Path::toFile)
                .forEach(File::delete);
    }
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 042a420 and 03e3602.

⛔ Files ignored due to path filters (5)
  • components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/ApplicationsApi.java is excluded by !**/gen/**
  • components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/ApplicationsApiService.java is excluded by !**/gen/**
  • components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/APIIdDTO.java is excluded by !**/gen/**
  • components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/APIIdsListDTO.java is excluded by !**/gen/**
  • components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/SDKGenerationRequestDTO.java is excluded by !**/gen/**
📒 Files selected for processing (8)
  • components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java (1 hunks)
  • components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java (5 hunks)
  • components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/ai/SDKGenerationConfigurationDTO.java (1 hunks)
  • components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml (2 hunks)
  • components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java (3 hunks)
  • components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml (2 hunks)
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/org.wso2.carbon.apimgt.core.default.json (1 hunks)
  • features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java (2)
components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/ai/SDKGenerationConfigurationDTO.java (1)
  • SDKGenerationConfigurationDTO (24-107)
components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConstants.java (1)
  • APIConstants (24-124)
🔇 Additional comments (13)
components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java (1)

566-573:

✅ Verification successful

Ensure new SDK generation constants align with API and configuration
The literals ("SdkGeneration", "Enabled", "AuthToken", "MergeSpecResource", "GenerateCodeResource", etc.) must exactly match the keys used in APIManagerConfiguration, DTO mappings, and the JAX-RS @Path annotations of the new SDK generation endpoints. Please verify that:

  1. APIManagerConfiguration parses these new keys.
  2. The DTOs and service implementation reference these constants (e.g., SDK_GENERATION_MERGE_SPEC_RESOURCE).
  3. The REST resource classes use matching @Path values.

🏁 Script executed:

#!/bin/bash
# Verify references to SDK generation constants in the codebase
rg -n "SdkGeneration" 
rg -n "MergeSpecResource" 
rg -n "GenerateCodeResource"

Length of output: 5506


No action required: SDK generation constants are properly aligned

  • All SDK generation keys in APIConstants (e.g., SDK_GENERATION, SDK_GENERATION_MERGE_SPEC_RESOURCE, SDK_GENERATION_GENERATE_CODE_RESOURCE) are correctly parsed by APIManagerConfiguration and populated into SDKGenerationConfigurationDTO.
  • ApplicationsApiServiceImpl uses the DTO getters (getMergeSpecResource(), getGenerateCodeResource(), etc.) to invoke the configured external endpoints.
  • There are no direct references to these constants in JAX-RS @Path annotations—endpoint paths are defined via the OpenAPI spec, not with these config keys.
features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/org.wso2.carbon.apimgt.core.default.json (1)

62-63: LGTM! Well-structured configuration additions.

The new SDK generation resource configuration entries follow the established naming conventions and patterns used by other AI features in this configuration file. The resource paths are descriptive and follow REST API conventions.

features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 (1)

467-484: LGTM! Consistent configuration structure.

The new <SdkGeneration> configuration section follows the established pattern used by other AI features like APIChat, MarketplaceAssistant, and DesignAssistant. The template variables are consistent with the configuration keys defined in the JSON file, maintaining good cohesion across configuration formats.

components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/ai/SDKGenerationConfigurationDTO.java (1)

24-107: Well-structured DTO with proper encapsulation.

The class follows standard DTO patterns with:

  • Appropriate private fields for configuration properties
  • Standard getter and setter methods
  • Boolean flags for validation purposes

The field names are descriptive and the structure supports the SDK generation feature requirements effectively.

components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java (5)

42-42: LGTM! Import statement is correctly implemented.

The import follows the established pattern and is properly placed alphabetically with other AI configuration DTO imports.


133-133: LGTM! Static instance declaration follows established patterns.

The declaration is consistent with other AI configuration DTOs in the class and follows proper naming conventions.


210-214: LGTM! Getter method implementation is consistent and correct.

The method follows the established pattern used by other AI configuration getters in the class.


698-700: LGTM! XML parsing integration is correctly implemented.

The conditional check follows the established pattern for other AI configurations and uses the appropriate constant from APIConstants.AI.


2810-2861: LGTM! SDK generation configuration method is well-implemented and secure.

The method implementation follows established patterns and best practices:

  • Consistent structure: Mirrors the implementation of other AI configuration methods in the class
  • Proper security handling: Uses MiscellaneousUtil.resolve() for secret resolution of sensitive data (keys and tokens)
  • Null safety: Includes appropriate null checks before accessing element text
  • Boolean flag management: Correctly sets keyProvided and authTokenProvided flags based on non-empty values
  • Resource configuration: Properly reads and sets merge spec and generate code resource paths
  • Naming conventions: Variables and method names follow established conventions in the codebase

The implementation integrates seamlessly with the existing AI configuration framework and maintains consistency with other similar features.

components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java (4)

41-42: LGTM! Import additions support the new SDK generation functionality.

The new imports are appropriate and necessary for the AI-assisted SDK generation feature implementation.

Also applies to: 44-45, 50-50, 55-55, 69-78


894-927: LGTM! Well-structured API specification retrieval method.

The method properly handles both single and multiple API scenarios with appropriate error handling and clear logic flow.


936-976: Good error handling, but thread safety concern remains.

The method has excellent error handling for different AI service failure scenarios (accessibility, throttling, general errors). However, it still uses the problematic static configDto field mentioned earlier.

The error handling properly categorizes AI service failures, which is good for debugging and user feedback.


978-1002: LGTM! Clean SDK generation implementation.

The method properly uses the APIClientGenerationManager with appropriate error handling and follows REST response conventions.

Comment on lines 21 to 23
/**
* This class represent the Marketplace Assistant configuration DTO.
*/
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect class documentation.

The Javadoc comment incorrectly states this class represents the "Marketplace Assistant configuration DTO" when it should refer to SDK generation configuration.

Apply this diff to correct the documentation:

 /**
- * This class represent the Marketplace Assistant configuration DTO.
+ * This class represents the SDK Generation configuration DTO.
  */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* This class represent the Marketplace Assistant configuration DTO.
*/
/**
* This class represents the SDK Generation configuration DTO.
*/
🤖 Prompt for AI Agents
In
components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/ai/SDKGenerationConfigurationDTO.java
around lines 21 to 23, the class Javadoc incorrectly states it represents the
"Marketplace Assistant configuration DTO." Update the comment to accurately
describe the class as representing the SDK generation configuration DTO.

Comment on lines 4388 to 4399
SDKGenerationRequest:
title: SDK Generation Request
type: object
properties:
apiIdsList:
$ref: '#/components/schemas/APIIdsList'
useCaseDescription:
type: string
description: |
An optional description of the use case for generating the SDK.
example: "This SDK will be used for integrating multiple APIs into a mobile application."
APIIdsList:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enforce required properties on SDKGenerationRequest
The SDKGenerationRequest schema declares apiIdsList and useCaseDescription but does not mark any field as required. At minimum, apiIdsList should be required to prevent invalid or empty payloads:

SDKGenerationRequest:
  type: object
  required:
    - apiIdsList
  properties:
    apiIdsList:
      $ref: '#/components/schemas/APIIdsList'
    useCaseDescription:
      type: string
      description: |
        An optional description of the use case for generating the SDK.
      example: "This SDK will be used for integrating multiple APIs into a mobile application."
🤖 Prompt for AI Agents
In
components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml
around lines 4388 to 4399, the SDKGenerationRequest schema does not specify any
required properties. To ensure valid payloads, add a required field listing with
"apiIdsList" included. This change will enforce that apiIdsList must be present
in requests, preventing empty or invalid SDKGenerationRequest objects.

Comment on lines 1761 to 1812
/applications/{applicationId}/generate-sdk/{language}:
post:
tags:
- SDK Generation
summary: Generate a single SDK for multiple APIs and optionally generate application code
description: |
Retrieve Swagger definitions for the provided API IDs and generate SDKs.
Optionally generate application code if use case is provided.
parameters:
- $ref: '#/components/parameters/applicationId'
- name: language
in: path
description: |
Programming language of the SDK that is required.

Languages supported by default are **Java**, **Javascript**, **Android** and **JMeter**.
required: true
schema:
type: string
requestBody:
description: |
Object containing the list of API IDs for which Swagger definitions need to be retrieved.
Optionally, a use case description can be provided.
content:
application/json:
schema:
$ref: '#/components/schemas/SDKGenerationRequest'
responses:
200:
description: |
OK.
SDK generated successfully.
content:
application/zip:
schema:
type: string
format: byte
400:
$ref: '#/components/responses/BadRequest'
404:
$ref: '#/components/responses/NotFound'
500:
$ref: '#/components/responses/InternalServerError'
security:
- OAuth2Security:
- apim:subscribe
- apim:app_manage
x-code-samples:
- lang: Curl
source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8"
-H "Content-Type: application/json" -X POST -d @data.json "https://localhost:9443/api/am/devportal/v3/applications/896658a0-b4ee-4535-bbfa-806c894a4015/generate-sdk"'

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Inconsistent sample URL: missing language parameter in x-code-samples
The x-code-samples entry under this endpoint omits the {language} segment defined in the path (/applications/{applicationId}/generate-sdk/{language}). This will confuse integrators.
Suggest updating the sample to include a concrete language, for example:

- lang: Curl
  source: >
    curl -k -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -X POST -d @data.json \
      "https://localhost:9443/api/am/devportal/v3/applications/896658a0-b4ee-4535-bbfa-806c894a4015/generate-sdk/javascript"
🤖 Prompt for AI Agents
In
components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml
between lines 1761 and 1812, the x-code-samples section for the POST endpoint
/applications/{applicationId}/generate-sdk/{language} is missing the required
{language} path parameter in the sample URL. To fix this, update the sample curl
command URL to include a concrete language value such as "javascript" after
generate-sdk, ensuring the sample matches the defined path and avoids confusion
for integrators.

💡 Verification agent

🧩 Analysis chain

Promote reuse: externalize language parameter
You’ve inlined the language path parameter here. For consistency with other endpoints, consider defining it once under components/parameters/language (with enum: [java, javascript, android, jmeter]) and then referencing it via - $ref: '#/components/parameters/language'. This improves discoverability and DRYs up the spec.


🏁 Script executed:

#!/bin/bash
# Verify if a reusable `language` parameter exists
rg -n "parameters:" -n components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml

Length of output: 1812


🏁 Script executed:

#!/bin/bash
# Check if a reusable `language` parameter is defined under components/parameters
pip install pyyaml >/dev/null 2>&1
python3 << 'EOF'
import yaml, sys
path = 'components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml'
try:
    with open(path) as f:
        doc = yaml.safe_load(f)
except Exception as e:
    print('ERROR loading YAML:', e)
    sys.exit(1)
params = doc.get('components', {}).get('parameters', {})
if isinstance(params, dict) and 'language' in params:
    print('FOUND')
    import json
    print(json.dumps(params['language'], indent=2))
else:
    print('NOT FOUND')
EOF

Length of output: 198


Externalize language path parameter to a reusable component
We already have a components/parameters/language defined as a query parameter. Reusing it for a path parameter would mix contexts and may introduce confusion. Instead, introduce a new reusable parameter (e.g. languagePath) under components/parameters with in: path and an enum of supported SDK languages, then swap out the inline definition in /applications/{applicationId}/generate-sdk/{language}.

Locations to update:

  • components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml
    1. Under components.parameters, add languagePath.
    2. In the post operation for /applications/{applicationId}/generate-sdk/{language}, replace the inline language block with a $ref to languagePath.

Proposed diff:

 components:
   parameters:
+    languagePath:
+      name: language
+      in: path
+      description: Programming language for SDK generation. Supported values: Java, Javascript, Android, JMeter.
+      required: true
+      schema:
+        type: string
+        enum:
+          - java
+          - javascript
+          - android
+          - jmeter

 /applications/{applicationId}/generate-sdk/{language}:
   post:
     parameters:
-      - name: language
-        in: path
-        description: |
-          Programming language of the SDK that is required.
-
-          Languages supported by default are **Java**, **Javascript**, **Android** and **JMeter**.
-        required: true
-        schema:
-          type: string
+      - $ref: '#/components/parameters/languagePath'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/applications/{applicationId}/generate-sdk/{language}:
post:
tags:
- SDK Generation
summary: Generate a single SDK for multiple APIs and optionally generate application code
description: |
Retrieve Swagger definitions for the provided API IDs and generate SDKs.
Optionally generate application code if use case is provided.
parameters:
- $ref: '#/components/parameters/applicationId'
- name: language
in: path
description: |
Programming language of the SDK that is required.
Languages supported by default are **Java**, **Javascript**, **Android** and **JMeter**.
required: true
schema:
type: string
requestBody:
description: |
Object containing the list of API IDs for which Swagger definitions need to be retrieved.
Optionally, a use case description can be provided.
content:
application/json:
schema:
$ref: '#/components/schemas/SDKGenerationRequest'
responses:
200:
description: |
OK.
SDK generated successfully.
content:
application/zip:
schema:
type: string
format: byte
400:
$ref: '#/components/responses/BadRequest'
404:
$ref: '#/components/responses/NotFound'
500:
$ref: '#/components/responses/InternalServerError'
security:
- OAuth2Security:
- apim:subscribe
- apim:app_manage
x-code-samples:
- lang: Curl
source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8"
-H "Content-Type: application/json" -X POST -d @data.json "https://localhost:9443/api/am/devportal/v3/applications/896658a0-b4ee-4535-bbfa-806c894a4015/generate-sdk"'
/applications/{applicationId}/generate-sdk/{language}:
post:
tags:
- SDK Generation
summary: Generate a single SDK for multiple APIs and optionally generate application code
description: |
Retrieve Swagger definitions for the provided API IDs and generate SDKs.
Optionally generate application code if use case is provided.
parameters:
- $ref: '#/components/parameters/applicationId'
- $ref: '#/components/parameters/languagePath'
requestBody:
description: |
Object containing the list of API IDs for which Swagger definitions need to be retrieved.
Optionally, a use case description can be provided.
content:
application/json:
schema:
$ref: '#/components/schemas/SDKGenerationRequest'
responses:
200:
description: |
OK.
SDK generated successfully.
content:
application/zip:
schema:
type: string
format: byte
400:
$ref: '#/components/responses/BadRequest'
404:
$ref: '#/components/responses/NotFound'
500:
$ref: '#/components/responses/InternalServerError'
security:
- OAuth2Security:
- apim:subscribe
- apim:app_manage
x-code-samples:
- lang: Curl
source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8"
-H "Content-Type: application/json" -X POST -d @data.json "https://localhost:9443/api/am/devportal/v3/applications/896658a0-b4ee-4535-bbfa-806c894a4015/generate-sdk"'
🤖 Prompt for AI Agents
In
components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml
around lines 1761 to 1812, the language path parameter is defined inline, but
there is already a reusable language parameter defined as a query parameter
which should not be reused for path parameters. To fix this, define a new
reusable parameter named languagePath under components.parameters with in: path
and an enum of supported SDK languages, then replace the inline language
parameter in the /applications/{applicationId}/generate-sdk/{language} post
operation with a $ref to this new languagePath parameter.

Comment on lines 1049 to 1091
private String retrieveApplicationCode (String apiSpecification, String sdkMethodsFile, String useCase, String language) throws APIManagementException {
APIManagerConfiguration configuration = ServiceReferenceHolder.
getInstance().getAPIManagerConfigurationService().getAPIManagerConfiguration();

if (configuration == null) {
log.error("API Manager configuration is not initialized.");
} else {
configDto = configuration.getSdkGenerationConfigurationDTO();
}
try {
if (configDto.isKeyProvided() || configDto.isAuthTokenProvided()) {
JSONObject payload = new JSONObject();

payload.put(SPECIFICATION, apiSpecification);
payload.put(METHODSFILE, sdkMethodsFile);
payload.put(USECASE, useCase);
payload.put(LANGUAGE, language);

String response;
if (configDto.isKeyProvided()) {
response = APIUtil.invokeAIService(configDto.getEndpoint(), configDto.getTokenEndpoint(),
configDto.getKey(), configDto.getGenerateCodeResource(), payload.toString(), null);

} else {
response = APIUtil.invokeAIService(configDto.getEndpoint(), null,
configDto.getAccessToken(), configDto.getGenerateCodeResource(), payload.toString(), null);

}
return response;
}
} catch (APIManagementException e) {
if (RestApiUtil.isDueToAIServiceNotAccessible(e)) {
throw new APIManagementException(e.getMessage(), e);
} else if (RestApiUtil.isDueToAIServiceThrottled(e)) {
throw new APIManagementException(e.getMessage(), e);
} else {
String errorMessage = "Error encountered while executing the SDK Generation service for generating application code";
log.error(errorMessage, e);
throw new APIManagementException(errorMessage, e);
}
}
return null;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider reducing code duplication with retrieveMergedAPISpec method.

This method shares significant structure and logic with retrieveMergedAPISpec. The configuration retrieval and AI service invocation patterns are nearly identical.

Consider extracting common AI service invocation logic:

private String invokeAIService(String resourcePath, JSONObject payload) throws APIManagementException {
    // Common configuration retrieval and AI service call logic
}

This would reduce duplication and improve maintainability.

🤖 Prompt for AI Agents
In
components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest.api.store.v1.impl/ApplicationsApiServiceImpl.java
around lines 1049 to 1091, the retrieveApplicationCode method duplicates
configuration retrieval and AI service invocation logic found in
retrieveMergedAPISpec. To fix this, extract the common logic of fetching
configuration and invoking the AI service into a new private method, for example
invokeAIService, which accepts the resource path and payload as parameters. Then
refactor retrieveApplicationCode and retrieveMergedAPISpec to call this new
method, passing the appropriate arguments, thereby reducing code duplication and
improving maintainability.

Comment on lines 86 to 93
private static SDKGenerationConfigurationDTO configDto;
public static final String SPECIFICATIONS = "specifications";
public static final String APICONTEXTS = "contexts";
public static final String SPECIFICATION = "APISpecification";
public static final String METHODSFILE = "sdkMethodsFile";
public static final String USECASE = "useCase";
public static final String LANGUAGE = "language";

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Address thread safety concern with static configDto field.

The static configDto field is reassigned in multiple methods (retrieveMergedAPISpec and retrieveApplicationCode) without synchronization, which can cause thread safety issues in a multi-threaded environment.

Consider one of these solutions:

-    private static SDKGenerationConfigurationDTO configDto;
+    // Remove static field and get config locally in each method

Or use proper synchronization:

-    private static SDKGenerationConfigurationDTO configDto;
+    private static volatile SDKGenerationConfigurationDTO configDto;
+    private static final Object CONFIG_LOCK = new Object();

Then synchronize access in the methods where it's assigned.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private static SDKGenerationConfigurationDTO configDto;
public static final String SPECIFICATIONS = "specifications";
public static final String APICONTEXTS = "contexts";
public static final String SPECIFICATION = "APISpecification";
public static final String METHODSFILE = "sdkMethodsFile";
public static final String USECASE = "useCase";
public static final String LANGUAGE = "language";
private static volatile SDKGenerationConfigurationDTO configDto;
private static final Object CONFIG_LOCK = new Object();
public static final String SPECIFICATIONS = "specifications";
public static final String APICONTEXTS = "contexts";
public static final String SPECIFICATION = "APISpecification";
public static final String METHODSFILE = "sdkMethodsFile";
public static final String USECASE = "useCase";
public static final String LANGUAGE = "language";
🤖 Prompt for AI Agents
In
components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java
around lines 86 to 93, the static field configDto is reassigned in multiple
methods without synchronization, causing thread safety issues. To fix this,
either remove the static modifier if shared state is not required, or make
configDto access thread-safe by synchronizing all reads and writes to it, for
example by using synchronized blocks or methods around assignments and usages in
retrieveMergedAPISpec and retrieveApplicationCode methods.

wso2-jenkins-bot and others added 28 commits May 29, 2025 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants