ResteasyClientBuilder是一个支持Client pool,SSL context,异步执行的HttpClient Builder。在使用时遇到了奇怪的事情。我在test包下使用
1 | new ResteasyClientBuilder().executorService(Executors.newCachedThreadPool()); |
就没问题,但是在main包下使用上述代码,就出现:
Caused by: org.jboss.resteasy.spi.UnhandledException: java.lang.NoSuchMethodError: org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder.executorService(Ljava/util/concurrent/ExecutorService;)Ljavax/ws/rs/client/ClientBuilder;
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:78)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:222)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:179)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:422)
NoSuchMethodError。我怀疑是项目包依赖的问题,去pom.xml发现依赖是
1 | <dependency> |
之所以用<scope>provided</scope>是因为resteasy-client是Wildfly自带的组件,所以打包项目时不包含resteasy-client,带了反而会出错。
之所以报NoSuchMethodError是因为Wildfly自带的resteasy-client在/home/bejond/codewildfly-10.1.0.Final/modules/system/layers/base/org/jboss/resteasy/resteasy-jaxrs/main/resteasy-client-3.0.19.Final.jar,版本比较旧,是3.0.19.Final。
这个版本里并没有executorService(ExecutorService executorService)。实际上是ResteasyClientBuilder的父类ClientBuilder并没有定义executorService(ExecutorService executorService)。
而test下能正常测试是因为使用的新版本的resteasy-client,我使用的是resteasy-client-3.5.0.Final。而自动化测试是不依赖Web服务器的,所以能正常运行。
pom.xml依赖没写<version>是依赖了父pom。子pom如果要使用别的版本的依赖,加上<version>即可:
1 | <dependency> |
Stackoverflow RESTEasy Client + NoSuchMethodError建议下载最新resteasy-jaxrx包,替换wildfly-10.1.0.Final/modules/system/layers/base/org/jboss/resteasy/resteasy-jaxrs所有的组件。我并没有这么做,一来不确定是否有兼容性问题(Java向下兼容做得很好,一般不会有这个问题。但就怕遇到,排查起来很麻烦),二来加大实施成本。所以我使用降级的方式来做,其实也不算降级,就是使用Wildfly10.1.0.Final自带的包。
这样调整后进入ResteasyClientBuilder就找不到executorService(ExecutorService executorService)了。但是打开ResteasyClientBuilder的源码,发现提示编译错误。
点击ClientBuilder跳到源码发现版本是2.1
2.1版本里的ClientBuilder定义新的抽象方法executorService(ExecutorService executorService),所以提示未实现抽象方法或者将ResteasyClientBuilder改为抽象类错误。
是因为Intellij项目library依赖配置问题,到项目.idea/library下,把Maven__org_jboss_spec_javax_ws_rs_jboss_jaxrs_api_2_1_spec_1_0_0_Final.xml删掉即可。
然后Intellij会自动根据maven依赖增加Maven__org_jboss_spec_javax_ws_rs_jboss_jaxrs_api_2_0_spec_1_0_1_Final.xml文件。
调整好依赖后,test里的测试代码就会对executorService(ExecutorService executorService)标红了。需要将项目代码和test的代码修改为
1 | new ResteasyClientBuilder().asyncExecutor(Executors.newCachedThreadPool()); |
需要注意,asyncExecutor(ExecutorService asyncExecutor)在新版本的resteasy-client包里已经过期,用executorService(ExecutorService executorService)代替。从这个例子也能看出程序设计的问题,低版本方法名定义得随意,到了后期调整为新的名字。实际上executorService直接调用的asyncExecutor,又将asyncExecutor标记为Deprecated。
补充: 在这个例子里如果不使用executorService(ExecutorService executorService),ResteasyClient.build()就会创建10线程固定大小的线程池。那么设定connectionPoolSize(int size)就不会起作用。