Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 47 additions & 40 deletions feign-core/src/main/java/feign/MethodHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package feign;

import java.io.IOException;
import java.lang.reflect.Type;

import javax.inject.Inject;
import javax.inject.Provider;
Expand All @@ -30,7 +29,7 @@
import static feign.Util.checkNotNull;
import static feign.Util.ensureClosed;

final class MethodHandler {
abstract class MethodHandler {

/**
* Those using guava will implement as {@code Function<Object[], RequestTemplate>}.
Expand All @@ -53,33 +52,48 @@ static class Factory {

public MethodHandler create(Target<?> target, MethodMetadata md,
BuildTemplateFromArgs buildTemplateFromArgs, Options options, Decoder decoder, ErrorDecoder errorDecoder) {
return new MethodHandler(target, client, retryer, wire, md, buildTemplateFromArgs, options, decoder, errorDecoder);
return new SynchronousMethodHandler(target, client, retryer, wire, md, buildTemplateFromArgs, options, decoder, errorDecoder);
}
}

private final MethodMetadata metadata;
private final Target<?> target;
private final Client client;
private final Provider<Retryer> retryer;
private final Wire wire;

private final BuildTemplateFromArgs buildTemplateFromArgs;
private final Options options;
private final Decoder decoder;
private final ErrorDecoder errorDecoder;

// cannot inject wildcards in dagger
@SuppressWarnings("rawtypes")
private MethodHandler(Target target, Client client, Provider<Retryer> retryer, Wire wire, MethodMetadata metadata,
BuildTemplateFromArgs buildTemplateFromArgs, Options options, Decoder decoder, ErrorDecoder errorDecoder) {
static final class SynchronousMethodHandler extends MethodHandler {
private final Decoder decoder;

private SynchronousMethodHandler(Target<?> target, Client client, Provider<Retryer> retryer, Wire wire, MethodMetadata metadata,
BuildTemplateFromArgs buildTemplateFromArgs, Options options, Decoder decoder, ErrorDecoder errorDecoder) {
super(target, client, retryer, wire, metadata, buildTemplateFromArgs, options, errorDecoder);
this.decoder = checkNotNull(decoder, "decoder for %s", target);
}

@Override protected Object decode(Object[] argv, Response response) throws Throwable {
if (metadata.returnType().equals(Response.class)) {
return response;
} else if (metadata.returnType() == void.class) {
return null;
}
return decoder.decode(metadata.configKey(), response, metadata.returnType());
}
}

protected final MethodMetadata metadata;
protected final Target<?> target;
protected final Client client;
protected final Provider<Retryer> retryer;
protected final Wire wire;

protected final BuildTemplateFromArgs buildTemplateFromArgs;
protected final Options options;
protected final ErrorDecoder errorDecoder;

private MethodHandler(Target<?> target, Client client, Provider<Retryer> retryer, Wire wire, MethodMetadata metadata,
BuildTemplateFromArgs buildTemplateFromArgs, Options options, ErrorDecoder errorDecoder) {
this.target = checkNotNull(target, "target");
this.client = checkNotNull(client, "client for %s", target);
this.retryer = checkNotNull(retryer, "retryer for %s", target);
this.wire = checkNotNull(wire, "wire for %s", target);
this.metadata = checkNotNull(metadata, "metadata for %s", target);
this.buildTemplateFromArgs = checkNotNull(buildTemplateFromArgs, "metadata for %s", target);
this.options = checkNotNull(options, "options for %s", target);
this.decoder = checkNotNull(decoder, "decoder for %s", target);
this.errorDecoder = checkNotNull(errorDecoder, "errorDecoder for %s", target);
}

Expand All @@ -88,45 +102,38 @@ public Object invoke(Object[] argv) throws Throwable {
Retryer retryer = this.retryer.get();
while (true) {
try {
return executeAndDecode(metadata.configKey(), template, metadata.returnType());
return executeAndDecode(argv, template);
} catch (RetryableException e) {
retryer.continueOrPropagate(e);
continue;
}
}
}

public Object executeAndDecode(String configKey, RequestTemplate template, Type returnType)
public Object executeAndDecode(Object[] argv, RequestTemplate template)
throws Throwable {
// create the request from a mutable copy of the input template.
Request request = target.apply(new RequestTemplate(template));
wire.wireRequest(target, request);
Response response = execute(request);
Response response;
try {
response = client.execute(request, options);
} catch (IOException e) {
throw errorExecuting(request, e);
}
try {
response = wire.wireAndRebufferResponse(target, response);
if (response.status() >= 200 && response.status() < 300) {
if (returnType.equals(Response.class)) {
return response;
} else if (returnType == void.class) {
return null;
}
return decoder.decode(configKey, response, returnType);
return decode(argv, response);
} else {
throw errorDecoder.decode(configKey, response);
throw errorDecoder.decode(metadata.configKey(), response);
}
} catch (Throwable e) {
} catch (IOException e) {
throw errorReading(request, response, e);
} finally {
ensureClosed(response.body());
if (IOException.class.isInstance(e))
throw errorReading(request, response, IOException.class.cast(e));
throw e;
}
}

private Response execute(Request request) {
try {
return client.execute(request, options);
} catch (IOException e) {
throw errorExecuting(request, e);
}
}
protected abstract Object decode(Object[] argv, Response response) throws Throwable;
}