-
Notifications
You must be signed in to change notification settings - Fork 649
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
base: ai-sdk-generator
Are you sure you want to change the base?
Add REST API resource for AI-assisted SDK generation with Application Code Generation #13121
Conversation
…y generate application code
…ptionally handle generating code if use case is provided
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 📝 WalkthroughWalkthroughThis 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
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
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
Documentation and Community
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this 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
: SimplifyAPIIdsList
for request payloads
TheAPIIdsList
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 ofAPIId
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
⛔ 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 inAPIManagerConfiguration
, DTO mappings, and the JAX-RS@Path
annotations of the new SDK generation endpoints. Please verify that:
APIManagerConfiguration
parses these new keys.- The DTOs and service implementation reference these constants (e.g.,
SDK_GENERATION_MERGE_SPEC_RESOURCE
).- 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 byAPIManagerConfiguration
and populated intoSDKGenerationConfigurationDTO
.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 likeAPIChat
,MarketplaceAssistant
, andDesignAssistant
. 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
andauthTokenProvided
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.
/** | ||
* This class represent the Marketplace Assistant configuration DTO. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
/** | |
* 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.
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: |
There was a problem hiding this comment.
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.
/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"' | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
- Under
components.parameters
, addlanguagePath
. - In the
post
operation for/applications/{applicationId}/generate-sdk/{language}
, replace the inlinelanguage
block with a$ref
tolanguagePath
.
- Under
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.
/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.
...onents/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml
Outdated
Show resolved
Hide resolved
...onents/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml
Outdated
Show resolved
Hide resolved
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; | ||
} |
There was a problem hiding this comment.
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.
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"; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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.
…t development iteration
…t development iteration
…t development iteration
…t development iteration
…t development iteration
…t development iteration
…t development iteration
…stants to APIConstants
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: