Unable to create call adapter for rx.Observable<java.util.Map<java.lang.String, java.lang.Object>>

  • Post author:
  • Post category:java


Unable to create call adapter for rx.Observable



异常描述

最近按照相关介绍,使用Retrofit进行Http请求处理,并按照其使用说明,定义如下请求接口。

interface NacosOperatorFunc {

    @POST("auth/users/login")
    rx.Observable<Map<String, Object>> nacosLogin(@Query("username") String username, @Query("password") String password);

    @GET("console/server/state")
    rx.Observable<Map<String, Object>> nacosVersion(@Query("accessToken") String accessToken, @Query("username") String userName);
}

然后,创建Retrofit,并执行请求。

protected Retrofit createRetrofit() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    return new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .baseUrl("http://localhost:8848/nacos/v1/")
            .addConverterFactory(JacksonConverterFactory.create(objectMapper))
            .build();
}

@Test
public void test() {
    this.createRetrofit().create(NacosOperatorFunc.class).nacosLogin("nacos", "nacos").forEach(System.out::println);
}

执行test方法时,方法抛出如下异常

java.lang.IllegalArgumentException: Unable to create call adapter for rx.Observable<java.util.Map<java.lang.String, java.lang.Object>>
    for method NacosOperatorFunc.nacosLogin

	at retrofit2.Utils.methodError(Utils.java:54)
	at retrofit2.HttpServiceMethod.createCallAdapter(HttpServiceMethod.java:116)
	at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:67)
	at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:39)
	at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:202)
	at retrofit2.Retrofit$1.invoke(Retrofit.java:160)
	at com.quelongjiang.nacos.config.rxjava.example.$Proxy4.nacosLogin(Unknown Source)
	at com.quelongjiang.nacos.config.rxjava.example.RxJavaHttpExample.test(RxJavaHttpExample.java:93)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for rx.Observable<java.util.Map<java.lang.String, java.lang.Object>>.
  Tried:
   * retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
   * retrofit2.CompletableFutureCallAdapterFactory
   * retrofit2.DefaultCallAdapterFactory
	at retrofit2.Retrofit.nextCallAdapter(Retrofit.java:272)
	at retrofit2.Retrofit.callAdapter(Retrofit.java:237)
	at retrofit2.HttpServiceMethod.createCallAdapter(HttpServiceMethod.java:114)
	... 28 more



问题原因

一顿百度后,给出解决措施是,是依赖版本不对引起。但是,上述代码依赖的版本一致,且都是2.9.0版本。初步分析,应该不是版本问题引起。

<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>retrofit</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>adapter-rxjava2</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>converter-jackson</artifactId>
    <version>2.9.0</version>
</dependency>

无赖之下,自力更生,自行debug,寻求原因。根据异常信息,断点到retrofit2.Retrofit.nextCallAdapter(Retrofit.java:272)处。

在这里插入图片描述

由于方法返回值类型定义为Observable,因此将关注点放到RxJava2CallAdapterFactory上。get方法处,其内部,通过判断returnType确定是否使用该Factory创建CallAdapter

在这里插入图片描述

此时问题,在于接口定义的返回值为rx.Observable,而get方法内部判断使用的Observable为io.reactivex.Observable。从而完美的错过了这个Factory。



解决方法

通过上述分析得知,Retrofit请求接口的返回值,若定义为 Observable,该类型需为io.reactivex.Observable,于是,接口定义修改如下所示

interface NacosOperatorFunc {

    @POST("auth/users/login")
    Observable<Map<String, Object>> nacosLogin(@Query("username") String username, @Query("password") String password);

    @GET("console/server/state")
    Observable<Map<String, Object>> nacosVersion(@Query("accessToken") String accessToken, @Query("username") String userName);
}

此时Observable为io.reactivex.Observable。

再次执行test方法,成功获取请求结果

在这里插入图片描述



后记

特此记录该异常解决信息,用于提醒自己,后续查阅相关资料时,要确定其所使用的类,避免浪费时间在不应该出现的问题上。



版权声明:本文为weixin_46053046原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。