corydissinger / raw4j

Other
48 stars 27 forks source link

Use Retrofit REST client instead of javax.ws.rs package for compatibility on Android #1

Closed abonander closed 11 years ago

abonander commented 11 years ago

Square's Retrofit REST client works on both Android and regular Java, and is a much more declarative way of writing a REST client.

Android does not provide the javax.ws.rs package currently used for networking in the com.cd.reddit.http.requestor.RedditRequestor class. It instead provides the Apache HttpComponents library for low-level networking.

Retrofit uses annotations to provide a beautifully declarative way of interacting with a RESTful service. It would be much simpler than the current implementation. Here is a great example from the library's homepage:

public interface GitHubService {
  @GET("/users/{user}/repos")
  List<Repo> listRepos(@Path("user") String user);
}

RestAdapter restAdapter = new RestAdapter.Builder()
    .setServer("https://api.github.com")
    .build();

GitHubService service = restAdapter.create(GitHubService.class);

List<Repo> repos = service.listRepos("octocat");

Repo is simply a class with fields whose names and types correspond to data values in the JSON response returned by the REST service.

It is typesafe, simple, declarative, and even allows asynchronous execution with callbacks. Callbacks are executed on the UI thread on Android, and on desktop, on the same thread that initiated the request.

corydissinger commented 11 years ago

Certainly looks simple enough.

I'm struggling to understand what the difference is between javax.ws.rs and Apache HttpComponents library other than the obvious Android incompatibility (and JSR below). It looks like Retrofit uses GSON under the hood to handle the JSON parsing.

Whenever I considering using a new dependency, I always wonder what the tradeoffs are. The biggest loss in switching to Retrofit is that GSON and Apache HttpComponents are not JSR-compliant (or am I wrong?)

Jersey/Jackson (which use the javax.ws.rs package) are compliant with the following JSRs

http://jcp.org/en/jsr/detail?id=311 http://jcp.org/en/jsr/detail?id=339 http://jcp.org/en/jsr/detail?id=353

abonander commented 11 years ago

Apache HttpComponents does not provide RESTful network access. It is for direct HTTP programming. RESTful extensions like Retrofit are built on top.

I will admit that I don't exactly understand JSR compliance or why it's important. Yet I doubt Retrofit or HttpComponents are compliant.

I may be wrong, but it looks like the JSRs concern the content of the Java standard library distributed with every install. Effort to comply with JSRs implies intent to be considered for inclusion in the standard lib, at least to me.

That doesn't seem to be an appropriate concern for a Reddit API wrapper.

When considering the addition of a new dependency, I look at how it will make my job easier. Right now, as a prospective user and contributor, I see a lot of boilerplate code in RedditRequestor, and dependency on packages that are not available on my target platform.

The class could be rewritten to allow an Android-compatible networking module to be dropped in under the REST abstraction, but that would require separate implementations for each platform, instead of one unified and ultimately simpler interface.

corydissinger commented 11 years ago

Right now my top priority is making travis-ci execute the Maven build for the Java 1.6 and 1.7 compiler, since 1.6 is still widely used.

After doing that, I'll take a look into using Retrofit. It will definitely make things a lot simpler (in theory) and should hopefully allow raw4j to work on Java 1.6/1.7 as well as they myriad of Android targets (hopefully).

Do you know if Retrofit work on the most prevalent Android versions? If it works on 2.2 and higher, it'll give me a much needed incentive to make this refactor. :)

abonander commented 11 years ago

AFAIK, it works on all API levels. I have only tested 2.3 and up, but 2.2-2.3 had no major change in networking so it should be the same. On Sep 18, 2013 6:48 AM, "corydissinger" notifications@github.com wrote:

Right now my top priority is making travis-ci execute the Maven build for the Java 1.6 and 1.7 compiler, since 1.6 is still widely used.

After doing that, I'll take a look into using Retrofit. It will definitely make things a lot simpler (in theory) and should hopefully allow raw4j to work on Java 1.6/1.7 as well as they myriad of Android targets (hopefully).

Do you know if Retrofit work on the most prevalent Android versions? If it works on 2.2 and higher, it'll give me a much needed incentive to make this refactor. :)

— Reply to this email directly or view it on GitHubhttps://github.com/corydissinger/raw4j/issues/1#issuecomment-24665015 .

corydissinger commented 11 years ago

After playing around with Retrofit for a little while and getting some code working, I realized that the JSON parsing (using Jackson) which already works for all the possible Reddit 'Things' does not really mesh with Retrofit's way of converting things.

So, in order to achieve Android compatibility I'm going continue with the removal of the references to the javax.ws.rs package and use Apache Http Components in conjunction with the existing JSON parsing.

You will see where I realized the existing JSON parsing did not mesh with Retrofit's way of doing things

I made a branch (retrofit-dev) just in case...

abonander commented 11 years ago

Yeah, the best way to implement JSON REST with Retrofit is to write it from scratch and use Retrofit's annotations on data classes to describe the API. You probably don't want to do that.

corydissinger commented 11 years ago

In the next couple of days, I should have a working POC using Apache Http Components - I'll add another comment here when that happens. If you can verify that the API is Android compatibile at that point, I would really appreciate it - then we can really focus on implementing all of the Reddit API calls. :)

abonander commented 11 years ago

Yeah, I can check it. I can even make a quick sample project if you like.

abonander commented 11 years ago

Would it be better to close this issue and open a new one for HttpComponents?

corydissinger commented 11 years ago

Good call. Just realized this issue is titled for Retrofit specifically, and not neccessarily Android compatibility with raw4j. I will close this issue.