简体   繁体   中英

How to send a query params map using RESTEasy proxy client

I'm looking for a way to pass a map that contains param names and values to a GET Web Target. I am expecting RESTEasy to convert my map to a list of URL query params; however, RESTEasy throws an exception saying Caused by: javax.ws.rs.ProcessingException: RESTEASY004565: A GET request cannot have a body. . How can I tell RESTEasy to convert this map to a URL query parameters?

This is the proxy interface:

@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
public interface ExampleClient {

    @GET
    @Path("/example/{name}")
    @Produces(MediaType.APPLICATION_JSON)
    Object getObject(@PathParam("name") String name, MultivaluedMap<String, String> multiValueMap);

}

This is the usage:

@Controller
public class ExampleController {

  @Inject
  ExampleClient exampleClient; // injected correctly by spring DI

  // this runs inside a spring controller
  public String action(String objectName) {
      MultivaluedMap<String, String> params = new MultivaluedHashMap<>();

      // in the real code I get the params and values from a DB
      params.add("foo", "bar")
      params.add("jar", "car")
      //.. keep adding

      exampleClient.getObject(objectName, params); // throws exception
  }

}

After hours digging down in RESTEasy source code, I found out that there is no way to do that though interface annotation. In short, RESTEasy creates something called a 'processor' from org.jboss.resteasy.client.jaxrs.internal.proxy.processors.ProcessorFactory to map the annotation to the target URI.

However, it is really simple to solve this issue by creating a ClientRequestFilter that takes the Map from the request body (before executing the request of course), and place them inside the URI query param. Check the code below:

The filter:

@Provider
@Component // because I'm using spring boot
public class GetMessageBodyFilter implements ClientRequestFilter {
    @Override
    public void filter(ClientRequestContext requestContext) throws IOException {
        if (requestContext.getEntity() instanceof Map && requestContext.getMethod().equals(HttpMethod.GET)) {
            UriBuilder uriBuilder = UriBuilder.fromUri(requestContext.getUri());
            Map allParam = (Map)requestContext.getEntity();
            for (Object key : allParam.keySet()) {
                uriBuilder.queryParam(key.toString(), allParam.get(key));
            }
            requestContext.setUri(uriBuilder.build());
            requestContext.setEntity(null);
        }
    }
}

PS: I have used Map instead of MultivaluedMap for simplicity

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM