very big problem since 48h00.
with postman, absolutly no problem to post my body. return is 200.
there is no authentication with concerned api.
but, when i use my java-code, always 400 is returned !!!!
String baseUrl = "myBaseUrl";
String uri = "myUri";
WebClient webClient = WebClient.create(baseUrl);
ClientResponse cresponse = webClient
.post()
.uri(uri)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.syncBody(myObject)
.exchange()
.block();
// always 400!!!! here !!!!!!!
System.out.println("result :" + cresponse.statusCode());
Probably something wrong with "myObject".
I think the problem is the way in you are feeding the body in your request. Use Mono.just to create a mono to feed the body as shown below
webClient.post().body(Mono.just(myObject)), MyObject.class).exchange().block().statusCode();
Related
I have to request data from an API but the API needs a JSON in the request body and it has to be sent using the GET method. My project uses the Java 11 HttpClient library so I want solutions that only include using this library. How do I send the body in GET method?
HttpRequest request = HttpRequest.newBuilder(uri)
.header("Content-Type", "application/json")
.GET(BodyPublishers.ofString(jsonObject.toString()))
.build();
HttpClient client = AppHttpClient.getInstance();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
Code issue
Builder class doesn't have a predefined GET method with the ability to pass request body. In this case just use more generic approach:
HttpRequest request = HttpRequest.newBuilder(uri)
.header("Content-Type", "application/json")
.method("GET", BodyPublishers.ofString(jsonObject.toString()))
.build();
HttpClient client = AppHttpClient.getInstance();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
General
Usually, passing body in the GET request is not recommended, so I would recommend reconsidering your API design. Instead of a body, you can use URL query parameters or think about using the POST method if the request body is quite big and can't be mapped to the query parameters.
I have recently upgraded my project to the latest version of spring-boot 2.5.0 and got going with refactoring a ton of deprecated code. I noticed that awaitExchange() has now been deprecated and should be replaced with awaitExchange{it}
However, as soon as I replaced one with the other it appears I can no longer extract the body from the ClientResponse object by response.awaitBody() in a different class and keep getting No value received via onNext for awaitSingle. Is such behaviour by design?
Is there any other way to actually get hold of the body without having to use `
awaitExchange{ it.awaitBody() } in the class that makes the webservice call?
Since you did not show your code its hard to say what is the issue. But you can use WebClient in following ways
val client = WebClient.create()
val data: MultiValueMap<String, String> = LinkedMultiValueMap()
data["username"] = "johndoe"
data["target_site"] = "aloha"
client.create()
.post()
.uri("some uri")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(BodyInserters.fromFormData(data))
.retrieve()
.awaitBodyOrNull<String>() ?: throw Exception("Received null response")
Another way to do is
val response = client.get()
.uri("some uri")
.contentType(MediaType.APPLICATION_JSON)
.retrieve()
.toEntity(String::class.java)
.awaitSingle()
if (!response.statusCode.is2xxSuccessful) {
throw Exception("Received ${response.statusCodeValue} response.")
}
I am working on a Spring boot project that uses Spring Webclient to do a GET request on a URL which has a 3xx redirection. Using webclient to do the GET request to that url gives 200 response. I would like to stop at the redirection and get a header named "location" from there.
I tried the following code and I am getting a null in response.
WebClient webclient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create().followRedirect(false)
)).build();
#GetMapping("/")
Mono<Object> webclientTest2() throws URISyntaxException {
return webclient.get()
.uri("https://URL_THAT_HAS_REDIRECTION")
.exchange()
.flatMap(res -> {
Headers headers = res.headers();
System.out.println("Status code: "+res.statusCode());
headers.asHttpHeaders().forEach((k,v) -> {
System.out.println(k+" : "+v);
});
return Mono.just(headers.asHttpHeaders().get("location"));
});
}
Webclient isnt stopping at 3xx redirection. The System.out.println statement shows only Status code: 200 and some headers from the next System.out.println statement. How can I get that location header from that 3xx redirection?
Note: One interesting observation I made is using the httpclient instead of webclient is able to retrieve the location header.
HttpClient httpclient = HttpClient.create().followRedirect(false);
I developed a Java library for Twitter API here using OkHttp3 4.8.1.
Unfortunately, it looks like after having sent a request, once everything is finished, the program never stops and is stuck in SocketInputStream.
When not using cache, it is stuck in waitForReferencePendingList method of Reference class instead :
I tried everything, closing connection explicitly in my code like this, updating the version of OkHttp, but still the same. Any idea ?
If needed, here is the full code where the request is done, in summary :
Request request = new Request.Builder()
.url(url)
.get()
.headers(Headers.of("Authorization", "Bearer " + bearerToken))
.build();
OkHttpClient client = new OkHttpClient.Builder().build()
Response response = client.newCall(request).execute();
String stringResponse = response.body().string();
return Optional.ofNullable(TwitterClient.OBJECT_MAPPER.readValue(stringResponse, classType));
Finally adding client.connectionPool().evictAll(); elsewhere (in my post request to get a bearer token) solved the problem !
how to re-use webclient client response? I am using webclient for synchronous request and response. I am new to webclient and not sure how to extract response body in multiple places
WebClient webClient = WebClient.builder().baseUrl("http://localhost:8080").build();
below is my call to API which returns valid response
ClientResponse clientResponse;
clientResponse = webClient.get()
.uri("/api/v1/data")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.block();
How to use clientResponse in multiple places? only one time I am able to extract response body
String response = clientResponse.bodyToMono(String.class).block(); // response has value
When I try to extract the response body second time (in a different class), it's null
String response = clientResponse.bodyToMono(String.class).block(); // response is null
So, can someone explain why response is null second time and how to extract the response body multiple times?
WebClient is based on Reactor-netty and the buffer received is one time thing.
One thing you could do is to cache the result at the first time and then reuse it.
You can refer to this issue in spring cloud gateway: https://github.com/spring-cloud/spring-cloud-gateway/issues/1861
Or refer to what Spring Cloud gateway do for caching request body: https://github.com/spring-cloud/spring-cloud-gateway/blob/master/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/AdaptCachedBodyGlobalFilter.java
Or you can write your code like:
String block = clientResponse.bodyToMono(String.class).block();
And next time you can use this body:
Mono.just(block);