Giter Club home page Giter Club logo

feign's People

Contributors

aalmiray avatar adriancole avatar ahus1 avatar arthurscchan avatar ashleyfrieze avatar bstick12 avatar davidmc24 avatar dependabot[bot] avatar flolei avatar gimbimloki avatar gromspys avatar jerzykrlk avatar jkomoroski avatar jkschneider avatar kdavisk6 avatar mroccyen avatar mstryoda avatar nmiyake avatar pilak avatar pnepywoda avatar rfalke avatar ricardordzg avatar rspieldenner avatar santhosh-tekuri avatar simy4 avatar snyk-bot avatar spencergibb avatar velo avatar vitalijr2 avatar wplong11 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

feign's Issues

Support parameterized base apis

Consider the example:

public interface BaseAPI {
     @RequestLine("GET /health")
     String health();
     @RequestLine("GET /all")
     List<Entity> all();
}

And then some specific API:

public interface CustomAPI extends BaseAPI {
     @RequestLine("GET /custom")
     String custom();
}

I'd like to use CustomAPI when creating Feign client and be able to access methods of the BaseAPI.

Currently only methods defined directly in the CustomAPI are bound to handlers.

It looks like the only required changes to be made are:

1 feign.Contract.BaseContract.parseAndValidatateMetadata(Class<?> declaring):

//      for (Method method : declaring.getDeclaredMethods()) {
      for (Method method : declaring.getMethods()) {

2 feign.ReflectiveFeign.newInstance(Target<T> target):

//    for (Method method : target.type().getDeclaredMethods()) {
    for (Method method : target.type().getMethods()) {

I was able to get the required functionality with the above changes.
Would be great to have this functionality either out of the box or easily configurable.

Support query param encoders

It'd be nice to be able to supply custom query param encoders. For example, sometimes we need to encode a Date query param as a String with a given format.

Move to Dagger 2

Dagger 1.x is not likely to continue. Dagger 2 is.

I'm interested enough to help port everything here (and maybe fix some bugs etc along the way), plus revamp denominator accordingly.

Please ping this issue if you feel strongly that feign should not move to Dagger 2.

Investigate using types alone for Decoder bindings

currently, we use method key (ex. IAM or IAM#auth(String,String)) to wire decoders to the methods that need them. This is consistent with error handlers, etc, but possibly overkill for decoders, where the intended result is always correlated to the return type of the method (or the type param of the observer).

If we switch to type-only, it is possible for us to use Set bindings, to collect decoders. Something far less complicated then our current approach.

Getting started guide

While there are a couple examples, there's no step-by-step introduction for using feign, or how to make custom decoders, etc.

Named Query Parameters on GET requests

Picking up the latest version I'd expect to be able to do something like the following

@RequestLine("GET /users?name={name}")
public JsonObject getUsersByName(@nAmed("name") String name);

Unfortunately this doesn't seem to work. The default encoder receives a LinkedHashMap and complains about it not being a String. The GsonEncoder copes fine with it but the end result is that a POST is made with the query parameters encoded into the body.

Ability to register modules w/ Target

Maybe I'm missing something, but it doesn't seem possible to mix a module with the .target()-style builder. It'd be great to have a .module(Object...) method so targets can be mixed with modules such as the JAXRS module. I'd be happy to PR it if I'm not missing something.

Release 7.0.0

Let's release 7.0.0, particularly as some backports are only partially merged into 6.x. Doing this also frees up master to do more bold things.

  • cut branch 7.x from master
  • update master branch gradle.properties 8.0.0-SNAPSHOT
  • create 7.x release job based on 6.x one
  • kick off 7.x release job to release 7.0.0 from 7.x branch
  • don't forget to close and release the oss sonatype staging repo!
  • update main example-github and example-wikipedia to use version 7.0.0
  • update denominator to use version 7.0.0 

cc @qualidafial @davidmc24 @rspieldenner

interface level header defaults

I implemented an enhanced contract that extends the default contract but adds the ability to set interface level Headers as defaults unless overridden at the method level..

I also added convenience annotations for ContentType & Accept since those (at least in our experience) are most typically set.
The annotations follow more of the jaxrs style, but another option I could see would be adding these as settables in the Feign.Builder when creating the client.. I'm on fence as which one i like better.

Are either of these of interest as a pull? @adriancole

Provide means to trace calls

A vendor management system at netflix started looking at feign and realized they needed a way to trace every java call that results in feign calls.

While this could be done via the feign Logger, it is cleaner to extract out a profiling interface. I don't have a specific design, yet, but we could borrow from retrofit's Profiler.

Before making a final choice, we should document what metadata is needed in the requests and see how (if at all) this is addressed in other systems such as JAX-RS 2.0, WebSocket, Netty, etc.

Add interceptor

A vendor management system at netflix started looking at feign and realized they needed a way to add contextual headers to a request, such as application id, and request id.

While this could be done with Target.apply, the essence of the change is more environment-specific. Exposing an Interceptor interface could be a better way to model this.

class FooInterceptor implements RequestInterceptor {
  @Override public void intercept(RequestTemplate request) {
    request.header("extra", "value");
  }
}

feign with hystrix

I'd like to use hystrix with feign, but it appears i'd have to shoehorn it into the invocation handler factory, and if i wanted the ability to do things async it would be more changes to methodmetadata to look for Future<?> return types..
I could do this on the outside of the feign, but that seems kludgy so i wanted to see if there were any better ideas floating around?

Release 7.2.0

Adds features needed to cut a denominator release.

Release Version 6.1.1

It would be really helpful if you can please release version 6.1.1 in maven central?

investigate async http client integration

Per a discussion with @NiteshKant, I believe we can make a compatible http response callback interface to facilitate nio support.

Context

Many async http clients provide a callback interface such as below

Future<Integer> f = asyncHttpClient.prepareGet("http://www.ning.com/").execute(
   new AsyncCompletionHandler<Integer>(){

    @Override
    public Integer onCompleted(Response response) throws Exception{
        // Do something with the Response
        return response.getStatusCode();
    }

    @Override
    public void onThrowable(Throwable t){
        // Something wrong happened.
    }
});

https://github.com/AsyncHttpClient/async-http-client

How

It should be possible to extend our Client to be compatible with the callback system from one or more async http clients, avoiding the need to independently manage threads in Feign.

ex.

interface Client {
  // existing
  Response execute(Request request, Options options) throws IOException;
  // new
  void execute(Request request, Options options, IncrementalCallback<Response> responseCallback);

An asynchronous client would need to map their callback to ours.

Any synchronous http client (including our default) could extend from a base class that implements the callback method like so

void execute(Request request, Options options, IncrementalCallback<Response> responseCallback) {
      httpExecutor.get().execute(new Runnable() {
        @Override public void run() {
          Error error = null;
          try {
            responseCallback.onNext(execute(request, options));
            responseCallback.onSuccess();
          } catch (Error cause) {
            // assign to a variable in case .onFailure throws a RTE
            error = cause;
            responseCallback.onFailure(cause);
          } catch (Throwable cause) {
            responseCallback.onFailure(cause);
          } finally {
            Thread.currentThread().setName(IDLE_THREAD_NAME);
            if (error != null)
              throw error;
          }
        }
      }
  }

Using header to pass additional information

I've seen the RequestInterceptor example. Does Feign allow user to put stuff in header for passing additional information on each call without recreating the client?

I have client code that will create a Feign client one time, but based on the Request Interceptor example, we need to recreate the feign client every time the code is called.

Logger should emit on IOException

It would be really helpful to trackdown things like socket timeout errors, if the logger emitted a message when an IOException occurs.

This came up using denominator where a service emitted read timeouts longer than expected.

Enforce JAX-RS interfaces are interpreted as defined for services

Particularly in relation to @Provides and @Consumes, we need to interpret jax-rs annotations knowing that they are defined on service apis. For example, @Consumes implies that the server accepts the media type. So, feign's interpretation should be that @Consumes affects the content-type header, not the accept header, sent.

cc @syed-haq

Support for Iterable Query Param

Currently feign doesn't support iterable query param. Could you add this support?

Also, it should probably throw a better exception then the current one when using iterable query param:

feign.FeignException: status 505 reading ; content:

Release 7.1.0

Let's cut 7.1, as it has the feign.Param annotation needed to bridge to 8.x. Also includes OkHttp support and some bug fixes.

Use of `java.lang.reflect.Type` not sufficient for proper generic types

As you may be aware, Java's support for handling and resolving generic types is not particularly good. For background info, here -- http://www.cowtowncoder.com/blog/archives/2010/12/entry_436.html -- is a blog entry I wrote a while back explaining why use of java.lang.reflect.Type is not sufficient for handling generic types of method calls.

Unfortunately many frameworks, such as JAX-RS, have used this is their canonical type representation.
Note that this is not just a theoretical issue: it is very difficult to, for example, implement java.lang.reflect.Type. The only uses for it really are:

  1. Pass Class<?> instances, OR
  2. Pass Type one gets via reflection from Method or Field instances.

Of these, second case is the problematic one, since it is not possible to resolve many cases that involve type parameters.

An immediate problem is that there aren't many obviously better mechanisms. For what it is worth, Classmate:

https://github.com/cowtowncoder/java-classmate

does actually solve the problem of handling of generic types. But downside is that not many codec libraries support ClassMate -- because of this, it may or may not be a good solution here.

Another smaller improvement would be introduction of "type token" type (Jackson and Gson have their own token types), which at least would allow static passing of generic types, with constructs like:

new TypeReference<Map<String,Integer>>() { }

The problem here is similar to ClassMate case: since JDK does not provide such standard wrapper, nor is there a universally used 3rd party lib, it may be difficult to add full support.

Support Basic Authentication

I've got a working implementation of this as a RequestInterceptor that I'd be happy to contribute. Assuming that there's interest in this, would you prefer it within core, in a separate module in the main repo, or publishing it as a standalone repo elsewhere?

CHANGES.md skips 6.0.1?

Currently, it looks to me like there are entries in CHANGES.md for 6.0 and 6.0.2, but nothing for 6.0.1. From looking around a bit, it looks like 6.0.1 was released, and should include the change that is listed as 6.0.2. Probably the correct fix is to change the existing entry in CHANGES.md from 6.0.2 to 6.0.1?

Add example of a nasty api

The GitHub example seems like a nice intro to Feign, but it is actually a poor choice. The json model is clean, as are the way rest calls are made. Most apis are not even close to as clean as this, so the example leads to a cliff.

@benjchristensen had a good idea to add an example a nastier, more realistic api, such as wikipedia. Let's do that.

Specific HTTP error code FeignExceptions

Currently any error caused by the executed HTTP call results in a FeignException. This makes it impossible to handle according to the type of HTTP error. (Or am I missing something?)

Would it be an idea to:

  • have HTTP error code ranged exceptions, like Http4xxFeignException for any 400-499 HTTP error, and Http5xxFeignException for 500-599 HTTP errors
  • have the specific error code available in the exception

IncrementalCallback support

Incremental callbacks facilitate asynchronous invocations, where the http connection and decoding of elements inside the response are decoupled from the calling thread.

In a typical synchronous response, the calling thread blocks on the http connect, reading from the socket, and also decoding of the response data into a java type. As such, a java type is returned.

interface GitHub {
  @RequestLine("GET /repos/{owner}/{repo}/contributors")
  Iterator<Contributor> contributors(@Named("owner") String owner, @Named("repo") String repo);
}

In an incremental callback pattern, the calling thread blocks until the request is queued, but processing of the response (including connect, read, decode) are free to be implemented on different threads. To unblock the caller, void is returned.

interface GitHub {
  @RequestLine("GET /repos/{owner}/{repo}/contributors")
  contributors(@Named("owner") String owner, @Named("repo") String repo, IncrementalCallback<Contributor> contributors);
}

Motivation

Denominator works primarily on high latency collections, where responses can take up to minutes to return. Even-though denominator returns Iterators, allowing iterative response processing, usually update granularity is per http request due to response parsing semantics of returning a list.

Ex. Sax parsing into a list which is later returned.

    if (qName.equals("HostedZone")) {
            zones.add(Zone.create(this.name, id));
...
    @Override
    public ZoneList getResult() {
        return zones;

Ex. Incremental callback pattern allows for immediate visibility of new elements

    if (qName.equals("HostedZone")) {
            observer.onNext(Zone.create(this.name, id));

Also, Netflix RxJava is increasingly employed, so optimizing for Observers makes sense.

IncrementalCallback Design

The following design takes from RxJava Observer and Retrofit Callback.

public interface IncrementalCallback<T> {
  void onNext(T element);
  void onSuccess();
  void onFailure(Throwable cause);
}

Why Throwable onFailure instead of Exception

The design we are discussing is how to address async callbacks in a Java idiomatic way. We issue Throwable on error instead of Exception, as Feign doesn't have a catch-all exception wrapper and Errors could be the reason why the failure occurred. This allows visibility of Errors such as AssertionErrors or thread starvation to propagate without confusing exception wrappers. It also allows us to simply propagate exception.getCause() without a wrapper.

The above rationale supports the case for Throwable vs Exception where Feign exists in isolation. Where Feign interacts with other libraries unveils other considerations. For example, Every current java async web callback issues throwable, not exception, for error signals. If we chose to retain Exception as opposed to Throwable, converting to or from these interfaces will be lossy.

how do we make this callback asynchronous?

should we decode the response?

IncrementalCallback vs ...

In order to support asynchronous processing of http responses, we need to implement responses of Future, (RxJava) Observable, or allow users to pass in a Callback or and Observer.

As Observable is the centerpiece of RxJava's reactive pattern, it is a relatively wide interface. As such, the source for Observable.java is larger than the entire codebase of feign including tests. Making a move to couple to Observable seems overkill just to afford asynchronous invocation.

Future semantics are hard to guarantee, as operations such as cancel() rarely perform as expected with blocking i/o. For example, many implementations of http futures simply fire a callable which has no means to stop the connection or stop reading from it. Moreover timeouts are hard to make sense in future. For example connect vs read timeouts are hard to understand. Typically a response is returned after connect, but during connection you have no means to stop it. After future.get is returned, another timeout is possible reading from the stream. In summary while Future is often used, it is a tricky abstraction.

Callback and Observer approaches are simplest and incur no core dependencies. They can both be type-safe interface, such as the one in Retrofit or android-http. IncrementalCallback slightly wins as it allows for incremental parsing, and doesn't imply that Feign is Observable.

Why not reuse RxJava Observer?

RxJava Observer is not a wide interface, so much easier to grok than Observable. However, the Observer type in rx is a concrete class and implies a dependency on rxjava, a dependency which is an order of magnitude larger than feign itself. Decoupling in core, and recoupling as an extension is the leanest way to interop.

Check for a default Accept header in mock tests

If feign doesn't explicitly set an Accept header then HttpURLConnection.java (line 376) will set the Accept header below.

Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2

This can cause API validations to choke, if they're expecting no Accept header or an Accept header from a predefined list of application/json, application/xml, etc.

Feign should check for default Accept header in mock tests to prevent this scenario from occurring.

See this comment in Denominator for more context.

release feign 5.4.0 and 6.0.0

We haven't had a release in a while..

release 5.4.0

  • update 5.x branch gradle.properties 5.4.0-SNAPSHOT
  • kick off 5.x release job to release 5.4.0 from 5.x branch
  • don't forget to close and release the oss sonatype staging repo!

release 6.0.0

  • cut branch 6.x from master
  • update master branch gradle.properties 7.0.0-SNAPSHOT
  • create 6.x release job based on 5.x one
  • kick off 6.x release job to release 6.0.0 from 6.x branch
  • don't forget to close and release the oss sonatype staging repo!
  • update main example-github and example-wikipedia to use version 6.0.0
  • update denominator to use version 6.0.0 

cc @cfieber @davidmc24

Feature Request: add support for custom request Content-Encoding (such as gzip)

I have an API that I'd like to use Feign to connect to that requires that the POST request body use gzip content encoding.

This feels to me like something that should be possible using a RequestInterceptor, but the current structure of RequestTemplate (storing body as String, and converting to bytes in the client) doesn't really seem like it supports it. I know I could add support for this using a custom Client implementation. Is there a better approach?

[question] How to use Feign with a JAX-RS interface defining jaxrs.Response as return types

Hi,

I'm using Feign with a JAX-RS interface using JAX-RS Response return types (not feign.Response).
For instance:

@Path("/users")
@Produces(MediaType.APPLICATION_JSON)
public interface UserContract {
    @POST
    @Path("/")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response create(User user);

    ...

When using feign and calling the "create" method, it seems that feigns tries to deserialize the jaxrs.Response object from the HTTP reponse.

Well it makes sense since it's the return type but it's obviously not what I expect. What would be the best way to handle jaxrs.Response type with feign ?

Thanks

Simplify Feign

There are a number of ideas in feign that didn't work out very well, are edge case, or pure over-engineering. We should get rid of them as feign is used in production and should focus its code base, failure cases, and WTFs on things relevant to those use cases.

  • For those who do not use dagger, or do not wish to, we could expose a builder which defines all dependencies explicitly that can be provided. see issue #34
  • Codec types such as Decoder, Encoder, should not have a type parameter. The implicit responsibility of type adapters is better taken by implementations like gson. Moreover, binding to a raw-type Set<Decoder> is confusing when the type parameter is meaningful.
  • IncrementalDecoder should be axed. This is even more hairy than above, and even less often used. Streaming is application specific (twitter newlines vs S3 buckets) and rare. There are no feign clients I'm aware of that actually employ incremental parsing. Finally, multiplexed (SPDY, HTTP2) or message oriented (WebSocket) approaches imply less need for really long stream decodes over time.
  • Pattern decoders should be axed. Existing use of RegEx decoders was limited to XML responses, so rather than maintain a sizable chunk of code for both SAX and RegEx, let's prefer SAX.
  • Observer/Observable should be axed. Due to above, getting an Observer to actually work per-element is application-specific, not format specific, and would imply a lot of confusing feign config. While there is usefulness in exposing the response (or even its reader) as a callback, Observable overshoots this and adds complexity. Similarly to IncrementalDecoder, Observable isn't used in feign client in production I'm aware of! Currently, those wanting Observer could do so by submitting a Callable to a feign method w/ rx.Observer. Experimentation would end up in an extension per #25 and #26

This doesn't mean we shouldn't play with ideas or that these ideas will never reach prod. Just that we shouldn't commit all ideas to trunk as that increases the cognitive and maintenance load of feign without helping real production use. This may imply we need a "labs" repo or persistent forks to facilitate research.

Add Feign.Builder

For those who do not use dagger, or do not wish to, we could expose a builder which defines all dependencies explicitly that can be provided. This includes logging config, decoders, etc. This could be modeled similarly to retrofit RestAdapter.Builder or jclouds ContextBuilder

ex.

api = Feign.builder()
                .loggingLevel(BASIC)
                .decoder(customType)
                .target(GitHub.class, "http://foo");

Note that this will still use dagger under the scenes, albeit via reflection. When/if someone wants to switch to pure dagger, they could use the module system directly.

cc @benjchristensen

Ensure unused Provides methods fail at compile-time

For many users, feign will be the first time they see Dagger. Dagger has a wonderful system of compile-time failures. However, when Module(library=true) is set, unused bindings will not fail. This causes an issue when for example, someone binds a parameterized type where a raw type is needed.

Let's hunt down anything that implies users will have to supply Module(library=true) and kill it or identify why.

cc @benjchristensen

Skip Query parameters when value is null

Currently, when a @QueryParam value is specified, and the user passes null, there's a literal null in the http request. Using as close to JAX-RS and URI-Template semantics as we can, we should allow the client (only in jax-rs) to skip a query parameter on null.

implement Observable

making this v4 so that we can delete IncrementalCallback :)

If viewed in the light that Iterator is to Observer as Iterable is to Observable, the essential relationships needed to make a functional Observer pattern are relatively tight.

  • add Subscription interface, with a single method unsubscribe() which means "stop giving me stuff!"
  • rename IncrementalCallback to Observer
  • return Subscription on methods that accept an Observer param.
    • This is the Async equiv to returning a lazy Iterator from a single http request
    • ex. `Subscription contributors(String account, String repo, Observer contributors);
  • allow Observable as a return type
    • Observer has a single method: Subscription subscribe(Observer<T> observer);
    • each time subscribe is called, a new http request is sent and the observer observes that.
    • This is the Async equiv to an Iterable, where each Iterator is a new http request

Support binary request bodies

There are cases where it may be useful to submit binary content as the body for a request. Examples of this include uploading files or using content encodings (such as compression).

This was first discussed under issue #52.

Remove need to specify overrides = true

When Module(overrides=true) is set, any @Provides(type = SET) methods will override as opposed to adding to ones specified by feign.

This leads to hacks inside ReflectiveFeign like below, which manually enforce a base set of decoders. These cannot be overridden by dagger at all.

      this.decoders.put(void.class, stringDecoder);
      this.decoders.put(Response.class, stringDecoder);
      this.decoders.put(String.class, stringDecoder);

As soon as Dagger 1.1 is out (likely this week), we'll have access to the SET_VALUES feature, which should allow us to eliminate the troublesome Module(overrides=true) features.

With this in, we should update examples and any how-to docs to show how to wire up feign so as to not require or suggest Module(overrides=true), except in very specific cases.

cc @benjchristensen

RibbonClient doesn't support HTTPS

Using the following test - https://gist.github.com/bstick12/2a21ffd30b14ec68716f#file-ribbonclienttest

You will see the following exception raised in the logs

21:04:25.583 [pool-1-thread-2] DEBUG c.n.l.LoadBalancerExecutor - Got error java.net.SocketException: Unexpected end of file from server when executed on server api.github.com:443

This is due to the request being made to http://api.github.com:443/.

The URI created in RibbonClient does include a scheme and eventually com.netflix.loadbalancer.LoadBalancerContext.deriveSchemeAndPortFromPartialUri(URI) will default the scheme to http.

Disabling exceptions for error statuses when using Response.

As far as I can tell this isn't currently possible. I'm trying to use feign for writing integration tests against an internal service. At the moment I've had to write my own ErrorDecoder to intercept and clone the Response object. It would be much easier from my perspective to disable the exceptions.

I'll try to get it implemented myself. But I'd need a little help with working out why the gradle build doesn't appear to work.
"Artifact 'org.codehaus.plexus:plexus-utils:2.0.5@jar' not found."

I can't even run gradle dependencies to find out what's pulling it in.

Provide easier support for empty targets

In some cases, it may be useful to have Feign instances that don't have any base URL at all. Instead, all methods would include a URI parameter.

Currently, this can be accomplished by using a custom implementation of Target that requires a URL to be provided. I've included an example below. This target can then be passed to Feign.builder().target(Target) Feign.create(Target, Object...).

If such an EmptyTarget were included in feign-core, we could add signatures like Feign.builder().target(Class) that allow creating Feign instances without a base URL and without explicitly specifying a Target type. A signature for Feign.create will require a bit more thought, since Feign.create(Class, Object...) would conflict with the pre-existing Feign.create(Class, String, Object...).

public class EmptyTarget<T> implements Target<T> {
    private final Class<T> type;
    private final String name;

    public EmptyTarget(Class<T> type) {
      this.type = checkNotNull(type, "type");
      this.name = "empty:" + type.getSimpleName();
    }

    @Override
    public Class<T> type() {
        return type;
    }

    @Override
    public String name() {
        return name;
    }

    @Override
    public String url() {
        throw new UnsupportedOperationException("Empty targets don't have URLs");
    }

    @Override
    public Request apply(RequestTemplate input) {
        if (input.url().indexOf("http") != 0) {
            throw new UnsupportedOperationException("Request with non-absolute URL not supported with empty target");
        }
        return input.request();
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(new Object[]{type, name});
    }

    @Override
    public boolean equals(Object obj) {
      if (obj == null) {
          return false;
      }
      if (this == obj) {
          return true;
      }
      if (EmptyTarget.class != obj.getClass()) {
          return false;
      }
      EmptyTarget<?> that = EmptyTarget.class.cast(obj);
      return this.type.equals(that.type) && this.name.equals(that.name);
    }
}

JmxMonitorRegistry race condition with RibbonClient

If you run the following test - https://gist.github.com/bstick12/2a21ffd30b14ec68716f#file-ribbonclienttest

You will occasionally get the the following warning issued from servo.

The com.netflix.loadbalancer.LoadBalancerContext.initWithNiwsConfig(IClientConfig) registers the load balancer and the RibbonClient is recreating the LBClient on each request.

0:44:38.155 [pool-1-thread-2] WARN  c.n.servo.jmx.JmxMonitorRegistry - Unable to register Monitor:MonitorConfig{name=Client_github, tags=class=LBClient, policy=DefaultPublishingPolicy}
javax.management.InstanceNotFoundException: com.netflix.servo:name=github_LoadBalancerExecutionTimer,statistic=max,class=LBClient,type=GAUGE,id=Client_github,unit=MILLISECONDS
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1095) ~[na:1.7.0_72]
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.exclusiveUnregisterMBean(DefaultMBeanServerInterceptor.java:427) ~[na:1.7.0_72]
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.unregisterMBean(DefaultMBeanServerInterceptor.java:415) ~[na:1.7.0_72]
    at com.sun.jmx.mbeanserver.JmxMBeanServer.unregisterMBean(JmxMBeanServer.java:546) ~[na:1.7.0_72]
    at com.netflix.servo.jmx.JmxMonitorRegistry.register(JmxMonitorRegistry.java:82) ~[servo-core-0.7.4.jar:na]
    at com.netflix.servo.jmx.JmxMonitorRegistry.register(JmxMonitorRegistry.java:106) ~[servo-core-0.7.4.jar:na]
    at com.netflix.servo.DefaultMonitorRegistry.register(DefaultMonitorRegistry.java:135) [servo-core-0.7.4.jar:na]
    at com.netflix.servo.monitor.Monitors.registerObject(Monitors.java:207) [servo-core-0.7.4.jar:na]
    at com.netflix.loadbalancer.LoadBalancerContext.initWithNiwsConfig(LoadBalancerContext.java:111) [ribbon-loadbalancer-2.0-RC5.jar:na]
    at com.netflix.loadbalancer.LoadBalancerContext.<init>(LoadBalancerContext.java:82) [ribbon-loadbalancer-2.0-RC5.jar:na]
    at com.netflix.loadbalancer.LoadBalancerExecutor.<init>(LoadBalancerExecutor.java:45) [ribbon-loadbalancer-2.0-RC5.jar:na]
    at com.netflix.client.AbstractLoadBalancerAwareClient.<init>(AbstractLoadBalancerAwareClient.java:54) [ribbon-loadbalancer-2.0-RC5.jar:na]
    at feign.ribbon.LBClient.<init>(LBClient.java:47) [feign-ribbon-7.2.0.jar:7.2.0]
    at feign.ribbon.RibbonClient.lbClient(RibbonClient.java:76) [feign-ribbon-7.2.0.jar:7.2.0]
    at feign.ribbon.RibbonClient.execute(RibbonClient.java:64) [feign-ribbon-7.2.0.jar:7.2.0]
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:95) [feign-core-7.2.0.jar:7.2.0]
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:74) [feign-core-7.2.0.jar:7.2.0]
    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:101) [feign-core-7.2.0.jar:7.2.0]
    at com.brendan.atlassian.$Proxy6.users(Unknown Source) [na:na]
    at com.brendan.atlassian.RibbonClientTest$1.run(RibbonClientTest.java:56) [test-classes/:na]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [na:1.7.0_72]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.