java - example - jersey-client maven
DropWizard/Jersey API Clients (4)
DropWizard usa Jersey debajo del capó para REST. Estoy intentando descubrir cómo escribir un cliente para los puntos finales RESTful que expondrá mi aplicación DropWizard.
Por el bien de este ejemplo, digamos que mi aplicación DropWizard tiene un CarResource
, que expone algunos puntos finales RESTful simples para autos CRUDding:
@Path("/cars")
public class CarResource extends Resource {
// CRUDs car instances to some database (DAO).
public CardDao carDao = new CarDao();
@POST
public Car createCar(String make, String model, String rgbColor) {
Car car = new Car(make, model, rgbColor);
carDao.saveCar(car);
return car;
}
@GET
@Path("/make/{make}")
public List<Car> getCarsByMake(String make) {
List<Car> cars = carDao.getCarsByMake(make);
return cars;
}
}
Así que me imagino que un cliente API estructurado sería algo así como un CarServiceClient
:
// Packaged up in a JAR library. Can be used by any Java executable to hit the Car Service
// endpoints.
public class CarServiceClient {
public HttpClient httpClient;
public Car createCar(String make, String model, String rgbColor) {
// Use ''httpClient'' to make an HTTP POST to the /cars endpoint.
// Needs to deserialize JSON returned from server into a `Car` instance.
// But also needs to handle if the server threw a `WebApplicationException` or
// returned a NULL.
}
public List<Car> getCarsByMake(String make) {
// Use ''httpClient'' to make an HTTP GET to the /cars/make/{make} endpoint.
// Needs to deserialize JSON returned from server into a list of `Car` instances.
// But also needs to handle if the server threw a `WebApplicationException` or
// returned a NULL.
}
}
Pero las únicas dos referencias oficiales a los clientes de Drop Wizard que puedo encontrar son totalmente contradictorias entre sí:
- La estructura de proyecto recomendada por DropWizard , que dice que debo poner mi código de cliente en un proyecto de
car-client
en el paquetecar.service.client
; pero entonces... - El manual DropWizard Client - que lo hace parecer como un "Cliente DropWizard" está destinado a integrar mi aplicación DropWizard con otros servicios web RESTful (actuando así como intermediario).
Entonces pregunto, ¿cuál es la forma estándar de escribir clientes API Java para sus servicios web DropWizard? ¿DropWizard tiene una biblioteca de cliente que puedo utilizar para este tipo de caso de uso? ¿Se supone que debo implementar el cliente a través de una API cliente de Jersey? ¿Alguien puede agregar pseudocódigo a mi CarServiceClient
para que pueda entender cómo funcionaría?
Puede integrarse con Spring Framework para implementar
Sí, lo que dropwizard-client proporciona solo debe ser utilizado por el servicio en sí, más probablemente para comunicar otros servicios. No proporciona nada para las aplicaciones del cliente directamente.
No hace mucha magia con HttpClients de todos modos. Simplemente configura el cliente de acuerdo con el archivo yml, asigna el mapeador de objetos Jackson existente y el validador al cliente de Jersey, y creo que reutiliza el grupo de subprocesos de la aplicación. Puede verificar todo eso en https://github.com/dropwizard/dropwizard/blob/master/dropwizard-client/src/main/java/io/dropwizard/client/JerseyClientBuilder.java
Creo que iría y estructuraría mis clases como lo hiciste con Jersey Client. Lo que sigue es una clase abstracta que he estado usando para los servicios al cliente:
public abstract class HttpRemoteService {
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String TOKEN_PREFIX = "Bearer ";
private Client client;
protected HttpRemoteService(Client client) {
this.client = client;
}
protected abstract String getServiceUrl();
protected WebResource.Builder getSynchronousResource(String resourceUri) {
return client.resource(getServiceUrl() + resourceUri).type(MediaType.APPLICATION_JSON_TYPE);
}
protected WebResource.Builder getSynchronousResource(String resourceUri, String authToken) {
return getSynchronousResource(resourceUri).header(AUTHORIZATION_HEADER, TOKEN_PREFIX + authToken);
}
protected AsyncWebResource.Builder getAsynchronousResource(String resourceUri) {
return client.asyncResource(getServiceUrl() + resourceUri).type(MediaType.APPLICATION_JSON_TYPE);
}
protected AsyncWebResource.Builder getAsynchronousResource(String resourceUri, String authToken) {
return getAsynchronousResource(resourceUri).header(AUTHORIZATION_HEADER, TOKEN_PREFIX + authToken);
}
protected void isAlive() {
client.resource(getServiceUrl()).get(ClientResponse.class);
}
}
y así es como lo hago concreto:
private class TestRemoteService extends HttpRemoteService {
protected TestRemoteService(Client client) {
super(client);
}
@Override
protected String getServiceUrl() {
return "http://localhost:8080";
}
public Future<TestDTO> get() {
return getAsynchronousResource("/get").get(TestDTO.class);
}
public void post(Object object) {
getSynchronousResource("/post").post(object);
}
public void unavailable() {
getSynchronousResource("/unavailable").get(Object.class);
}
public void authorize() {
getSynchronousResource("/authorize", "ma token").put();
}
}
si alguien está tratando de usar DW 0.8.2 al construir un cliente, y está obteniendo el siguiente error:
cannot access org.apache.http.config.Registry
class file for org.apache.http.config.Registry not found
at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:858)
at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
... 19 more
actualice su dropwizard-client en su pom.xml de 0.8.2 a 0.8. 4 y deberías ser bueno. Creo que se actualizó una subdependencia de embarcadero que lo solucionó.
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-client</artifactId>
<version>0.8.4</version>
<scope>compile</scope>
</dependency>
Aquí hay un patrón que puede usar con el cliente JAX-RS.
Para obtener el cliente:
javax.ws.rs.client.Client init(JerseyClientConfiguration config, Environment environment) {
return new JerseyClientBuilder(environment).using(config).build("my-client");
}
A continuación, puede hacer llamadas de la siguiente manera:
javax.ws.rs.core.Response post = client
.target("http://...")
.request(MediaType.APPLICATION_JSON)
.header("key", value)
.accept(MediaType.APPLICATION_JSON)
.post(Entity.json(myObj));