web-dev-qa-db-fra.com

Client Jersey / JAX-RS et facultatif (pas par défaut) @QueryParam (côté client)

J'ai une API RESTful dont le document indique qu'un certain paramètre de requête est facultatif et ne fournit pas d'argument par défaut. Ainsi, je peux soit fournir la valeur ou ne pas l'envoyer dans la demande GET en tant que paramètre.

Exemple:

  • queryA est requis
  • queryB est facultatif (peut envoyer GET sans lui)

Cela devrait fonctionner:

http://www.example.com/service/endpoint?queryA=foo&queryB=bar

Cela devrait également fonctionner:

http://www.example.com/service/endpoint?queryA=foo

Comment puis-je créer une interface client pour Jersey-Proxy qui peut le faire ?? Je n'ai pas le code côté serveur pour l'interface avec donc j'utilise org.glassfish.jersey.client.proxy.WebResourceFactory via Jersey-Proxy pour générer le client pour interagir avec l'API du serveur.

Exemple d'interface:

import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/service")
@Produces("application/json")
public interface ServiceInterface {

    @Path("/endpoint")
    @GET
    public Response getEndpoint(
            @QueryParam("queryA") String first,
            @QueryParam("queryB") String second);

}

Je sais que je peux faire une autre méthode:

    @Path("/endpoint")
    @GET
    public Response getEndpoint(
            @QueryParam("queryA") String first);

Mais que se passe-t-il lorsque vous avez plusieurs champs facultatifs ?? Je ne veux pas en faire toutes les mutations possibles!

17
justderb

L'interface était correcte depuis le début

Je ne peux pas croire que c'était aussi simple:

import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/service")
@Produces("application/json")
public interface ServiceInterface {

    @Path("/endpoint")
    @GET
    public Response getEndpoint(
            @QueryParam("queryA") String first,
            @QueryParam("queryB") String second);

}

Remarquez quelque chose de différent de l'interface des questions ?? Nan. C'est parce que c'est la réponse!


N'utilisez pas @DefaultValue pour les paramètres facultatifs

Si vous souhaitez attribuer par défaut un paramètre à une valeur spécifique, vous utilisez l'annotation @DefaultValue Dans le paramètre:

import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/service")
@Produces("application/json")
public interface ServiceInterface {

    @Path("/endpoint")
    @GET
    public Response getEndpoint(
            @QueryParam("queryA") String first,
            @QueryParam("queryB") @DefaultValue("default") String second);

}

Passez null au @QueryParam Dont vous ne voulez pas

Si vous souhaitez rendre l'option @QueryParam Facultative, vous n'appliquez pas l'annotation @DefaultValue. Pour passer une valeur avec le paramètre de requête, transmettez simplement la valeur normalement. Si vous souhaitez que le paramètre de requête n'apparaisse pas du tout, passez simplement null!

import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/service")
@Produces("application/json")
public interface ServiceInterface {

    @Path("/endpoint")
    @GET
    public Response getEndpoint(
            @QueryParam("queryA") String first,
            // Pass null to this parameter to not put it in the GET request
            @QueryParam("queryB") String second);

}

Donc, appeler ServiceInterface.getEndpoint("firstQueryParam", "secondQueryParam"); appelle:

http://targethost.com/service/endpoint?queryA=firstQueryParam&queryB=secondQueryParam

et appeler ServiceInterface.getEndpoint("firstQueryParam", null); appelle:

http://targethost.com/service/endpoint?queryA=firstQueryParam

Et walla! Pas de deuxième paramètre de requête! :)

Remarque sur les valeurs primitives

Si votre API prend des valeurs primitives (comme int, float, boolean, etc.), utilisez la classe wrapper d'objet ( Autoboxing ) pour cela primitive (comme Integer, Float, Boolean, etc.). Ensuite, vous pouvez passer null à la méthode:

public Response getEndpoint(@QueryParam("queryA") Boolean first);
28
justderb

Vous pouvez injecter une instance UriInfo (ou autre chose comme HttpServletRequest) dans votre méthode et en retirer les données que vous souhaitez.

Par exemple

@Path("/endpoint")
@GET
public Response getEndpoint(@Context UriInfo info, @QueryParam("queryA") String queryA) {
  String queryB = info.getQueryParameters().getFirst("queryB");
  if (null != queryB) {
    // do something with it
  }
  ...
}
2
Alex