-
Notifications
You must be signed in to change notification settings - Fork 7.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Retrofit 2.0 API Spec (Working Draft) #297
Comments
guys. this is great. looking forward to helping |
Looks awesome. Love that Callbacks now become part of the real api, at compile-time. |
Any examples of what error handling may look like in 2.0? |
@austynmahoney I'm tempted to revert a bit back to pre-1.0 days with multiple callback methods. Something like this: public interface Callback<T> {
void success(T result); // 2XX responses
void networkError(IOException e); // IOException from underlying input stream
void unexpectedError(Exception e); // Error from converter or internal Retrofit error.
void httpError(int status, ...); // non-2XX responses
} What do you think? |
Or maybe! public interface Callback<T> {
void success(T result); // 2XX responses
}
public interface ErrorCallback {
void networkError(IOException e); // IOException from underlying input stream
void unexpectedError(Exception e); // Error from converter or internal Retrofit error.
void httpError(int status, ...); // non-2XX responses
class EmptyErrorCallback implements ErrorCallback {
@Override public void networkError(IOException e) {}
@Override public void unexpectedError(Exception e) {}
@Override public void httpError(int status, ...) {}
}
} |
Just from what I see here, I'd say the second form seems preferable to me. A bit more granular control over errors vs success, and allows independent re-use of callbacks as needed. |
I'd be really interested in seeing plans related to the support for different authentication mechanisms (i.e. oauth). Any thoughts on that? |
Presumably the request and response interceptor/replacement would be enough to enable that. I have no plans to work on anything around oauth, digest, or the like myself. It will have to be contributed during the 2.0 development. |
I would like to suggest that the Synchronous request: Response <Tweet> r = api.listTweets("JakeWharton");
List<Tweet> tweets = r.get(); Asynchronous request: Response <Tweet> r = api.listTweets("JakeWharton");
r.get(new Callback<List<Tweet>>() {
@Override public void onSuccess(List<Tweet> response) { }
}); Asynchronous request (Observable): Response <Tweet> r = api.listTweets("JakeWharton");
r.get(new ObservableCallback<Tweet>() {
@Override public void onNext(Tweet tweet) { }
// ...
}); I think this way of doing it would make it clearer what is happening for someone not familiar with the library. It also makes it clearer that you are done with the Regarding the error handling i very much like what @JakeWharton suggested in his latest comment. I would however make a suggestion to remove the |
I like the new One thing I am worried about though is what the code will look like when you try to figure out the difference between a I agree with @emilsjolander. The Just to make sure, 3xx responses are not getting passed into |
Another thing I'd like to see in 2.0 is generic error handling. Right now the handler you can add to class GenericErrorCallback implements ErrorCallback {
@Override public void networkError(IOException e) {...}
@Override public void unexpectedError(Exception e) {...}
@Override public void httpError(int status, ...) {
if(status == HTTP_401) {
// Do something
}
// We need something here like a boolean or return type so the error can be propagated to the ErrorCallback on the actual request.
}
} |
I think ObservableCallback should be named Observer and the method that Observer would have an onError(Throwable). I'm not sure about the mutli ErrorCallback yet and would need to play with I wonder if we could do a working design that could be published from a On Friday, August 9, 2013, Emil Sjölander wrote:
|
A 2.0 alpha release would be nice to play around with. This way we see how it feels using the new API in a real app. |
Just hit a spot in an app I am working on where a |
Absolutely agree callback void needs to be supported for this case. On Friday, August 9, 2013, Austyn Mahoney wrote:
|
Thoughts about Observer Seems to work well enough for nice json lists from an RPC response (ex public void intoObserver(TypedInput body, Type type, Observer<? super Object> observer, AtomicBoolean subscribed) throws ConversionException {
JsonReader jsonReader = new JsonReader(body.in(), charset);
jsonReader.beginArray();
while (subscribed.get() && jsonReader.hasNext()) {
observer.onNext(fromJson(jsonReader, type));
}
} So, this would emit each item in the array to the observer. Cool.. works.. saves reaction time, which could be seconds or longer. On the other hand, "streaming" apis don't always have nice or similar json forms (think tweet blobs or newline). This could lead to confusing converter code. Further, anytime we touch or even think about IO, we'd have to think about the impact on IncrementalConverter, which if not widely used, could be wasted cycles. This is compounded if folks interested in Observing things switch to message oriented or multiplexed protocols which have less need to send really long streams of things (which is what the incremental parsing optimizes for). In short, I'm thinking just supporting Callback in 2.0 would be better than investing in Observer in our base model. |
Dropped observable from the spec. Added error callback interface (still needs description). |
I think the callback can be an abstract class:
Though not as pure as an interface, this approach is ergonomic. You can handle all error types together, or you can handle each kind independently. This is the approach I'm considering for OkHttp. Whatever we do here, we should probably do similarly in OkHttp. |
I think you should rename
I prefer |
OkHttp knows about transport which is much more important. Things like SPDY On Wed, Apr 29, 2015 at 5:22 PM Hannes Dorfmann notifications@github.com
|
@YuriHeupa I know you are asking for a proper cancel mechanism, I am waiting for it too. But for now this works perfectly for me, I am sure you might be doing something similar, if not, have a look at this. Just extend from this
CallBackManager:
Usage:
|
@mwajeeh |
Most of this was done in #845. For everything else there's separate issues tracking it. |
when i can get this with graddle? |
@Tooto You can get the 2.0 snapshot from the Sonatype's snapshots repository, just add the following to your gradle file:
And declare this on your dependencies:
|
But be aware that the 2.0 API is far from stable and moving fast at the moment ;) |
is there a separate issue for tracking the error handling implementation? |
Error handlers can be implemented as CallAdapters. There will be an example. On Tue, Jun 16, 2015 at 12:58 AM Felipe Lima notifications@github.com
|
@jdreesen @JakeWharton @YuriHeupa, can the source code of 2.0 preview be seen somewhere ? |
master On Thu, Jul 2, 2015, 6:10 PM Stéphane Nicolas notifications@github.com
|
Wow :) Cool. Thx. Eager to try that. |
You cite Dagger 2. Google approached us about them spearheading Dagger 2 On Fri, Aug 7, 2015, 2:18 AM Chang Yu-heng notifications@github.com wrote:
|
Sorry. No offense, it's a experimental project. The naming/building were just following Google Dagger 2 without intention. You can see the description that is copied. Avoid unnecessary politics/ideology issues. I thought to introduce it after some projects tested it, and approach you, ask for advice. It's time. It is at your disposal. What name do you suppose? Or just remove that project. |
Finally we have Canceling in Retrofit. That's awesome. |
Error handlers can be implemented as CallAdapters. There will be an example. Where can I find such an example? |
[Converter!!!]It's better: Sometimes,i just want: |
Hi, I'm a little confused about what state error handlers at are but I've just been thinking about them in the context of autogenerated code. Would it be perhaps possible to define all the possible (known) paths of success (only one) and error (potentially a few) at compile time? Like defining a subclass of a Callback with the error types I want to handle (HTTP 400, HTTP 404, etc) annotated? so something like: retrofit:
custom:
service:
I've not fully thought through the implications how this would be connected up, but it would offer really good compile time guarantees that I've handled the error cases I care about. |
You don't need to generate that, just use an abstract class for your On Tue, Nov 10, 2015, 6:16 AM Sam Duke notifications@github.com wrote:
|
Sure, I mean that it creates a more type-safe way to ensure errors are handled. I can't use the endpoint unless I handle the errors in a callback object and I get the deserialization of error bodies for free too, reducing boilerplace. Otherwise I end up documenting it:
And then handling the error, checking the errortype, deserializing the json. When I say autogenerated, I mean from things like RAML or Swagger. These allow error cases to be defined just as thoroughly as success cases. |
Hi Jack i am facing an issue when i try to run the app for the first time on a new device the first request doesn't execute,i have to send the request again to get the response,i am using retrofit version: retrofit:2.0.0-beta2,and in my code i am send a post request on success of which i am executing the get request,i am not using a custom version of okhttp,i am using the version which is build with retrofit already,i have tested on emulator as well android nexus 6 device.i am using methods like Call.eneque for async processing of request and i am calling these methods on button click without any use of asynctasks...,should i switch back to the previous version or there is issue with my code.waiting for your response, keep up the good work! |
Hey there, |
Consider using an OkHttp application interceptor. |
this OR if your are using Retrofit + RxJava you could use retry or retryWhen operator |
This is a living spec for what will be v2 of Retrofit.
Goals
RestAdapter
or generated interface instance.Changes
Annotation Processors
An annotation processor will be embedded inside the core artifact for compile-time verification of REST API interface declarations.
A second annotation processor will be provided as a separate artifact for full code generation of a class implementation of each API interface.
The
RestAdapter
will always do a read-through cached lookup for the generated classes since it has no knowledge of whether the code-gen processor was used and we don't want to place the burden on the caller either.Request Object
All interface declarations will be required to return an object through which all interaction will occur. The behavior of this object will be similar to a
Future
and will be generic typed (T
) for the success response type (ref: #231).Callers can synchronously call
.execute()
which will return typeT
. Exceptions will be thrown for any error, network error, unsuccessful response, or unsuccessful deserialization of the response body. While these exceptions will likely extend from the same supertype, it's unclear as to whether that supertype should be checked or unchecked.Callers can also supply callbacks to this object for asynchronous notification of the response. The traditional
Callback<T>
of the current version of Retrofit will be available. One change will be that the error object passed tofailure
will not be the same exception as would be thrown in synchronous execution but rather something a bit more transparent to the underlying cause.TODO describe error handling
The call object is also an obvious place for handling the retry and cancelation of requests. Both are a simple, no-args method on the object which can only be called at appropriate times.
cancel()
is a no-op after the response has been received. In all other cases the method will set any callbacks tonull
(thus freeing strong references to the enclosing class if declared anonymously) and render the request object dead. All future interactions with the request object will throw an exception. If the request is waiting in the executor itsFuture
will be cancelled so that it is never invoked.retry()
will re-submit the request onto the backing executor without passing through any of the mutating pipeline described above. Retrying a request is only available after a network error or 5XX response. Attempting to retry a request that is currently in flight, after a non-5XX response, after an unexpected error, or after callingcancel()
will throw an exception.Extension System
In order to facilitate libraries which offer semantics on both synchronous and asynchronous operations without requiring a wrapper, we will introduce a system which we will tentatively refer to as extensions. An extension instance will be registered with the
RestAdapter
and associate itself as handling an explicit interface method return type.By default, Retrofit will install its own extension which handles the aforementioned
Call
type for both synchronous and asynchronous request execution.The current (albeit experimentally denoted) RxJava integration will also be provided as an opt-in extension. This extension will register itself as handling the
Observable
type which will allow the declaration of interfaces which return this type.And more...
TODO!
The text was updated successfully, but these errors were encountered: