java - Spring RestTemplate & AsyncRestTemplate with Netty4 hangs forever -
very simple setup:
pom.xml
<?xml version="1.0" encoding="utf-8"?> <project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com.example</groupid> <artifactid>demo-rest-client</artifactid> <version>0.0.1-snapshot</version> <packaging>jar</packaging> <name>demo-rest-client</name> <description>demo project spring boot</description> <parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>1.4.1.release</version> <relativepath/> <!-- lookup parent repository --> </parent> <properties> <project.build.sourceencoding>utf-8</project.build.sourceencoding> <project.reporting.outputencoding>utf-8</project.reporting.outputencoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>io.netty</groupid> <artifactid>netty-all</artifactid> <version>4.1.5.final</version> </dependency> <dependency> <groupid>io.netty</groupid> <artifactid>netty-buffer</artifactid> <version>4.1.5.final</version> </dependency> <dependency> <groupid>com.squareup.okhttp3</groupid> <artifactid>okhttp</artifactid> <version>3.4.1</version> </dependency> <dependency> <groupid>io.github.openfeign</groupid> <artifactid>feign-core</artifactid> <version>9.3.1</version> </dependency> <dependency> <groupid>io.github.openfeign</groupid> <artifactid>feign-hystrix</artifactid> <version>9.3.1</version> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-test</artifactid> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-maven-plugin</artifactid> </plugin> </plugins> </build> </project>
and test case demonstrate different usages of asyncresttemplate:
sampletests.java
package com.example; import com.netflix.hystrix.hystrixcommand; import com.netflix.hystrix.hystrixcommandproperties; import feign.requestline; import feign.hystrix.hystrixfeign; import feign.hystrix.setterfactory; import org.junit.test; import org.springframework.http.responseentity; import org.springframework.http.client.netty4clienthttprequestfactory; import org.springframework.http.client.okhttp3clienthttprequestfactory; import org.springframework.util.concurrent.listenablefuture; import org.springframework.web.client.asyncresttemplate; import org.springframework.web.client.resttemplate; public class sampletests { private static final string url = "https://api.github.com/users/octocat"; private static final int default_sleep_millis = 20; private static final int default_timeout = 10000; @test(timeout = default_timeout) public void syncrestnetty() throws exception { resttemplate resttemplate = new resttemplate(new netty4clienthttprequestfactory()); responseentity<string> response = resttemplate.getforentity(url, string.class); system.out.println("response = " + response); } @test(timeout = default_timeout) public void asyncrestnetty() throws exception { asyncresttemplate resttemplate = new asyncresttemplate(new netty4clienthttprequestfactory()); listenablefuture<responseentity<string>> listenablefuture = resttemplate.getforentity(url, string.class); listenablefuture.addcallback(result -> system.out.println("result = " + result), throwable::printstacktrace); while (!listenablefuture.isdone()) { thread.sleep(default_sleep_millis); } system.out.println("the end"); } @test public void asyncrestokhttp() throws exception { asyncresttemplate resttemplate = new asyncresttemplate(new okhttp3clienthttprequestfactory()); listenablefuture<responseentity<string>> listenablefuture = resttemplate.getforentity(url, string.class); listenablefuture.addcallback(result -> system.out.println("result = " + result), throwable::printstacktrace); while (!listenablefuture.isdone()) { thread.sleep(default_sleep_millis); } system.out.println("the end"); } @test public void asyncresthystrixfeign() throws exception { github github = hystrixfeign.builder() .setterfactory((target, method) -> new setterfactory.default().create(target, method).andcommandpropertiesdefaults(hystrixcommandproperties.defaultsetter().withexecutiontimeoutinmilliseconds(10000))) .target(github.class, "https://api.github.com"); hystrixcommand<string> command = github.octocatasync(); command.toobservable().subscribe(result -> system.out.println("result = " + result), throwable::printstacktrace); while (!command.isexecutioncomplete()) { thread.sleep(default_sleep_millis); } system.out.println("command.getexecutiontimeinmilliseconds() = " + command.getexecutiontimeinmilliseconds()); system.out.println("the end"); } interface github { @requestline("get /users/octocat") hystrixcommand<string> octocatasync(); } }
when trying run tests use netty hang forever. (to see please remove junit timeout constraint). if run exact same code other clients works expected.
i have tried different versions of spring boot , netty did not succeed. , logs looks ok.
what missing here?
edit: opened ticket https://jira.spring.io/browse/spr-14744 suggested on spring gitter
edit-2: answer brian clozel helped me find issue related netty not realizing server sent empty response (a particular case github api , plain http) marking accepted.
can try configure request factory netty sslcontext?
netty4clienthttprequestfactory nettyfactory = new netty4clienthttprequestfactory(); nettyfactory.setsslcontext(sslcontextbuilder.forclient().build()); asyncresttemplate resttemplate = new asyncresttemplate(nettyfactory);
without context, client trying send plaintext requests https endpoint; in case, you're getting http 400 response.
in example code, throwable
should instance of httpclienterrorexception
, , information logging response status or body exception.getresponsebodyasstring()
.
Comments
Post a Comment