Skip to content
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

Cloud provides response type change recipe? #18

Open
stevenniu9527 opened this issue Oct 28, 2024 · 3 comments
Open

Cloud provides response type change recipe? #18

stevenniu9527 opened this issue Oct 28, 2024 · 3 comments
Labels
enhancement New feature or request recipe

Comments

@stevenniu9527
Copy link

I have tried the existing recipe. Now the recipe MigrateApiOperationToOperation directly deletes the response without change.

- org.openrewrite.java.RemoveAnnotationAttribute:
      annotationType: io.swagger.v3.oas.annotations.Operation
      attributeName: response

How to Migrate from Swagger to OpenAPI, Get the replacement below. Especially reserve the reponse type

@ApiOperation(value = "acquireSyncLeader", notes = "acquireSyncLeader", response = String.class, httpMethod = "GET")
i hope after migrate :

@Operation(summary = "acquireSyncLeader", description = "acquireSyncLeader", responses = {@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class))),

@stevenniu9527 stevenniu9527 added the enhancement New feature or request label Oct 28, 2024
@timtebeek
Copy link
Contributor

hi @stevenniu9527 ; thanks for reporting here! Indeed right now the recipe does a simple removal

- org.openrewrite.java.RemoveAnnotationAttribute:
annotationType: io.swagger.v3.oas.annotations.Operation
attributeName: response

To go from the before to after scenario you've described we'd need to add a dedicated recipe that adds the new replacement responses attribute instead. That would likely be similar to this existing recipe, if you'd like an example to help you implement this:

new JavaIsoVisitor<ExecutionContext>() {
@Override
public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext ctx) {
J.Annotation an = super.visitAnnotation(annotation, ctx);
if (ANNOTATION_MATCHER.matches(an)) {
return an.withArguments(ListUtils.map(an.getArguments(), this::maybeReplaceResponseCodeTypeAndValue));
}
return an;
}
private Expression maybeReplaceResponseCodeTypeAndValue(Expression arg) {
if (arg instanceof J.Assignment) {
J.Assignment assignment = (J.Assignment) arg;
boolean matchesField = assignment.getVariable() instanceof J.Identifier &&
"responseCode".equals(((J.Identifier) assignment.getVariable()).getSimpleName());
boolean usesNumberLiteral = assignment.getAssignment() instanceof J.Literal &&
((J.Literal) assignment.getAssignment()).getValue() instanceof Number;
if (matchesField && usesNumberLiteral) {
J.Literal assignedLiteral = (J.Literal) assignment.getAssignment();
return assignment
.withType(JavaType.Primitive.String)
.withAssignment(assignedLiteral
.withValue(String.valueOf(assignedLiteral.getValue()))
.withValueSource("\"" + assignedLiteral.getValue() + "\"")
.withType(JavaType.Primitive.String));
}
}
return arg;
}
}

And perhaps good to check: are you certain that change is necessary? What's default without that additional property?

@timtebeek timtebeek moved this to Recipes Wanted in OpenRewrite Oct 28, 2024
@stevenniu9527
Copy link
Author

stevenniu9527 commented Oct 29, 2024

I think the return type content = @Content(mediaType = "application/json", schema = @Schema(implementation = User.class)) is a necessary swagger parameter and is used to generate swagger interface documentation.
like Example 2 in swagger doc:https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Annotations

    @GET
    @Path("/{username}")
    @Operation(summary = "Get user by user name",
            responses = {
                    @ApiResponse(description = "The user",
                            content = @Content(mediaType = "application/json",
                                    schema = @Schema(implementation = User.class))),
                    @ApiResponse(responseCode = "400", description = "User not found")})
    public Response getUserByName(
            @Parameter(description = "The name that needs to be fetched. Use user1 for testing. ", required = true) @PathParam("username") String username)
            throws ApiException {
        User user = userData.findUserByName(username);
        if (null != user) {
            return Response.ok().entity(user).build();
        } else {
            throw new NotFoundException(404, "User not found");
        }
    }

The output for Example 2 would be:

/user/{username}:
    get:
      summary: Get user by user name
      operationId: getUserByName
      parameters:
      - name: username
        in: path
        description: 'The name that needs to be fetched. Use user1 for testing. '
        required: true
        schema:
          type: string
      responses:
        default:
          description: The user
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        400:
          description: User not found

@timtebeek
Copy link
Contributor

That's helpful info, thanks! Would you be willing and able to help create that recipe?
We have some self-guided recipe authoring resources here to help you get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request recipe
Projects
Status: Recipes Wanted
Development

No branches or pull requests

2 participants