com.apollographql.apollo.exception.ApolloParseException: 无法解析 http 响应

com.apollographql.apollo.exception.ApolloParseException: Failed to parse http response

我收到针对特定配置文件查询的 "Failed to parse http response" 异常。从日志中可以看出,数据似乎已通过 200 OK 响应成功读取,但控制转到了查询的 onFailure。

  1. 在此查询之前,程序成功运行 mutation,没有任何问题。
  2. 只有配置文件查询发出异常。
  3. 并且此查询在服务器上也运行良好。

日志:

2019-09-23 16:57:45.431 27729-28889/com.sed.RP D/OkHttp: --> POST https://rf-xxx-xxxxxxxxx.com/
2019-09-23 16:57:45.432 27729-28889/com.sed.RP D/OkHttp: Content-Length: 329
2019-09-23 16:57:45.432 27729-28889/com.sed.RP D/OkHttp: Content-Type: application/json
2019-09-23 16:57:45.432 27729-28889/com.sed.RP D/OkHttp: Accept: application/json
2019-09-23 16:57:45.432 27729-28889/com.sed.RP D/OkHttp: X-APOLLO-OPERATION-ID: 7572eb1080830d1b4c285bb96f09ac5ad2417ab45fcb701d5d9608593f95874c
2019-09-23 16:57:45.432 27729-28889/com.sed.RP D/OkHttp: X-APOLLO-OPERATION-NAME: profile
2019-09-23 16:57:45.433 27729-28889/com.sed.RP D/OkHttp: Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ZDdmY2E4NmVmMGFiMzAwMjRjNTk3NWIiLCJyb2xlIjoiVEVBQ0hFUiIsImVtYWlsIjoiaXRhYmR1bGxhaC5zZWRAZ21haWwuY29tIiwibW9iaWxlIjoiMDEyMzQ1Njc4OSIsImNvdW50cnlDb2RlIjoiS1NBIiwiaXNzdWVkQXQiOiIyMDE5LTA5LTIzVDExOjI3OjQ1LjA2NFoiLCJpYXQiOjE1NjkyMzgwNjUsImV4cCI6MTU2OTg0Mjg2NX0.3LNNSPenLuMGmOxdD_9KKoqrKo0eyPkWe0qx8MZjZME
2019-09-23 16:57:45.433 27729-28889/com.sed.RP D/OkHttp: X-APOLLO-CACHE-KEY: dbde9fb84c5eda4a362f8db542fef516
2019-09-23 16:57:45.433 27729-28889/com.sed.RP D/OkHttp: X-APOLLO-CACHE-FETCH-STRATEGY: NETWORK_ONLY
2019-09-23 16:57:45.433 27729-28889/com.sed.RP D/OkHttp: X-APOLLO-EXPIRE-TIMEOUT: 0
2019-09-23 16:57:45.433 27729-28889/com.sed.RP D/OkHttp: X-APOLLO-EXPIRE-AFTER-READ: false
2019-09-23 16:57:45.433 27729-28889/com.sed.RP D/OkHttp: X-APOLLO-PREFETCH: false
2019-09-23 16:57:45.434 27729-28889/com.sed.RP D/OkHttp: X-APOLLO-CACHE-DO-NOT-STORE: false
2019-09-23 16:57:45.435 27729-28889/com.sed.RP D/OkHttp: {"operationName":"profile","variables":{},"query":"query profile($_id:ID) {  profile(_id:$_id) {    __typename    _id    fullName    firstName    lastName    email    classDetails {      __typename      _id      className      section      subjectName    }    academicYear {      __typename      startYear      endYear    }  }}"}
2019-09-23 16:57:45.435 27729-28889/com.sed.RP D/OkHttp: --> END POST (329-byte body)
2019-09-23 16:57:46.960 27729-28889/com.sed.RP D/OkHttp: <-- 200 OK https://rf-xxx-xxxxxxxxxxx/ (1524ms)
2019-09-23 16:57:46.960 27729-28889/com.sed.RP D/OkHttp: Server: Cowboy
2019-09-23 16:57:46.960 27729-28889/com.sed.RP D/OkHttp: Connection: keep-alive
2019-09-23 16:57:46.960 27729-28889/com.sed.RP D/OkHttp: X-Powered-By: Express
2019-09-23 16:57:46.960 27729-28889/com.sed.RP D/OkHttp: Access-Control-Allow-Origin: *
2019-09-23 16:57:46.961 27729-28889/com.sed.RP D/OkHttp: Content-Type: application/json
2019-09-23 16:57:46.961 27729-28889/com.sed.RP D/OkHttp: Content-Length: 937
2019-09-23 16:57:46.961 27729-28889/com.sed.RP D/OkHttp: Date: Mon, 23 Sep 2019 11:27:46 GMT
2019-09-23 16:57:46.961 27729-28889/com.sed.RP D/OkHttp: Via: 1.1 vegur
2019-09-23 16:57:46.962 27729-28889/com.sed.RP D/OkHttp: {"data":{"profile":{"__typename":"User","_id":"5d7fca86ef0ab30024c5975b","fullName":"Mohamed Abdullah K","firstName":"Mohamed Abdullah","lastName":"K","email":"itabdullah.sed@gmail.com","classDetails":[{"__typename":"ClassDetails","_id":"5d8740e72c34b80024a8e31d","className":"tula","section":"2014","subjectName":"embedded"},{"__typename":"ClassDetails","_id":"5d8748ac2c34b80024a8e337","className":"tula","section":"2014","subjectName":"embedded"},{"__typename":"ClassDetails","_id":"5d8748d92c34b80024a8e338","className":"miah","section":"2018","subjectName":"maths"},{"__typename":"ClassDetails","_id":"5d87537e2c34b80024a8e33a","className":"Miah","section":"Tula","subjectName":"First"},{"__typename":"ClassDetails","_id":"5d88656336c2360024d0deb8","className":"IT","section":"2017","subjectName":"Arabic"}],"academicYear":{"__typename":"AcademicYear","startYear":"2012-01-01T00:00:00.000Z","endYear":"2013-01-01T00:00:00.000Z"}}}}
2019-09-23 16:57:46.962 27729-28889/com.sed.RP D/OkHttp: <-- END HTTP (937-byte body)

我的查询:

RequestHeaders requestHeaders = RequestHeaders.builder().addHeader(LoginActivity.AUTHORIZATION, bearerTokenTest).build();
        ProfileQuery profileQuery = ProfileQuery.builder().build();
        ApiClient.getMyApolloClient().query(profileQuery)
                .requestHeaders(requestHeaders)
                .enqueue(new ApolloCall.Callback<ProfileQuery.Data>() {
                    @Override
                    public void onResponse(@NotNull Response<ProfileQuery.Data> response) {

                        if (response.data() != null) {
                            Timber.e("onResponse: %s", response.data().profile()._id());
                            //processResponse(response);
                        }
                        if (!response.errors().isEmpty())
                            Timber.e("onResponse error: %s", response.errors().get(0).message());
                    }

                    @Override
                    public void onFailure(@NotNull ApolloException e) {
                        Timber.e("onFailure: %s", e.toString());
                        //processFailure();
                    }
                });

Graphql:

query profile($_id:ID){
    profile(_id:$_id){
        _id
        fullName
        firstName
        lastName
        email
        classDetails{
            _id
            className
            section
            subjectName
        }
        academicYear{
            startYear
            endYear
        }
    }
}

Apollo 客户端:


public class ApiClient {

    private static final String BASE_URL = "https://rf-xxxx.x.com";
    public static ApolloClient apolloClient;

    public static ApolloClient getMyApolloClient() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.level(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

        apolloClient = ApolloClient.builder()
                .serverUrl(BASE_URL)
                .okHttpClient(client)
                .build();
        return apolloClient;
    }

}

gradle:

buildscript {

    repositories {
        google()
        jcenter()
        maven { url "https://jitpack.io" } //comment if necessary
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.0'
        classpath 'com.apollographql.apollo:apollo-gradle-plugin:1.1.3'
        classpath 'com.apollographql.apollo:apollo-gradle-plugin:1.2.0-SNAPSHOT'


        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files

    }
}

感谢您的任何建议。

从堆栈跟踪中发现,这是 Apollo Client Builder 中缺少 "Custom DATE Type Adapter" 的问题。

java.lang.IllegalArgumentException: Can't map GraphQL type: Date to: class java.lang.Object. Did you forget to add custom type adapter?
    at com.apollographql.apollo.response.ScalarTypeAdapters.adapterFor(ScalarTypeAdapters.java:30)
    at com.apollographql.apollo.internal.response.RealResponseReader.readCustomType(RealResponseReader.java:193)

我已经将如下所示的自定义类型适配器添加到 Apollo Client Builder 中,现在它工作正常。


public static ApolloClient getMyApolloClient() {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'", Locale.US);
    CustomTypeAdapter dateCustomTypeAdapter = new CustomTypeAdapter<Date>() {
        @Override
        public Date decode(CustomTypeValue value) {
            try {
                return dateFormat.parse(value.value.toString());
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public CustomTypeValue encode(Date value) {
            return new CustomTypeValue.GraphQLString(dateFormat.format(value));
        }
    };

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.level(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

    apolloClient = ApolloClient.builder()
            .serverUrl(BASE_URL)
            .okHttpClient(client)
            .addCustomTypeAdapter(CustomType.DATE, dateCustomTypeAdapter)
            .build();
    return apolloClient;
}