Feature - In-Flow Extensions REST API support#1101
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (7)
📝 WalkthroughSummaryThis pull request adds comprehensive REST API support for In-Flow Extension actions, enabling external service invocation during flow execution. The changes introduce new API endpoints, models, and mappers to manage in-flow extension configurations. New API Models and Response ClassesAdded dedicated API model classes for in-flow extension configuration:
Action Management REST API Enhancements
Mapper and Service Integration
Flow Management Service Enhancements
OpenAPI Specification Updates
Configuration and Dependencies
Validation and Error Handling
WalkthroughThis pull request adds support for in-flow extensions—external service invocations during identity flow execution—addressing use cases such as risk assessment, data enrichment, and external verification. The implementation spans two coordinated layers: action management API (defining in-flow extension action types) and flow management API (exposing extension lifecycle operations). New API models define access configuration (expose/modify lists) and encryption settings. The action management service validates action types, rejects status toggles for extensions, and deserializes extension payloads. A dedicated mapper converts between API and engine representations. Flow management wires in action management, exposes REST endpoints for creating, listing, updating, and deleting extensions, enriches flow metadata with active extension connections, and provides context-tree metadata for flow composition UI. OpenAPI specs document all new endpoints and schemas. Sequence Diagram(s) sequenceDiagram
participant Client
participant FlowApiServiceImpl
participant ServerFlowMgtService
participant ActionManagementService
participant InFlowExtensionMapper
participant InFlowExtensionContextTreeService
Client->>FlowApiServiceImpl: POST /flow/in-flow-extensions (create)
FlowApiServiceImpl->>ServerFlowMgtService: createInFlowExtension(model)
ServerFlowMgtService->>InFlowExtensionMapper: toInFlowExtensionAction(model)
ServerFlowMgtService->>ActionManagementService: create(action, tenantDomain)
ActionManagementService-->>ServerFlowMgtService: created Action (id)
ServerFlowMgtService-->>FlowApiServiceImpl: InFlowExtensionResponse
FlowApiServiceImpl-->>Client: 201 Created (Location: /flow/in-flow-extensions/{id})
Client->>FlowApiServiceImpl: GET /flow/in-flow-extension/context-tree?flowType=...
FlowApiServiceImpl->>ServerFlowMgtService: getInFlowExtensionContextTree(flowType)
ServerFlowMgtService->>InFlowExtensionContextTreeService: buildContextTree(flowType)
InFlowExtensionContextTreeService-->>ServerFlowMgtService: InFlowExtensionContextTreeMetadata
ServerFlowMgtService->>InFlowExtensionMapper: (n/a) / InFlowExtensionContextTreeMapper
ServerFlowMgtService-->>FlowApiServiceImpl: InFlowExtensionContextTreeResponse
FlowApiServiceImpl-->>Client: 200 OK
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
|
||
| public AccessConfigModel expose(List<Object> expose) { | ||
|
|
||
| this.expose = expose; |
There was a problem hiding this comment.
Log Improvement Suggestion No: 1
| public AccessConfigModel expose(List<Object> expose) { | |
| this.expose = expose; | |
| public AccessConfigModel expose(List<Object> expose) { | |
| this.expose = expose; | |
| if (log.isDebugEnabled()) { | |
| log.debug("Setting expose configuration with " + (expose != null ? expose.size() : 0) + " paths"); | |
| } | |
| return this; |
| } | ||
|
|
||
| public AccessConfigModel modify(List<Object> modify) { | ||
|
|
||
| this.modify = modify; |
There was a problem hiding this comment.
Log Improvement Suggestion No: 2
| } | |
| public AccessConfigModel modify(List<Object> modify) { | |
| this.modify = modify; | |
| public AccessConfigModel modify(List<Object> modify) { | |
| this.modify = modify; | |
| if (log.isDebugEnabled()) { | |
| log.debug("Setting modify configuration with " + (modify != null ? modify.size() : 0) + " paths"); | |
| } | |
| return this; |
|
|
||
| public void setCertificate(String certificate) { | ||
|
|
||
| this.certificate = certificate; | ||
| } |
There was a problem hiding this comment.
Log Improvement Suggestion No: 3
| public void setCertificate(String certificate) { | |
| this.certificate = certificate; | |
| } | |
| public void setCertificate(String certificate) { | |
| if (certificate != null && !certificate.trim().isEmpty()) { | |
| log.debug("Setting encryption certificate for external service"); | |
| } | |
| this.certificate = certificate; | |
| } |
|
|
||
| public InFlowExtensionActionModel(ActionModel actionModel) { | ||
|
|
||
| setName(actionModel.getName()); | ||
| setDescription(actionModel.getDescription()); | ||
| setEndpoint(actionModel.getEndpoint()); | ||
| setRule(actionModel.getRule()); | ||
| } |
There was a problem hiding this comment.
Log Improvement Suggestion No: 4
| public InFlowExtensionActionModel(ActionModel actionModel) { | |
| setName(actionModel.getName()); | |
| setDescription(actionModel.getDescription()); | |
| setEndpoint(actionModel.getEndpoint()); | |
| setRule(actionModel.getRule()); | |
| } | |
| public InFlowExtensionActionModel(ActionModel actionModel) { | |
| log.debug("Initializing InFlowExtensionActionModel from ActionModel"); | |
| setName(actionModel.getName()); | |
| setDescription(actionModel.getDescription()); | |
| setEndpoint(actionModel.getEndpoint()); | |
| setRule(actionModel.getRule()); | |
| } |
|
|
||
| public InFlowExtensionActionResponse(ActionResponse actionResponse) { | ||
|
|
||
| setId(actionResponse.getId()); |
There was a problem hiding this comment.
Log Improvement Suggestion No: 5
| public InFlowExtensionActionResponse(ActionResponse actionResponse) { | |
| setId(actionResponse.getId()); | |
| public InFlowExtensionActionResponse(ActionResponse actionResponse) { | |
| log.debug("Creating InFlowExtensionActionResponse from ActionResponse with id: {}", actionResponse.getId()); | |
| setId(actionResponse.getId()); |
|
|
||
| public void setAccessConfig(AccessConfigModel accessConfig) { | ||
|
|
||
| this.accessConfig = accessConfig; |
There was a problem hiding this comment.
Log Improvement Suggestion No: 6
| public void setAccessConfig(AccessConfigModel accessConfig) { | |
| this.accessConfig = accessConfig; | |
| public void setAccessConfig(AccessConfigModel accessConfig) { | |
| if (log.isDebugEnabled()) { | |
| log.debug("Setting access config for action: {}", this.getId()); | |
| } | |
| this.accessConfig = accessConfig; |
| public ActionBasicResponse activateAction(String actionType, String actionId) { | ||
|
|
||
| try { |
There was a problem hiding this comment.
Log Improvement Suggestion No: 7
| public ActionBasicResponse activateAction(String actionType, String actionId) { | |
| try { | |
| public ActionBasicResponse activateAction(String actionType, String actionId) { | |
| try { | |
| log.info("Activating action with id: " + actionId + " of type: " + actionType); |
| public ActionNameCheckResponse checkActionName(String actionType, String name) { | ||
|
|
||
| try { |
There was a problem hiding this comment.
Log Improvement Suggestion No: 8
| public ActionNameCheckResponse checkActionName(String actionType, String name) { | |
| try { | |
| public ActionNameCheckResponse checkActionName(String actionType, String name) { | |
| try { | |
| if (log.isDebugEnabled()) { | |
| log.debug("Checking availability of action name: " + name + " for type: " + actionType); | |
| } |
| @Override | ||
| public Response checkActionName(String actionType, ActionNameCheckRequest actionNameCheckRequest) { | ||
|
|
There was a problem hiding this comment.
Log Improvement Suggestion No: 9
| @Override | |
| public Response checkActionName(String actionType, ActionNameCheckRequest actionNameCheckRequest) { | |
| @Override | |
| public Response checkActionName(String actionType, ActionNameCheckRequest actionNameCheckRequest) { | |
| log.debug("Checking action name availability for action type: {} with name: {}", actionType, actionNameCheckRequest.getName()); |
| case IN_FLOW_EXTENSION: | ||
| actionMapper = new InFlowExtensionActionMapper(); | ||
| break; |
There was a problem hiding this comment.
Log Improvement Suggestion No: 10
| case IN_FLOW_EXTENSION: | |
| actionMapper = new InFlowExtensionActionMapper(); | |
| break; | |
| case PRE_ISSUE_ID_TOKEN: | |
| actionMapper = new PreIssueIDTokenActionMapper(); | |
| break; | |
| case IN_FLOW_EXTENSION: | |
| actionMapper = new InFlowExtensionActionMapper(); | |
| log.info("Created InFlowExtensionActionMapper for action type: IN_FLOW_EXTENSION"); | |
| break; |
| @Override | ||
| public Action toAction(ActionModel actionModel) throws ActionMgtException { | ||
|
|
||
| if (!(actionModel instanceof InFlowExtensionActionModel)) { |
There was a problem hiding this comment.
Log Improvement Suggestion No: 11
| @Override | |
| public Action toAction(ActionModel actionModel) throws ActionMgtException { | |
| if (!(actionModel instanceof InFlowExtensionActionModel)) { | |
| public Action toAction(ActionModel actionModel) throws ActionMgtException { | |
| log.info("Converting ActionModel to Action for type: " + getSupportedActionType()); | |
| if (!(actionModel instanceof InFlowExtensionActionModel)) { |
| @SuppressWarnings("unchecked") | ||
| private AccessConfig toAccessConfig(AccessConfigModel configModel) { | ||
|
|
||
| if (configModel == null) { |
There was a problem hiding this comment.
Log Improvement Suggestion No: 12
| @SuppressWarnings("unchecked") | |
| private AccessConfig toAccessConfig(AccessConfigModel configModel) { | |
| if (configModel == null) { | |
| private AccessConfig toAccessConfig(AccessConfigModel configModel) { | |
| if (log.isDebugEnabled()) { | |
| log.debug("Converting AccessConfigModel to AccessConfig"); | |
| } | |
| if (configModel == null) { |
| supportedExecutors.add(EXTENSION_EXECUTOR); | ||
| return supportedExecutors; |
There was a problem hiding this comment.
Log Improvement Suggestion No: 14
| supportedExecutors.add(EXTENSION_EXECUTOR); | |
| return supportedExecutors; | |
| supportedExecutors.add(EXTENSION_EXECUTOR); | |
| if (log.isDebugEnabled()) { | |
| log.debug("Total supported executors count: " + supportedExecutors.size()); | |
| } | |
| return supportedExecutors; |
There was a problem hiding this comment.
AI Agent Log Improvement Checklist
- The log-related comments and suggestions in this review were generated by an AI tool to assist with identifying potential improvements. Purpose of reviewing the code for log improvements is to improve the troubleshooting capabilities of our products.
- Please make sure to manually review and validate all suggestions before applying any changes. Not every code suggestion would make sense or add value to our purpose. Therefore, you have the freedom to decide which of the suggestions are helpful.
✅ Before merging this pull request:
- Review all AI-generated comments for accuracy and relevance.
- Complete and verify the table below. We need your feedback to measure the accuracy of these suggestions and the value they add. If you are rejecting a certain code suggestion, please mention the reason briefly in the suggestion for us to capture it.
…capability for use in editing in-flow extension actions.
There was a problem hiding this comment.
Need to revert this
| - type: IN_FLOW_EXTENSION | ||
| displayName: In-Flow Extension | ||
| description: This action invokes during flow execution. | ||
| count: 1 |
| header: x-api-key | ||
| value: e12595c1-1435-4bf2-94e8-445135ab505a | ||
| type: API_KEY | ||
| accessConfig: |
There was a problem hiding this comment.
Should be changed: no raw paths are allowed. {"path": String, "encrypted": Boolean} pattern required.
| id: 24f64d17-9824-4e28-8413-de45728d8e84 | ||
| name: Risk Assessment Extension | ||
| description: This action invokes during flow execution to assess risk. | ||
| status: INACTIVE |
There was a problem hiding this comment.
ACTIVE by default
| required: true | ||
| schema: | ||
| enum: | ||
| - preIssueAccessToken |
There was a problem hiding this comment.
Name uniqueness check is not needed for all the actions
flow.execution from the action.management= flow.execution and action.management from flow.managemnt
…n-mgt-to-flow-mgt-migration
…low-mgt-migration Inflow extension/action mgt to flow mgt migration
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (1)
components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/core/ServerFlowMgtService.java (1)
375-380: ⚡ Quick winPrefer service-level name-availability API over full in-memory scan.
This local scan works functionally, but using the action-management availability API keeps behavior consistent across layers and avoids loading all actions for each check.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/core/ServerFlowMgtService.java` around lines 375 - 380, The code performs an in-memory scan by calling actionManagementService.getActionsByActionType(...) and filtering to determine name availability; replace that with the action-management service's name-availability API to avoid loading all actions. Call the appropriate availability method on actionManagementService (e.g., an isActionNameAvailable / isNameAvailable style API) passing IN_FLOW_EXTENSION_ACTION_TYPE, request.getName(), tenantDomain and excludeId (or equivalent parameters), and use its boolean result to build and return the InFlowExtensionNameCheckResponse.available(...) instead of performing the stream/filter/noneMatch logic locally.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/extend/java/org/wso2/carbon/identity/api/server/action/management/v1/InFlowExtensionActionResponse.java`:
- Around line 139-156: The equals/hashCode implementation in
InFlowExtensionActionResponse omits the copied metadata fields version,
createdAt, and updatedAt, so add comparisons for these in equals (e.g.,
Objects.equals(this.getVersion(), that.getVersion()),
Objects.equals(this.getCreatedAt(), that.getCreatedAt()),
Objects.equals(this.getUpdatedAt(), that.getUpdatedAt())) and include
getVersion(), getCreatedAt(), getUpdatedAt() in the Objects.hash(...) call in
hashCode so the metadata is considered when determining equality and computing
the hash.
In
`@components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/main/java/org/wso2/carbon/identity/api/server/action/management/v1/core/ServerActionManagementService.java`:
- Around line 172-185: The checkActionName method currently returns a hardcoded
available=true; restore the real evaluation by calling
actionManagementService.isActionNameAvailable(...) and set the
ActionNameCheckResponse based on that boolean. Use
validateActionType(actionType) and obtain tenantDomain from CarbonContext as
already done, then if excludeId is non-blank call
actionManagementService.isActionNameAvailable(actionType, name, excludeId,
tenantDomain) else call
actionManagementService.isActionNameAvailable(actionType, name, tenantDomain);
finally return new ActionNameCheckResponse().available(available) and preserve
the existing ActionMgtException catch behavior.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/pom.xml`:
- Around line 145-149: The pom declares jakarta.xml.bind-api 4.0.4 which
requires Java 11+, causing Java 8 build failures and mixed javax/jakarta
annotations (see InFlowExtensionBasicResponse.java); replace the compile-scope
Jakarta 4.x dependency with a Java 8-compatible JAXB API (e.g.,
javax.xml.bind:jaxb-api:2.3.1) and, if needed, add matching runtime impl (e.g.,
com.sun.xml.bind:jaxb-impl) and/or adjust the jaxb plugin config so generated
sources consistently use javax.xml.bind annotations; update the dependency entry
in the POM and regenerate the JAXB classes (or reconfigure the codegen plugin)
to ensure InFlowExtensionBasicResponse and other generated classes all import
javax.xml.bind.annotation.*.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/core/ServerFlowMgtService.java`:
- Around line 312-317: The method in ServerFlowMgtService that calls
actionManagementService.getActionByActionId (using
IN_FLOW_EXTENSION_ACTION_TYPE, extensionId, tenantDomain) must guard against a
null return before calling InFlowExtensionMapper.toInFlowExtensionResponse; if
getActionByActionId returns null, return/throw the API not-found error response
instead of proceeding. Add a null check for the Action named "action" after the
call and produce the proper 404 API error (consistent with other endpoints)
rather than mapping a null value; preserve the existing ActionMgtException catch
block.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/utils/InFlowExtensionMapper.java`:
- Around line 307-308: In getRequiredStringProp within InFlowExtensionMapper,
avoid directly casting props.get(key) to String; instead retrieve the Object,
validate it is an instance of String, and if not throw a controlled client error
(bad request) with a clear message about the expected string type for that key;
then cast to String and continue the existing empty-check (StringUtils.isEmpty).
This prevents ClassCastException for non-string inputs and returns a predictable
error to the client.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/resources/flow.yaml`:
- Around line 439-484: There are two identical path entries for
"/flow/in-flow-extension/context-tree" which breaks the OpenAPI YAML; remove the
duplicate block and keep a single definition for the path (preserve the
operationId getInFlowExtensionContextTree, the parameters (flowType) and all
responses), ensuring only one "/flow/in-flow-extension/context-tree" entry
remains in the paths mapping.
- Around line 1306-1308: The YAML schema is inconsistent: redirectionEnabled's
description claims REDIRECT is advertised in allowedOperations but the
allowedOperations enum only lists EXPOSE and MODIFY; update the contract by
either adding REDIRECT to the allowedOperations enum values (so
allowedOperations includes REDIRECT alongside EXPOSE and MODIFY) or by changing
redirectionEnabled's description to reflect the actual enum (e.g., state that it
toggles whether REDIRECT-related behavior is implied but is represented via
EXPOSE/MODIFY), and make the same change for the second occurrence of
redirectionEnabled/allowedOperations in the file (the other node with the same
schema).
- Around line 1295-1298: The schema for the property named flowType in flow.yaml
currently declares type: string but the description states it may be null;
update the schema to make it consistent by adding nullable: true to the flowType
definition (or alternatively update the description to document the concrete
fallback value the API returns), and ensure the example and any generated
models/clients reflect the nullable change; locate the flowType node in
flow.yaml and add nullable: true (or adjust the description/example) so the
OpenAPI contract matches the actual behavior.
- Around line 223-228: The 201 response for the create endpoint in flow.yaml
documents only the response body (InFlowExtensionResponse) but omits the
Location header; update the '201' response object for "In-Flow Extension
Created" to include a Location header entry (type: string, format: uri,
description: "URI of the created resource") so the OpenAPI contract reflects the
endpoint behavior returning the created resource URI; locate the '201' response
block referencing InFlowExtensionResponse and add a headers -> Location
definition alongside the existing content.
---
Nitpick comments:
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/core/ServerFlowMgtService.java`:
- Around line 375-380: The code performs an in-memory scan by calling
actionManagementService.getActionsByActionType(...) and filtering to determine
name availability; replace that with the action-management service's
name-availability API to avoid loading all actions. Call the appropriate
availability method on actionManagementService (e.g., an isActionNameAvailable /
isNameAvailable style API) passing IN_FLOW_EXTENSION_ACTION_TYPE,
request.getName(), tenantDomain and excludeId (or equivalent parameters), and
use its boolean result to build and return the
InFlowExtensionNameCheckResponse.available(...) instead of performing the
stream/filter/noneMatch logic locally.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 30778edd-bef6-4301-8a42-57bde4035a3c
⛔ Files ignored due to path filters (27)
components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/action/management/v1/ActionNameCheckRequest.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/action/management/v1/ActionNameCheckResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/action/management/v1/ActionType.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/action/management/v1/ActionsApi.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/action/management/v1/ActionsApiService.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/action/management/v1/factories/ActionsApiServiceFactory.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/AccessConfig.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/AuthenticationType.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/AuthenticationTypeResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/ContextPath.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/Encryption.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/Endpoint.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/EndpointResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/EndpointUpdateModel.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/FlowApi.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/FlowApiService.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/FlowMetaResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionBasicResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionConnectionInfo.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionContextTreeNode.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionContextTreeResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionModel.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionNameCheckRequest.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionNameCheckResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionUpdateModel.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/Link.javais excluded by!**/gen/**
📒 Files selected for processing (25)
components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/pom.xmlcomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/extend/java/org/wso2/carbon/identity/api/server/action/management/v1/AccessConfigModel.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/extend/java/org/wso2/carbon/identity/api/server/action/management/v1/EncryptionModel.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/extend/java/org/wso2/carbon/identity/api/server/action/management/v1/InFlowExtensionActionModel.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/extend/java/org/wso2/carbon/identity/api/server/action/management/v1/InFlowExtensionActionResponse.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/extend/java/org/wso2/carbon/identity/api/server/action/management/v1/InFlowExtensionActionUpdateModel.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/extend/java/org/wso2/carbon/identity/api/server/action/management/v1/InFlowExtensionBasicResponse.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/main/java/org/wso2/carbon/identity/api/server/action/management/v1/core/ServerActionManagementService.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/main/java/org/wso2/carbon/identity/api/server/action/management/v1/impl/ActionsApiServiceImpl.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/main/java/org/wso2/carbon/identity/api/server/action/management/v1/mapper/ActionMapperFactory.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/main/java/org/wso2/carbon/identity/api/server/action/management/v1/mapper/InFlowExtensionActionMapper.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/main/java/org/wso2/carbon/identity/api/server/action/management/v1/util/ActionDeserializer.javacomponents/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/main/resources/Actions.yamlcomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.common/src/main/java/org/wso2/carbon/identity/api/server/flow/management/common/FlowMgtServiceHolder.javacomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/pom.xmlcomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/constants/FlowEndpointConstants.javacomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/core/ServerFlowMgtService.javacomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/factories/ServerFlowMgtServiceFactory.javacomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/impl/FlowApiServiceImpl.javacomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/response/handlers/AbstractMetaResponseHandler.javacomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/utils/InFlowExtensionContextTreeMapper.javacomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/utils/InFlowExtensionMapper.javacomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/utils/Utils.javacomponents/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/resources/flow.yamlpom.xml
| return Objects.equals(this.getId(), that.getId()) && | ||
| Objects.equals(this.getType(), that.getType()) && | ||
| Objects.equals(this.getName(), that.getName()) && | ||
| Objects.equals(this.getDescription(), that.getDescription()) && | ||
| Objects.equals(this.getStatus(), that.getStatus()) && | ||
| Objects.equals(this.getEndpoint(), that.getEndpoint()) && | ||
| Objects.equals(this.accessConfig, that.accessConfig) && | ||
| Objects.equals(this.encryption, that.encryption) && | ||
| Objects.equals(this.iconUrl, that.iconUrl) && | ||
| Objects.equals(this.flowTypeOverrides, that.flowTypeOverrides) && | ||
| Objects.equals(this.getRule(), that.getRule()); | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
|
|
||
| return Objects.hash(getId(), getType(), getName(), getDescription(), getStatus(), getEndpoint(), | ||
| accessConfig, encryption, iconUrl, flowTypeOverrides, getRule()); |
There was a problem hiding this comment.
Include copied metadata fields in equality/hashCode.
Line 47 to Line 49 copy version, createdAt, and updatedAt, but Line 139 and Line 155 exclude them from equals/hashCode. This can treat materially different responses as equal.
Proposed fix
- return Objects.equals(this.getId(), that.getId()) &&
+ return Objects.equals(this.getId(), that.getId()) &&
Objects.equals(this.getType(), that.getType()) &&
Objects.equals(this.getName(), that.getName()) &&
Objects.equals(this.getDescription(), that.getDescription()) &&
Objects.equals(this.getStatus(), that.getStatus()) &&
+ Objects.equals(this.getVersion(), that.getVersion()) &&
+ Objects.equals(this.getCreatedAt(), that.getCreatedAt()) &&
+ Objects.equals(this.getUpdatedAt(), that.getUpdatedAt()) &&
Objects.equals(this.getEndpoint(), that.getEndpoint()) &&
Objects.equals(this.accessConfig, that.accessConfig) &&
Objects.equals(this.encryption, that.encryption) &&
Objects.equals(this.iconUrl, that.iconUrl) &&
Objects.equals(this.flowTypeOverrides, that.flowTypeOverrides) &&
Objects.equals(this.getRule(), that.getRule());
@@
- return Objects.hash(getId(), getType(), getName(), getDescription(), getStatus(), getEndpoint(),
+ return Objects.hash(getId(), getType(), getName(), getDescription(), getStatus(), getVersion(),
+ getCreatedAt(), getUpdatedAt(), getEndpoint(),
accessConfig, encryption, iconUrl, flowTypeOverrides, getRule());📝 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.
| return Objects.equals(this.getId(), that.getId()) && | |
| Objects.equals(this.getType(), that.getType()) && | |
| Objects.equals(this.getName(), that.getName()) && | |
| Objects.equals(this.getDescription(), that.getDescription()) && | |
| Objects.equals(this.getStatus(), that.getStatus()) && | |
| Objects.equals(this.getEndpoint(), that.getEndpoint()) && | |
| Objects.equals(this.accessConfig, that.accessConfig) && | |
| Objects.equals(this.encryption, that.encryption) && | |
| Objects.equals(this.iconUrl, that.iconUrl) && | |
| Objects.equals(this.flowTypeOverrides, that.flowTypeOverrides) && | |
| Objects.equals(this.getRule(), that.getRule()); | |
| } | |
| @Override | |
| public int hashCode() { | |
| return Objects.hash(getId(), getType(), getName(), getDescription(), getStatus(), getEndpoint(), | |
| accessConfig, encryption, iconUrl, flowTypeOverrides, getRule()); | |
| return Objects.equals(this.getId(), that.getId()) && | |
| Objects.equals(this.getType(), that.getType()) && | |
| Objects.equals(this.getName(), that.getName()) && | |
| Objects.equals(this.getDescription(), that.getDescription()) && | |
| Objects.equals(this.getStatus(), that.getStatus()) && | |
| Objects.equals(this.getVersion(), that.getVersion()) && | |
| Objects.equals(this.getCreatedAt(), that.getCreatedAt()) && | |
| Objects.equals(this.getUpdatedAt(), that.getUpdatedAt()) && | |
| Objects.equals(this.getEndpoint(), that.getEndpoint()) && | |
| Objects.equals(this.accessConfig, that.accessConfig) && | |
| Objects.equals(this.encryption, that.encryption) && | |
| Objects.equals(this.iconUrl, that.iconUrl) && | |
| Objects.equals(this.flowTypeOverrides, that.flowTypeOverrides) && | |
| Objects.equals(this.getRule(), that.getRule()); | |
| } | |
| `@Override` | |
| public int hashCode() { | |
| return Objects.hash(getId(), getType(), getName(), getDescription(), getStatus(), getVersion(), | |
| getCreatedAt(), getUpdatedAt(), getEndpoint(), | |
| accessConfig, encryption, iconUrl, flowTypeOverrides, getRule()); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/extend/java/org/wso2/carbon/identity/api/server/action/management/v1/InFlowExtensionActionResponse.java`
around lines 139 - 156, The equals/hashCode implementation in
InFlowExtensionActionResponse omits the copied metadata fields version,
createdAt, and updatedAt, so add comparisons for these in equals (e.g.,
Objects.equals(this.getVersion(), that.getVersion()),
Objects.equals(this.getCreatedAt(), that.getCreatedAt()),
Objects.equals(this.getUpdatedAt(), that.getUpdatedAt())) and include
getVersion(), getCreatedAt(), getUpdatedAt() in the Objects.hash(...) call in
hashCode so the metadata is considered when determining equality and computing
the hash.
| public ActionNameCheckResponse checkActionName(String actionType, String name, String excludeId) { | ||
|
|
||
| try { | ||
| validateActionType(actionType); | ||
| String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); | ||
| boolean available; | ||
| // if (StringUtils.isNotBlank(excludeId)) { | ||
| // available = actionManagementService.isActionNameAvailable( | ||
| // actionType, name, excludeId, tenantDomain); | ||
| // } else { | ||
| // available = actionManagementService.isActionNameAvailable(actionType, name, tenantDomain); | ||
| // } | ||
| return new ActionNameCheckResponse().available(true); | ||
| } catch (ActionMgtException e) { |
There was a problem hiding this comment.
Restore real name-availability evaluation in checkActionName.
Line 184 currently hardcodes available=true, so the endpoint does not actually validate uniqueness. Please re-enable service-backed evaluation, including excludeId handling for update scenarios.
Proposed fix
public ActionNameCheckResponse checkActionName(String actionType, String name, String excludeId) {
try {
validateActionType(actionType);
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
- boolean available;
-// if (StringUtils.isNotBlank(excludeId)) {
-// available = actionManagementService.isActionNameAvailable(
-// actionType, name, excludeId, tenantDomain);
-// } else {
-// available = actionManagementService.isActionNameAvailable(actionType, name, tenantDomain);
-// }
- return new ActionNameCheckResponse().available(true);
+ boolean available;
+ if (excludeId != null && !excludeId.isEmpty()) {
+ available = actionManagementService.isActionNameAvailable(
+ actionType, name, excludeId, tenantDomain);
+ } else {
+ available = actionManagementService.isActionNameAvailable(actionType, name, tenantDomain);
+ }
+ return new ActionNameCheckResponse().available(available);
} catch (ActionMgtException e) {
throw ActionMgtEndpointUtil.handleActionMgtException(e);
}
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@components/org.wso2.carbon.identity.api.server.action.management/org.wso2.carbon.identity.api.server.action.management.v1/src/main/java/org/wso2/carbon/identity/api/server/action/management/v1/core/ServerActionManagementService.java`
around lines 172 - 185, The checkActionName method currently returns a hardcoded
available=true; restore the real evaluation by calling
actionManagementService.isActionNameAvailable(...) and set the
ActionNameCheckResponse based on that boolean. Use
validateActionType(actionType) and obtain tenantDomain from CarbonContext as
already done, then if excludeId is non-blank call
actionManagementService.isActionNameAvailable(actionType, name, excludeId,
tenantDomain) else call
actionManagementService.isActionNameAvailable(actionType, name, tenantDomain);
finally return new ActionNameCheckResponse().available(available) and preserve
the existing ActionMgtException catch behavior.
| <groupId>jakarta.xml.bind</groupId> | ||
| <artifactId>jakarta.xml.bind-api</artifactId> | ||
| <version>4.0.4</version> | ||
| <scope>compile</scope> | ||
| </dependency> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
MODULE_DIR="components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1"
echo "== JAXB imports used by flow management v1 sources =="
rg -n --no-heading 'javax\.xml\.bind|jakarta\.xml\.bind' "${MODULE_DIR}/src" || true
echo
echo "== JAXB-related dependency declarations in module POM =="
rg -n --no-heading 'jakarta.xml.bind-api|jaxb-api|<source>|<target>' "${MODULE_DIR}/pom.xml"
echo
echo "== JAXB-related dependency management entries in root pom.xml =="
rg -n --no-heading 'jakarta.xml.bind-api|jaxb-api|version.org.wso2.orbit.javax.xml.bind' pom.xmlRepository: wso2/identity-api-server
Length of output: 5747
🏁 Script executed:
#!/bin/bash
set -euo pipefail
MODULE_DIR="components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1"
POM="${MODULE_DIR}/pom.xml"
echo "== Module pom.xml: inspect jakarta.xml.bind-api dependency block =="
# Print around the matched artifactId line
line=$(rg -n 'artifactId>\s*jakarta\.xml\.bind-api\s*<' "$POM" | head -n1 | cut -d: -f1)
start=$((line-6)); end=$((line+12))
sed -n "${start},${end}p" "$POM" | nl -ba -w2 -s':'
echo
echo "== Module pom.xml: compiler source/target + relevant plugins =="
# show around source/target
for patt in '<source>1.8</source>' '<target>1.8</target>'; do
l=$(rg -n "$patt" "$POM" | head -n1 | cut -d: -f1)
s=$((l-6)); e=$((l+6))
echo "--- around $patt (line $l) ---"
sed -n "${s},${e}p" "$POM" | nl -ba -w2 -s':'
done
echo
echo "== Generated source: inspect InFlowExtensionBasicResponse.java for jakarta vs javax usage =="
FILE="${MODULE_DIR}/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionBasicResponse.java"
if [ -f "$FILE" ]; then
# show around first jakarta.xml.bind.annotation usage
lj=$(rg -n 'jakarta\.xml\.bind\.annotation' "$FILE" | head -n1 | cut -d: -f1 || true)
lu=$(rg -n 'javax\.xml\.bind\.annotation' "$FILE" | head -n1 | cut -d: -f1 || true)
echo "First jakarta.xml.bind.annotation line: ${lj:-none}"
echo "First javax.xml.bind.annotation line: ${lu:-none}"
# print a focused window around jakarta usage if present; otherwise around imports
if [ -n "${lj:-}" ]; then
s=$((lj-15)); e=$((lj+25))
else
# fallback to imports region
s=1; e=120
fi
sed -n "${s},${e}p" "$FILE" | nl -ba -w2 -s':'
else
echo "File not found: $FILE"
fi
echo
echo "== Module src/gen/java: confirm overall JAXB namespace mix =="
rg -n --no-heading 'javax\.xml\.bind' "${MODULE_DIR}/src/gen/java" | head -n20
rg -n --no-heading 'jakarta\.xml\.bind' "${MODULE_DIR}/src/gen/java" | head -n20Repository: wso2/identity-api-server
Length of output: 198
🏁 Script executed:
#!/bin/bash
set -euo pipefail
MODULE_DIR="components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1"
POM="${MODULE_DIR}/pom.xml"
FILE="${MODULE_DIR}/src/gen/java/org/wso2/carbon/identity/api/server/flow/management/v1/InFlowExtensionBasicResponse.java"
echo "== Module pom.xml: inspect jakarta.xml.bind-api dependency block =="
line=$(rg -n 'artifactId>\s*jakarta\.xml\.bind-api\s*<' "$POM" | head -n1 | cut -d: -f1 || true)
if [ -z "${line}" ]; then
echo "Could not find jakarta.xml.bind-api in $POM"
else
start=$((line-8)); end=$((line+14))
echo "--- around line ${line} (artifactId jakarta.xml.bind-api) ---"
sed -n "${start},${end}p" "$POM"
fi
echo
echo "== Module pom.xml: compiler source/target entries =="
for patt in '<source>1.8</source>' '<target>1.8</target>'; do
l=$(rg -n "$patt" "$POM" | head -n1 | cut -d: -f1 || true)
if [ -n "$l" ]; then
s=$((l-6)); e=$((l+6))
echo "--- around $patt (line $l) ---"
sed -n "${s},${e}p" "$POM"
else
echo "No match for $patt"
fi
done
echo
echo "== Generated source: InFlowExtensionBasicResponse.java JAXB namespace usage =="
if [ -f "$FILE" ]; then
echo "-- first import/annotation occurrences (jakarta vs javax) --"
echo "jakarta.xml.bind.annotation:"
rg -n 'jakarta\.xml\.bind\.annotation' "$FILE" | head -n20 || true
echo "javax.xml.bind.annotation:"
rg -n 'javax\.xml\.bind\.annotation' "$FILE" | head -n20 || true
echo
echo "-- imports region (first ~120 lines) --"
sed -n '1,120p' "$FILE" | cat
else
echo "File not found: $FILE"
fi
echo
echo "== Quick overall JAXB namespace mix in module src/gen/java (top 20 each) =="
echo "javax.xml.bind:"
rg -n --no-heading 'javax\.xml\.bind' "${MODULE_DIR}/src/gen/java" | head -n20 || true
echo "jakarta.xml.bind:"
rg -n --no-heading 'jakarta\.xml\.bind' "${MODULE_DIR}/src/gen/java" | head -n20 || true
echo
echo "== Root pom.xml: check version.org.wso2.orbit.javax.xml.bind occurrences =="
rg -n --no-heading 'version\.org\.wso2\.orbit\.javax\.xml\.bind|artifactId>\s*jaxb-api\s*<' pom.xml | head -n50 || trueRepository: wso2/identity-api-server
Length of output: 11461
🏁 Script executed:
#!/bin/bash
set -euo pipefail
MODULE_DIR="components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1"
POM="${MODULE_DIR}/pom.xml"
echo "== Search for javax/jaxb-related dependencies in module pom.xml =="
rg -n --no-heading 'jaxb-api|javax\.xml\.bind|jakarta\.xml\.bind|xjc|maven-jaxb|jaxws|JAXB' "$POM" || true
echo
echo "== Search for dependencyManagement JAXB entries in module pom.xml (if any) =="
rg -n --no-heading '<dependencyManagement>|<dependencies>' "$POM" || true
echo
echo "== List all dependencies that mention xml.bind =="
rg -n --no-heading 'xml\.bind' "$POM" || trueRepository: wso2/identity-api-server
Length of output: 593
🌐 Web query:
Does jakarta.xml.bind-api 4.0.4 require Java 11+ (or another minimum) / is it compatible with Java 8 for compilation?
💡 Result:
The jakarta.xml.bind-api version 4.0.4 requires Java SE 11 or higher [1]. It is not compatible with Java 8 for compilation or execution, as the Jakarta XML Binding 4.x specifications and the associated Eclipse Implementation of JAXB explicitly mandate a minimum of Java SE 11 [2][1]. For projects still restricted to Java 8, you would need to use earlier versions of the JAXB API that support that environment, such as those within the 2.3.x release line [3].
Citations:
- 1: https://eclipse-ee4j.github.io/jaxb-ri/4.0.5/docs/ch02.html
- 2: https://jakarta.ee/specifications/xml-binding/4.0/
- 3: https://eclipse-ee4j.github.io/jaxb-ri/4.0.3/docs/ch02.html
Fix JAXB tooling/namespace mismatch for Java 8 builds
- This module targets Java 8 (
maven-compiler-pluginsource/target1.8) but declaresjakarta.xml.bind:jakarta.xml.bind-api:4.0.4(compilescope); JAXB 4.x requires Java SE 11+, so Java 8 builds will fail. - The generated sources mix namespaces: most classes import
javax.xml.bind.annotation.*, whileInFlowExtensionBasicResponse.javaalso uses@jakarta.xml.bind.annotation.XmlType(...); align the dependency and generated annotations to be consistentlyjavax.*or consistentlyjakarta.*.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/pom.xml`
around lines 145 - 149, The pom declares jakarta.xml.bind-api 4.0.4 which
requires Java 11+, causing Java 8 build failures and mixed javax/jakarta
annotations (see InFlowExtensionBasicResponse.java); replace the compile-scope
Jakarta 4.x dependency with a Java 8-compatible JAXB API (e.g.,
javax.xml.bind:jaxb-api:2.3.1) and, if needed, add matching runtime impl (e.g.,
com.sun.xml.bind:jaxb-impl) and/or adjust the jaxb plugin config so generated
sources consistently use javax.xml.bind annotations; update the dependency entry
in the POM and regenerate the JAXB classes (or reconfigure the codegen plugin)
to ensure InFlowExtensionBasicResponse and other generated classes all import
javax.xml.bind.annotation.*.
| try { | ||
| String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); | ||
| Action action = actionManagementService.getActionByActionId( | ||
| IN_FLOW_EXTENSION_ACTION_TYPE, extensionId, tenantDomain); | ||
| return InFlowExtensionMapper.toInFlowExtensionResponse(action); | ||
| } catch (ActionMgtException e) { |
There was a problem hiding this comment.
Handle not-found results before mapping extension by ID.
Line 316 maps action directly; if the backend returns null for an unknown ID, this path can fail with an internal error instead of returning a not-found response. Please add a null guard and return the appropriate API error.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/core/ServerFlowMgtService.java`
around lines 312 - 317, The method in ServerFlowMgtService that calls
actionManagementService.getActionByActionId (using
IN_FLOW_EXTENSION_ACTION_TYPE, extensionId, tenantDomain) must guard against a
null return before calling InFlowExtensionMapper.toInFlowExtensionResponse; if
getActionByActionId returns null, return/throw the API not-found error response
instead of proceeding. Add a null check for the Action named "action" after the
call and produce the proper 404 API error (consistent with other endpoints)
rather than mapping a null value; preserve the existing ActionMgtException catch
block.
| String val = (String) props.get(key); | ||
| if (StringUtils.isEmpty(val)) { |
There was a problem hiding this comment.
Avoid unsafe cast for authentication properties.
getRequiredStringProp directly casts props.get(key) to String. A non-string input will throw ClassCastException instead of returning a controlled client error.
Proposed fix
private static String getRequiredStringProp(Map<String, Object> props, String key)
throws ActionMgtClientException {
if (props == null || !props.containsKey(key)) {
throw new ActionMgtClientException(
ERROR_CODE_INVALID_ENDPOINT_AUTH_PROPERTIES.getMessage(),
ERROR_CODE_INVALID_ENDPOINT_AUTH_PROPERTIES.getDescription(),
ERROR_CODE_INVALID_ENDPOINT_AUTH_PROPERTIES.getCode());
}
- String val = (String) props.get(key);
+ Object rawVal = props.get(key);
+ if (!(rawVal instanceof String)) {
+ throw new ActionMgtClientException(
+ ERROR_CODE_INVALID_ENDPOINT_AUTH_PROPERTIES.getMessage(),
+ ERROR_CODE_INVALID_ENDPOINT_AUTH_PROPERTIES.getDescription(),
+ ERROR_CODE_INVALID_ENDPOINT_AUTH_PROPERTIES.getCode());
+ }
+ String val = (String) rawVal;
if (StringUtils.isEmpty(val)) {
throw new ActionMgtClientException(
ERROR_CODE_EMPTY_ENDPOINT_AUTH_PROPERTIES.getMessage(),
ERROR_CODE_EMPTY_ENDPOINT_AUTH_PROPERTIES.getDescription(),
ERROR_CODE_EMPTY_ENDPOINT_AUTH_PROPERTIES.getCode());
}
return val;
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/java/org/wso2/carbon/identity/api/server/flow/management/v1/utils/InFlowExtensionMapper.java`
around lines 307 - 308, In getRequiredStringProp within InFlowExtensionMapper,
avoid directly casting props.get(key) to String; instead retrieve the Object,
validate it is an instance of String, and if not throw a controlled client error
(bad request) with a clear message about the expected string type for that key;
then cast to String and continue the existing empty-check (StringUtils.isEmpty).
This prevents ClassCastException for non-string inputs and returns a predictable
error to the client.
| '201': | ||
| description: In-Flow Extension Created | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: '#/components/schemas/InFlowExtensionResponse' |
There was a problem hiding this comment.
Document the Location header on create.
The create endpoint is expected to return the created resource URI, but the 201 response here only documents the body. Add a Location header so the published contract matches the endpoint behavior.
Suggested spec update
'201':
description: In-Flow Extension Created
+ headers:
+ Location:
+ description: URI of the created in-flow extension resource.
+ schema:
+ type: string
content:
application/json:
schema:
$ref: '`#/components/schemas/InFlowExtensionResponse`'📝 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.
| '201': | |
| description: In-Flow Extension Created | |
| content: | |
| application/json: | |
| schema: | |
| $ref: '#/components/schemas/InFlowExtensionResponse' | |
| '201': | |
| description: In-Flow Extension Created | |
| headers: | |
| Location: | |
| description: URI of the created in-flow extension resource. | |
| schema: | |
| type: string | |
| content: | |
| application/json: | |
| schema: | |
| $ref: '`#/components/schemas/InFlowExtensionResponse`' |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/resources/flow.yaml`
around lines 223 - 228, The 201 response for the create endpoint in flow.yaml
documents only the response body (InFlowExtensionResponse) but omits the
Location header; update the '201' response object for "In-Flow Extension
Created" to include a Location header entry (type: string, format: uri,
description: "URI of the created resource") so the OpenAPI contract reflects the
endpoint behavior returning the created resource URI; locate the '201' response
block referencing InFlowExtensionResponse and add a headers -> Location
definition alongside the existing content.
| /flow/in-flow-extension/context-tree: | ||
| get: | ||
| summary: Retrieve the controlled In-Flow Extension context tree | ||
| description: > | ||
| Returns the canonical context tree filtered by the deployment.toml whitelist | ||
| ([identity.in_flow_extension.context.{flow_type}]) for the given flow type. | ||
| When `flowType` is omitted the default tree is returned. Used by the Console UI | ||
| to render the In-Flow Extension access-config editor without offering paths | ||
| the deployment has switched off, and to drive per-flow-type policy flags such | ||
| as `redirectionEnabled` and `allowReadOnlyClaimsModification`. | ||
| operationId: getInFlowExtensionContextTree | ||
| tags: | ||
| - Flow Composer | ||
| parameters: | ||
| - in: query | ||
| name: flowType | ||
| required: false | ||
| schema: | ||
| type: string | ||
| enum: [REGISTRATION, PASSWORD_RECOVERY, INVITED_USER_REGISTRATION, ASK_PASSWORD] | ||
| description: Optional flow type. When omitted, the default tree is returned. | ||
| responses: | ||
| '200': | ||
| description: Successfully retrieved the context tree | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: '#/components/schemas/InFlowExtensionContextTreeResponse' | ||
| '400': | ||
| description: Invalid flow type specified | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: '#/components/schemas/Error' | ||
| '401': | ||
| description: Unauthorized | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: '#/components/schemas/Error' | ||
| '403': | ||
| description: Forbidden | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: '#/components/schemas/Error' |
There was a problem hiding this comment.
Remove the duplicated context-tree path.
/flow/in-flow-extension/context-tree is declared twice in the same paths mapping. That makes the spec unreliable for YAML/OpenAPI tooling and matches the current lint failure. Keep a single definition.
🧰 Tools
🪛 YAMLlint (1.38.0)
[error] 439-439: duplication of key "/flow/in-flow-extension/context-tree" in mapping
(key-duplicates)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/resources/flow.yaml`
around lines 439 - 484, There are two identical path entries for
"/flow/in-flow-extension/context-tree" which breaks the OpenAPI YAML; remove the
duplicate block and keep a single definition for the path (preserve the
operationId getInFlowExtensionContextTree, the parameters (flowType) and all
responses), ensuring only one "/flow/in-flow-extension/context-tree" entry
remains in the paths mapping.
| flowType: | ||
| type: string | ||
| description: Echoed flow type. `null` when no flowType was supplied (default tree). | ||
| example: PASSWORD_RECOVERY |
There was a problem hiding this comment.
Make flowType nullable or change the description.
The description says this field is null when no flowType was supplied, but the schema only allows a string. Either add nullable: true or document the concrete fallback value returned by the API.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/resources/flow.yaml`
around lines 1295 - 1298, The schema for the property named flowType in
flow.yaml currently declares type: string but the description states it may be
null; update the schema to make it consistent by adding nullable: true to the
flowType definition (or alternatively update the description to document the
concrete fallback value the API returns), and ensure the example and any
generated models/clients reflect the nullable change; locate the flowType node
in flow.yaml and add nullable: true (or adjust the description/example) so the
OpenAPI contract matches the actual behavior.
| redirectionEnabled: | ||
| type: boolean | ||
| description: Whether REDIRECT is advertised in `allowedOperations` for this flow type. |
There was a problem hiding this comment.
Align redirectionEnabled with allowedOperations.
redirectionEnabled says REDIRECT is advertised in allowedOperations, but the node schema only allows EXPOSE and MODIFY. Please update either the flag description or the enum so the contract is internally consistent.
Also applies to: 1338-1343
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@components/org.wso2.carbon.identity.api.server.flow.management/org.wso2.carbon.identity.api.server.flow.management.v1/src/main/resources/flow.yaml`
around lines 1306 - 1308, The YAML schema is inconsistent: redirectionEnabled's
description claims REDIRECT is advertised in allowedOperations but the
allowedOperations enum only lists EXPOSE and MODIFY; update the contract by
either adding REDIRECT to the allowedOperations enum values (so
allowedOperations includes REDIRECT alongside EXPOSE and MODIFY) or by changing
redirectionEnabled's description to reflect the actual enum (e.g., state that it
toggles whether REDIRECT-related behavior is implied but is represented via
EXPOSE/MODIFY), and make the same change for the second occurrence of
redirectionEnabled/allowedOperations in the file (the other node with the same
schema).
| @@ -0,0 +1,138 @@ | |||
| /* | |||
| * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). | |||
Purpose
Resolves wso2/product-is#27771
Add REST API support for In-Flow Extension actions and an action name availability check endpoint.
Goals
/actions/inFlowExtension)POST /actions/{actionType}/check-name)Approach
inFlowExtensionas an action type with dedicated request/response schemas for AccessConfig and EncryptioninFlowExtensionfrom activate/deactivate action type enums since EXTENSION category actions don't support status toggleUser stories
N/A
Developer Checklist (Mandatory)
product-isissue to track any behavioral change or migration impact.Release note
POST /actions/{actionType}/check-name)Documentation
N/A
Training
N/A
Certification
N/A
Marketing
N/A
Automation tests
Security checks
Samples
N/A
Related PRs
Migrations (if applicable)
N/A
Test environment
Learning
N/A