Skip to content

Commit

Permalink
Fix null Response.getEntity in REST Reactive
Browse files Browse the repository at this point in the history
  • Loading branch information
gastaldi committed Aug 27, 2024
1 parent de779d8 commit 819ec81
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,18 @@ public Object getEntity() {
checkClosed();
// this check seems very ugly, but it seems to be needed by the TCK
// this will likely require a better solution
if (entity instanceof GenericEntity) {
GenericEntity<?> genericEntity = (GenericEntity<?>) entity;
if (entity instanceof GenericEntity genericEntity) {
if (genericEntity.getRawType().equals(genericEntity.getType())) {
return ((GenericEntity<?>) entity).getEntity();
}
}
return entity;
return entity == null ? entityStream : entity;
}

protected void setEntity(Object entity) {
this.entity = entity;
if (entity instanceof InputStream) {
this.entityStream = (InputStream) entity;
if (entity instanceof InputStream inputStream) {
this.entityStream = inputStream;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.quarkus.it.rest.client.main;

import java.net.URI;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
Expand All @@ -10,6 +12,7 @@
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.resteasy.reactive.RestResponse;
Expand Down Expand Up @@ -260,6 +263,24 @@ void init(@Observes Router router) {
rc.response().setStatusCode(500).end(e.getCause().getClass().getSimpleName());
}
});

router.post("/preserve-response-entity").blockingHandler(rc -> {
String url = rc.body().asString();
JAXRSResponseClient client = QuarkusRestClientBuilder.newBuilder().baseUri(URI.create(url))
.build(JAXRSResponseClient.class);
Response response = client.call();
Response newResponse = Response.fromResponse(response).build();
rc.response().end(newResponse.getEntity().toString());
});

router.post("/preserve-response-entity-async").blockingHandler(rc -> {
String url = rc.body().asString();
final JAXRSResponseClient client = QuarkusRestClientBuilder.newBuilder().baseUri(URI.create(url))
.build(JAXRSResponseClient.class);
Response response = client.asyncCall().await().atMost(Duration.of(5, ChronoUnit.SECONDS));
rc.response().end(response.getEntity().toString());
});

}

private Future<Void> success(RoutingContext rc, String body) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.quarkus.it.rest.client.main;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import io.smallrye.mutiny.Uni;

@Path("/client-logger")
@RegisterRestClient(configKey = "w-client-logger")
public interface JAXRSResponseClient {

@GET
Response call();

@GET
Uni<Response> asyncCall();
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package io.quarkus.it.rest.client;

import static io.restassured.RestAssured.get;
import static io.restassured.RestAssured.given;
import static io.restassured.RestAssured.with;
import static java.util.stream.Collectors.counting;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
import static org.awaitility.Awaitility.await;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;

import java.time.Duration;
import java.util.List;
Expand Down Expand Up @@ -40,26 +41,26 @@ public class BasicTest {

@Test
public void shouldMakeTextRequest() {
Response response = RestAssured.with().body(helloUrl).post("/call-hello-client");
Response response = with().body(helloUrl).post("/call-hello-client");
assertThat(response.asString()).isEqualTo("Hello, JohnJohn");
}

@Test
public void shouldMakeJsonRequestAndGetTextResponse() {
Response response = RestAssured.with().body(helloUrl).post("/call-helloFromMessage-client");
Response response = with().body(helloUrl).post("/call-helloFromMessage-client");
assertThat(response.asString()).isEqualTo("Hello world");
}

@Test
public void restResponseShouldWorkWithNonSuccessfulResponse() {
Response response = RestAssured.with().body(helloUrl).post("/rest-response");
Response response = with().body(helloUrl).post("/rest-response");
assertThat(response.asString()).isEqualTo("405");
}

@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
void shouldMakeJsonRequest() {
List<Map> results = RestAssured.with().body(appleUrl).post("/call-client")
List<Map> results = with().body(appleUrl).post("/call-client")
.then()
.statusCode(200)
.contentType("application/json")
Expand All @@ -73,50 +74,50 @@ void shouldMakeJsonRequest() {

@Test
void shouldRetryOnFailure() {
RestAssured.with().body(appleUrl).post("/call-client-retry")
with().body(appleUrl).post("/call-client-retry")
.then()
.statusCode(200)
.body(equalTo("4"));
}

@Test
void shouldLogWithExplicitLogger() {
RestAssured.with().body(baseUrl).post("/call-client-with-explicit-client-logger")
with().body(baseUrl).post("/call-client-with-explicit-client-logger")
.then()
.statusCode(200);
}

@Test
void shouldLogWithGlobalLogger() {
RestAssured.with().body(baseUrl).post("/call-client-with-global-client-logger")
with().body(baseUrl).post("/call-client-with-global-client-logger")
.then()
.statusCode(200);
}

@Test
void shouldLogCdiWithGlobalLogger() {
RestAssured.with().body(baseUrl).post("/call-cdi-client-with-global-client-logger")
with().body(baseUrl).post("/call-cdi-client-with-global-client-logger")
.then()
.statusCode(200);
}

@Test
void shouldMapException() {
RestAssured.with().body(baseUrl).post("/call-client-with-exception-mapper")
with().body(baseUrl).post("/call-client-with-exception-mapper")
.then()
.statusCode(200);
}

@Test
void shouldMapExceptionCdi() {
RestAssured.with().body(baseUrl).post("/call-cdi-client-with-exception-mapper")
with().body(baseUrl).post("/call-cdi-client-with-exception-mapper")
.then()
.statusCode(200);
}

@Test
void shouldInterceptDefaultMethod() {
RestAssured.with().body(baseUrl).post("/call-with-fault-tolerance")
with().body(baseUrl).post("/call-with-fault-tolerance")
.then()
.statusCode(200)
.body(equalTo("Hello fallback!"));
Expand All @@ -125,13 +126,13 @@ void shouldInterceptDefaultMethod() {
@Test
void shouldApplyInterfaceLevelInterceptorBinding() {
for (int i = 0; i < 2; i++) {
RestAssured.with().body(baseUrl).post("/call-with-fault-tolerance-on-interface")
with().body(baseUrl).post("/call-with-fault-tolerance-on-interface")
.then()
.statusCode(200)
.body(equalTo("ClientWebApplicationException"));
}

RestAssured.with().body(baseUrl).post("/call-with-fault-tolerance-on-interface")
with().body(baseUrl).post("/call-with-fault-tolerance-on-interface")
.then()
.statusCode(200)
.body(equalTo("CircuitBreakerOpenException"));
Expand All @@ -142,7 +143,7 @@ void shouldCreateClientSpans() {
// Reset captured traces
RestAssured.given().when().get("/export-clear").then().statusCode(200);

Response response = RestAssured.with().body(helloUrl).post("/call-hello-client-trace");
Response response = with().body(helloUrl).post("/call-hello-client-trace");
assertThat(response.asString()).isEqualTo("Hello, MaryMaryMary");

String serverSpanId = null;
Expand Down Expand Up @@ -243,12 +244,29 @@ void shouldCreateClientSpans() {

@Test
public void shouldConvertParamFirstToOneUsingCustomConverter() {
RestAssured.with().body(paramsUrl).post("/call-params-client-with-param-first")
with().body(paramsUrl).post("/call-params-client-with-param-first")
.then()
.statusCode(200)
.body(equalTo("1"));
}

@Test
void shouldPreserveResponseEntity() {
with().body(baseUrl).post("/preserve-response-entity")
.then()
.statusCode(200)
.body(is(notNullValue()));
}

@Test
void shouldPreserveResponseEntityAsync() {
with().body(baseUrl).post("/preserve-response-entity-async")
.then()
.log().all()
.statusCode(200)
.body(is(notNullValue()));
}

private List<Map<String, Object>> getServerSpansFromPath(final String spanName, final String urlPath) {
return get("/export").body().as(new TypeRef<List<Map<String, Object>>>() {
}).stream()
Expand Down

0 comments on commit 819ec81

Please sign in to comment.