Response:
[
{
"version": "1.0",
"content": [
"12345",
"67076",
"123462",
"604340",
"1331999",
"1332608",
"1785581",
]
}
]
Code:
Mono<List<String>> mp = webClient.get().uri(accountMgmtURI)
.retrieve()
.bodyToMono(Map.class)
.flatMap(trans-> {
List<String> content= (List<String>) trans.get("content");
System.out.println("content :: "+content);
return Mono.just(content);
});
System.out.println("content :: "+mp.toString());
String sites=mp.toString();
The first issue is that the API you're using is not returning a single object, but an array of objects, indicated by the square brackets ([]
).
This means you should at least refactor your code to use bodyToFlux()
in stead of bodyToMono()
:
client
.get()
.retrieve()
// bodyToFlux() in stead of bodyToMono(
.bodyToFlux(Map.class)
// ...
The second issue is that it isn't easy to work with a Map
in this case since you would have to cast everything the whole time as you weren't able to pass any generics. Working with a proper class, would make things easier. For example, you could write the following class:
public class VersionContent {
private String version;
private List<String> content;
// TODO: Getters + Setters
}
And change your code to:
client
.get()
.retrieve()
.bodyToFlux(VersionContent.class)
.map(VersionContent::getContent)
.flatMap(Flux::fromIterable)
// ...
This piece of code will retrieve the content for each object, and flatMap
it so that each individual value is emitted separately.
Right now, each item within the content
array would be published individually. This brings us to the third issue, which is that you're not concatenating your strings.
To concat items, you could use the reduce()
operator:
client
.get()
.retrieve()
.bodyToFlux(VersionContent.class)
.map(VersionContent::getContent)
.flatMap(Flux::fromIterable)
// reduce() can be used to merge all individual items to a single item
.reduce((sites, site) -> sites + "|" + site)
// ...
The final issue is that you're using toString()
, which won't work. One of the key aspects of reactive programming is that everything happens asynchronously. That means that if you try to do anything with your data in the main thread, nothing will happen.
Additionally, another feature of publishers like Mono
and Flux
is that they're lazy. Without a proper subscription, nothing will even happen.
The solution is to properly subscribe()
to get your value, for example:
client
.get()
.retrieve()
.bodyToFlux(VersionContent.class)
.map(VersionContent::getContent)
.flatMap(Flux::fromIterable)
.reduce((sites, site) -> sites + "|" + site)
.subscribe(System.out::println);
For your example, the code above would print the following to the console:
12345|67076|123462|604390|1331999|1332608|1785581
Be aware, this also means that every operation you want to do with these sites, should be done asynchronously.
If you don't want to work asynchronously, you can use the block()
operator like this:
String sites = client
.get()
.retrieve()
.bodyToFlux(VersionContent.class)
.map(VersionContent::getContent)
.flatMap(Flux::fromIterable)
.reduce((sites, site) -> sites + "|" + site)
.block();
Please use ready solutions. You should not use List<String> content= (List<String>) trans.get("content")
. Java is strong typing language - so create classes for types. And frameworks as spring works with classes and objects.
At this case:
public class VersionedDataResponse {
private List<VersionedData> versionedDataList;
}
....
public class VersionedData {
private String version;
private List<String> content;
}
And spring will convert it at bodyToMono(VersionedDataResponse.class)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With