eclipse / microprofile-rest-client

MicroProfile Rest Client
Apache License 2.0
141 stars 71 forks source link

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

Open vickymicky opened 10 months ago

vickymicky commented 10 months ago

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 commented 10 months ago

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

WhiteCat22 commented 10 months ago

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 commented 10 months ago

@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: https://github.com/OpenAPITools/openapi-generator/issues/17071 PR: https://github.com/OpenAPITools/openapi-generator/pull/17072

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

WhiteCat22 commented 8 months ago

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.