0
votes

I am requesting a web-service API with Retrofit 2 library. I have the following code for URL of API:

String ENDPOINT = "https://api.trakt.tv/";

@GET("movies/popular?limit=10&extended=full,images")
public Observable<PopularMoviesResponse> getPopularMovies(@Header("trakt-api-version") String trakt_api_version,
                                                  @Header("trakt-api-key") String trakt_api_key,
                                                  @Query("page") String page);

I am using the above method in:

public Observable<List<PopularMovies>> fetchPopularMovies(String trakt_api_version,
                                                          String trakt_api_key,
                                                          String page) {
    return movieService
            .getPopularMovies(trakt_api_version, trakt_api_key, page)
            .concatMap(new Func1<PopularMoviesResponse, Observable<? extends List<PopularMovies>>>() {
                @Override
                public Observable<? extends List<PopularMovies>> call(final PopularMoviesResponse popularMoviesResponse) {
                    Log.d("uuuuuu", "oooooo");
                    return Observable.create(new Observable.OnSubscribe<List<PopularMovies>>() {
                        @Override
                        public void call(Subscriber<? super List<PopularMovies>> subscriber) {
                            Log.d("uuuuuu", "oooooo");
                            try {
                                if (subscriber.isUnsubscribed()) return;
                                subscriber.onNext(popularMoviesResponse.getPopularMovies());
                                subscriber.onCompleted();
                            } catch (Exception e) {
                                subscriber.onError(e);
                            }
                        }
                    });

                }
            });
}

Log data tell that the http status code is 200, and okhttp logs response normally. However in the second snippet of code the logs are not reached! What's the problem?

Update,

This is the code that subscribes to the observable:

public void getPopularMovies(final String page) {
    mDataManager.fetchPopularMovies(TraktAPI.TRAKT_API_VERSION.getValue(), TraktAPI.TRAKT_API_KEY.getValue(), page)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(new Observer<List<PopularMovies>>() {
                @Override
                public void onCompleted() {
                }

                @Override
                public void onError(Throwable e) {
                    mMvpView.showEmpty();
                }

                @Override
                public void onNext(List<PopularMovies> popularMoviesList) {
                    Log.d("onNext", "pppppppppppp");
                    mMvpView.showListOfPopularMovies(popularMoviesList);
                }
            });
}

I have logged the onError in subscription code, I got the following stacktrace:

07-20 12:15:16.547 2056-2056/org.unrwa.edits W/System.err: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
07-20 12:15:16.548 2056-2056/org.unrwa.edits W/System.err:     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:221)
07-20 12:15:16.549 2056-2056/org.unrwa.edits W/System.err:     at com.google.gson.TypeAdapter.fromJson(TypeAdapter.java:260)
07-20 12:15:16.549 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:33)
07-20 12:15:16.549 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:23)
07-20 12:15:16.550 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:154)
07-20 12:15:16.550 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.OkHttpCall.execute(OkHttpCall.java:118)
07-20 12:15:16.550 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:107)
07-20 12:15:16.551 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:88)
07-20 12:15:16.551 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:162)
07-20 12:15:16.552 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:154)
07-20 12:15:16.552 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:162)
07-20 12:15:16.552 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:154)
07-20 12:15:16.553 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:162)
07-20 12:15:16.553 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:154)
07-20 12:15:16.553 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:162)
07-20 12:15:16.554 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:154)
07-20 12:15:16.555 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:162)
07-20 12:15:16.555 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:154)
07-20 12:15:16.556 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable.unsafeSubscribe(Observable.java:8098)
07-20 12:15:16.556 2056-2056/org.unrwa.edits W/System.err:     at rx.internal.operators.OperatorSubscribeOn$1$1.call(OperatorSubscribeOn.java:62)
07-20 12:15:16.556 2056-2056/org.unrwa.edits W/System.err:     at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
07-20 12:15:16.557 2056-2056/org.unrwa.edits W/System.err:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
07-20 12:15:16.557 2056-2056/org.unrwa.edits W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
07-20 12:15:16.558 2056-2056/org.unrwa.edits W/System.err:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
07-20 12:15:16.558 2056-2056/org.unrwa.edits W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
07-20 12:15:16.558 2056-2056/org.unrwa.edits W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
07-20 12:15:16.559 2056-2056/org.unrwa.edits W/System.err:     at java.lang.Thread.run(Thread.java:818)

URL of web-service API, can be found using the following link: https://api.trakt.tv/movies/popular?(page=%271%27)&limit=10&extended=full,images

PopularMoviesResponse POJO class

public class PopularMoviesResponse {

private String OdataContext;
private List<PopularMovies> popularMovies = new ArrayList<PopularMovies>();


/**
 * 
 * @param OdataContext
 *     The @odata.context
 */
public void setOdataContext(String OdataContext) {
    this.OdataContext = OdataContext;
}

/**
 * 
 * @return
 *     The value
 */
public List<PopularMovies> getPopularMovies() {
    return popularMovies;
}

/**
 *
 * @param popularMovies
 */
public void setPopularMovies(List<PopularMovies> popularMovies) {
    this.popularMovies = popularMovies;
}

}

PopularMovies class

@Generated("org.jsonschema2pojo") public class PopularMovies {

@SerializedName("title")
@Expose
private String title;
@SerializedName("year")
@Expose
private long year;
@SerializedName("ids")
@Expose
private Ids ids;
@SerializedName("tagline")
@Expose
private String tagline;
@SerializedName("overview")
@Expose
private String overview;
@SerializedName("released")
@Expose
private String released;
@SerializedName("runtime")
@Expose
private long runtime;
@SerializedName("trailer")
@Expose
private String trailer;
@SerializedName("homepage")
@Expose
private String homepage;
@SerializedName("rating")
@Expose
private double rating;
@SerializedName("votes")
@Expose
private long votes;
@SerializedName("updated_at")
@Expose
private String updatedAt;
@SerializedName("language")
@Expose
private String language;
@SerializedName("available_translations")
@Expose
private List<String> availableTranslations = new ArrayList<String>();
@SerializedName("genres")
@Expose
private List<String> genres = new ArrayList<String>();
@SerializedName("certification")
@Expose
private String certification;
@SerializedName("images")
@Expose
private Images images;

/**
 * No args constructor for use in serialization
 * 
 */
public PopularMovies() {
}

/**
 * 
 * @param trailer
 * @param genres
 * @param availableTranslations
 * @param ids
 * @param votes
 * @param runtime
 * @param homepage
 * @param released
 * @param updatedAt
 * @param certification
 * @param title
 * @param overview
 * @param images
 * @param year
 * @param language
 * @param rating
 * @param tagline
 */
public PopularMovies(String title, long year, Ids ids, String tagline, String overview, String released, long runtime, String trailer, String homepage, double rating, long votes, String updatedAt, String language, List<String> availableTranslations, List<String> genres, String certification, Images images) {
    this.title = title;
    this.year = year;
    this.ids = ids;
    this.tagline = tagline;
    this.overview = overview;
    this.released = released;
    this.runtime = runtime;
    this.trailer = trailer;
    this.homepage = homepage;
    this.rating = rating;
    this.votes = votes;
    this.updatedAt = updatedAt;
    this.language = language;
    this.availableTranslations = availableTranslations;
    this.genres = genres;
    this.certification = certification;
    this.images = images;
}

/**
 * 
 * @return
 *     The title
 */
public String getTitle() {
    return title;
}

/**
 * 
 * @param title
 *     The title
 */
public void setTitle(String title) {
    this.title = title;
}

public PopularMovies withTitle(String title) {
    this.title = title;
    return this;
}

/**
 * 
 * @return
 *     The year
 */
public long getYear() {
    return year;
}

/**
 * 
 * @param year
 *     The year
 */
public void setYear(long year) {
    this.year = year;
}

public PopularMovies withYear(long year) {
    this.year = year;
    return this;
}

/**
 * 
 * @return
 *     The ids
 */
public Ids getIds() {
    return ids;
}

/**
 * 
 * @param ids
 *     The ids
 */
public void setIds(Ids ids) {
    this.ids = ids;
}

public PopularMovies withIds(Ids ids) {
    this.ids = ids;
    return this;
}

/**
 * 
 * @return
 *     The tagline
 */
public String getTagline() {
    return tagline;
}

/**
 * 
 * @param tagline
 *     The tagline
 */
public void setTagline(String tagline) {
    this.tagline = tagline;
}

public PopularMovies withTagline(String tagline) {
    this.tagline = tagline;
    return this;
}

/**
 * 
 * @return
 *     The overview
 */
public String getOverview() {
    return overview;
}

/**
 * 
 * @param overview
 *     The overview
 */
public void setOverview(String overview) {
    this.overview = overview;
}

public PopularMovies withOverview(String overview) {
    this.overview = overview;
    return this;
}

/**
 * 
 * @return
 *     The released
 */
public String getReleased() {
    return released;
}

/**
 * 
 * @param released
 *     The released
 */
public void setReleased(String released) {
    this.released = released;
}

public PopularMovies withReleased(String released) {
    this.released = released;
    return this;
}

/**
 * 
 * @return
 *     The runtime
 */
public long getRuntime() {
    return runtime;
}

/**
 * 
 * @param runtime
 *     The runtime
 */
public void setRuntime(long runtime) {
    this.runtime = runtime;
}

public PopularMovies withRuntime(long runtime) {
    this.runtime = runtime;
    return this;
}

/**
 * 
 * @return
 *     The trailer
 */
public String getTrailer() {
    return trailer;
}

/**
 * 
 * @param trailer
 *     The trailer
 */
public void setTrailer(String trailer) {
    this.trailer = trailer;
}

public PopularMovies withTrailer(String trailer) {
    this.trailer = trailer;
    return this;
}

/**
 * 
 * @return
 *     The homepage
 */
public String getHomepage() {
    return homepage;
}

/**
 * 
 * @param homepage
 *     The homepage
 */
public void setHomepage(String homepage) {
    this.homepage = homepage;
}

public PopularMovies withHomepage(String homepage) {
    this.homepage = homepage;
    return this;
}

/**
 * 
 * @return
 *     The rating
 */
public double getRating() {
    return rating;
}

/**
 * 
 * @param rating
 *     The rating
 */
public void setRating(double rating) {
    this.rating = rating;
}

public PopularMovies withRating(double rating) {
    this.rating = rating;
    return this;
}

/**
 * 
 * @return
 *     The votes
 */
public long getVotes() {
    return votes;
}

/**
 * 
 * @param votes
 *     The votes
 */
public void setVotes(long votes) {
    this.votes = votes;
}

public PopularMovies withVotes(long votes) {
    this.votes = votes;
    return this;
}

/**
 * 
 * @return
 *     The updatedAt
 */
public String getUpdatedAt() {
    return updatedAt;
}

/**
 * 
 * @param updatedAt
 *     The updated_at
 */
public void setUpdatedAt(String updatedAt) {
    this.updatedAt = updatedAt;
}

public PopularMovies withUpdatedAt(String updatedAt) {
    this.updatedAt = updatedAt;
    return this;
}

/**
 * 
 * @return
 *     The language
 */
public String getLanguage() {
    return language;
}

/**
 * 
 * @param language
 *     The language
 */
public void setLanguage(String language) {
    this.language = language;
}

public PopularMovies withLanguage(String language) {
    this.language = language;
    return this;
}

/**
 * 
 * @return
 *     The availableTranslations
 */
public List<String> getAvailableTranslations() {
    return availableTranslations;
}

/**
 * 
 * @param availableTranslations
 *     The available_translations
 */
public void setAvailableTranslations(List<String> availableTranslations) {
    this.availableTranslations = availableTranslations;
}

public PopularMovies withAvailableTranslations(List<String> availableTranslations) {
    this.availableTranslations = availableTranslations;
    return this;
}

/**
 * 
 * @return
 *     The genres
 */
public List<String> getGenres() {
    return genres;
}

/**
 * 
 * @param genres
 *     The genres
 */
public void setGenres(List<String> genres) {
    this.genres = genres;
}

public PopularMovies withGenres(List<String> genres) {
    this.genres = genres;
    return this;
}

/**
 * 
 * @return
 *     The certification
 */
public String getCertification() {
    return certification;
}

/**
 * 
 * @param certification
 *     The certification
 */
public void setCertification(String certification) {
    this.certification = certification;
}

public PopularMovies withCertification(String certification) {
    this.certification = certification;
    return this;
}

/**
 * 
 * @return
 *     The images
 */
public Images getImages() {
    return images;
}

/**
 * 
 * @param images
 *     The images
 */
public void setImages(Images images) {
    this.images = images;
}

public PopularMovies withImages(Images images) {
    this.images = images;
    return this;
}

}

JSON response

[ { "title": "The Dark Knight", "year": 2008, "ids": { "trakt": 120, "slug": "the-dark-knight-2008", "imdb": "tt0468569", "tmdb": 155 }, "tagline": "Why So Serious?", "overview": "Batman raises the stakes in his war on crime. With the help of Lt. Jim Gordon and District Attorney Harvey Dent, Batman sets out to dismantle the remaining criminal organizations that plague the streets. The partnership proves to be effective, but they soon find themselves prey to a reign of chaos unleashed by a rising criminal mastermind known to the terrified citizens of Gotham as the Joker.", "released": "2008-07-18", "runtime": 152, "trailer": "http://youtube.com/watch?v=GVx5K8WfFJY", "homepage": "http://thedarkknight.warnerbros.com/dvdsite/", "rating": 9.03781, "votes": 24887, "updated_at": "2016-07-13T10:06:28.000Z", "language": "en", "available_translations": [ "en", "de", "fi", "sv", "zh", "ru", "nl", "it", "fr", "hu", "da", "es", "tr", "pt", "cs", "pl", "bg", "he", "sr", "no", "el", "sk", "ja", "th", "ko", "uk", "fa", "lv", "ro", "id", "bs", "ca" ], "genres": [ "action", "crime", "drama", "thriller" ], "certification": "PG-13", "images": { "fanart": { "full": "https://walter.trakt.us/images/movies/000/000/120/fanarts/original/f7884a908e.jpg", "medium": "https://walter.trakt.us/images/movies/000/000/120/fanarts/medium/f7884a908e.jpg", "thumb": "https://walter.trakt.us/images/movies/000/000/120/fanarts/thumb/f7884a908e.jpg" }, "poster": { "full": "https://walter.trakt.us/images/movies/000/000/120/posters/original/8369bf0d4a.jpg", "medium": "https://walter.trakt.us/images/movies/000/000/120/posters/medium/8369bf0d4a.jpg", "thumb": "https://walter.trakt.us/images/movies/000/000/120/posters/thumb/8369bf0d4a.jpg" }, "logo": { "full": "https://walter.trakt.us/images/movies/000/000/120/logos/original/3e39105d34.png" }, "clearart": { "full": "https://walter.trakt.us/images/movies/000/000/120/cleararts/original/295bcec2cd.png" }, "banner": { "full": "https://walter.trakt.us/images/movies/000/000/120/banners/original/7065417461.jpg" }, "thumb": { "full": "https://walter.trakt.us/images/movies/000/000/120/thumbs/original/6363cb8aeb.jpg" } } },

...

]

1
Are you sure you've subscribed on Observable returns from fetchPopularMovies? Could you please show that part of your code? - Divers
@Divers I've just just updated my post with code. - Androider
Try to log onError in your subscription. Is there anything? Also check if onCompleted been called. - Divers
@Divers I have updated my post. JSON exception. I have the following url: api.trakt.tv/movies/… - Androider
Using Observable.create for this is discouraged. Besides, you don't need concatMap but just map: getPopularMovies(...).map(p -> p.getPopularMovies()). If it still doesn't work get back to us. - akarnokd

1 Answers

2
votes

Please try to change

public Observable<PopularMoviesResponse> getPopularMovies

to

public Observable<List<PopularMovies>> getPopularMovies

Android your method then:

public Observable<List<PopularMovies>> fetchPopularMovies(String trakt_api_version,
                                                          String trakt_api_key,
                                                          String page) {
    return movieService 
            .getPopularMovies(trakt_api_version, trakt_api_key, page)
}

UPD

Just to make sure that your POJO matches of JSON, you can use that service. In that gist you can check full result.