在 Quarkus 上,我尝试使用动态 baseUrl 构建反应式微配置文件 REST 客户端,但到目前为止,在所有实现变体中,REST 调用在订阅后都会阻塞。有趣的是,非响应式实现就像一个魅力。让我们看一些代码...
REST 客户端界面:
package ...;
import io.smallrye.mutiny.Uni;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.util.concurrent.CompletionStage;
import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
@Path("")
public interface RetrievalRestApi {
@GET
@Produces(APPLICATION_OCTET_STREAM)
Uni<InputStream> retrieve();
@GET
@Produces(APPLICATION_OCTET_STREAM)
InputStream retrieve2(); // non-reactive, the only one that works...
@GET
@Produces(APPLICATION_OCTET_STREAM)
Uni<Response> retrieve3();
@GET
@Produces(APPLICATION_OCTET_STREAM)
CompletionStage<InputStream> retrieve4();
}
Quarkus 测试:
package ...;
import io.quarkus.test.junit.QuarkusTest;
import io.smallrye.mutiny.Uni;
import org.apache.commons.io.IOUtils;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.function.Consumer;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@QuarkusTest
class RetrievalRestApiTest {
private URL restUrl;
@BeforeEach
void setUp() throws MalformedURLException {
restUrl = new URL("https://some-valid-url");
}
@Test
void testRetrieve() {
Uni<InputStream> uni = RestClientBuilder.newBuilder()
.baseUrl(restUrl)
.build(RetrievalRestApi.class)
.retrieve()
.onFailure().invoke((Consumer<Throwable>) System.out::println);
InputStream inputStream = uni.subscribe()
.withSubscriber(UniAssertSubscriber.create())
.await()
.assertCompleted()
.getItem();
assertNotNull(inputStream);
}
@Test
void testRetrieve2() throws IOException {
InputStream inputStream = RestClientBuilder.newBuilder()
.baseUrl(restUrl)
.build(RetrievalRestApi.class)
.retrieve2();
assertNotNull(inputStream);
String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
assertNotNull(content);
}
@Test
void testRetrieve3() {
Uni<Response> uni = RestClientBuilder.newBuilder()
.baseUrl(restUrl)
.build(RetrievalRestApi.class)
.retrieve3()
.onFailure().invoke((Consumer<Throwable>) System.out::println);
Response response = uni.subscribe()
.withSubscriber(UniAssertSubscriber.create())
.await()
.assertCompleted()
.getItem();
assertNotNull(response);
}
@Test
void testRetrieve4() {
Uni<InputStream> uni = Uni.createFrom().completionStage(RestClientBuilder.newBuilder()
.baseUrl(restUrl)
.build(RetrievalRestApi.class)
.retrieve4())
.onFailure().invoke((Consumer<Throwable>) System.out::println);
InputStream inputStream = uni.subscribe()
.withSubscriber(UniAssertSubscriber.create())
.await()
.assertCompleted()
.getItem();
assertNotNull(inputStream);
}
}
在运行 4 个测试时,只有使用非反应式 API 的 testRetrieve2 是成功的。所有其他人都挂在 AssertSubscriber.await() 中。
有任何想法吗?