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

Can we wrap all parameters including body parameter into a single object ? #365

Open
vickymicky opened this issue Nov 17, 2023 · 4 comments
Labels

Comments

@vickymicky
Copy link

vickymicky commented Nov 17, 2023

Hello,

I am trying to see if it's possible to create rest client interface methods with all the parameters wrapped into a single object instead of multiple parameters.

Scenario:
I have multiple header parameters and non null parameters which i dont want to fill while calling the method everytime.

At current state, the interfaces are defined like this,

@Path("/movies")
public interface MovieReviewService {
 
    @GET
    @Path("/{movieId}/reviews/{reviewId}")
    Review getReview( @PathParam("movieId") String movieId, @PathParam("reviewId") String reviewId, @HeaderParam apiKey, @HeaderParam logId);

    @POST
    @Path("/{movieId}/reviews")
    String submitReview( @PathParam("movieId") String movieId, Review review, @HeaderParam apiKey, @HeaderParam logId );

}

Here, I would like to populate all header parameters at a common class for ex, RegisterClientHeaders filters or I would like to not pass a value for a particular param.

Expectation:

@Path("/movies")
 public interface MovieReviewService {
  
     @GET
     @Path("/{movieId}/reviews/{reviewId}")
     Review getReview(GetReviewRequest request);

     @POST
     @Path("/{movieId}/reviews")
     String submitReview( SubmitReviewRequest request);

}

class GetReviewRequest { 
@PathParam("movieId") String movieId;
@PathParam("reviewId") String reviewId;
@HeaderParam String apiKey;
@HeaderParam String logId;
}

class SubmitReviewRequest { 
@PathParam("movieId") String movieId;
@HeaderParam String apiKey;
@HeaderParam String logId;
**Review review;**
}

End result:
I tried wrapping params like this, while the getReview operation works with or without annotated with @BeanParam but submitReview operation doesnt work.

My Observation:
If I unwrap body params from that single object and pass it as another method argument, it works.

Is it by design that we cannot wrap body params into a class along with other params ?
PS: I have tested this using Quarkus / resteasy-reactive implementation.

@Emily-Jiang
Copy link
Member

Are you sure it is Rest Client question? I think it is a Jakarta Restful question.

@WhiteCat22
Copy link
Contributor

WhiteCat22 commented Nov 17, 2023

Hi @vickymicky,

I don't think this is supported. The reason is that using the @RequestBody annotation in a POST is not mandatory, the RestClient will try to determine which parameter is the body if it isn't specified. In this case, I believe it thinks your SubmitReviewRequest is the body and therefore not honoring the inner params. From what I can tell, you must list out all of the params for a POST method. You could try adding a @RequestBody annotation in addition to your SubmitReviewRequest but I don't know if it will work or not.

@vickymicky
Copy link
Author

vickymicky commented Nov 18, 2023

@Emily-Jiang , I read the JAX-RS spec, https://jakarta.ee/specifications/restful-ws/3.1/jakarta-restful-ws-spec-3.1#entity_parameters which states any param not annotated with is considered as entity param but not sure if there is any deviation in microprofile with respect to wrapping params into single object.

@WhiteCat22 , Indeed I tried like this,

@POST
@Path("/{movieId}/reviews")
String submitReview(SubmitReviewRequest request, Review review);

And it works.

I also tried using @RequestBody in class level field but I got an error that it's not supported at class level field, rather it works with method argument.

I think it would be nice if there is design choice provided with microprofile spec.

Bit of background, I am trying to generate microprofile client using openapi spec and was stumbled upon a feature available in openapi-generator hence enquiring if it's possible to wrap all params inside just one object.

Issue: OpenAPITools/openapi-generator#17071
PR: OpenAPITools/openapi-generator#17072

For now, we are wrapping the params with just beanparam and leaving the body param as is in the interface.

@WhiteCat22
Copy link
Contributor

We discussed this feature at today's spec meeting. We understand the desire to clean up your method signature, but we're not sure how to split one single object back into multiple parts type safely. If you have a PR to demonstrate the desired behavior, please submit it so that we can review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants