How to convert List<Mono<String>> into Flux<List<String>>? - java

List<Mono<String>> responses = apiCall()
I would like to get Flux<String> to await all mono-s from list.
How could I achieve it ?
P.S.
I've found similar question but I need vice versa operation https://stackoverflow.com/a/44040346/2674303

You could use Flux.mergeSequential() and Flux.collectList()
Mono<List<String>> list = Flux.mergeSequential(apiCall()).collectList();

Related

Convert Mono<Stream<String>> to Flux<String>

I have a Mono like this Mono<Stream<String>> and I want to convert it to a Flux like this Flux<String>. In my junior mind I think it should be simple because Mono<Stream<String>> is the "hope" for a String and Flux<String> is also the "hope" of a String, therefore there should be a simple operator to do the conversion.
I am new to Spring boot webflux, so if there is an operator for this query just show me or tell me why such operation is not possible.
Mono<Stream<String>> authoritiesStream = Mono.just(Stream.of(""));
Flux<String> authorities = authoritiesStream.???
I don't want to collect() the stream and use flatMapIterable() to do the conversion because collecting would imply that I have lost my asynch edge. Please teach me
Thank you in advance.
Not sure what is the idea behind Mono<Stream<String>> but assuming you are getting it from another method you could do something like
Flux<String> authorities = authoritiesStream
.flatMapMany(stream -> Flux.fromStream(stream));

How to get the index of the Flux.fromIterable

I searched for a long time but couldn't find anything in this topic which can help me in this situation. I have the following code:
return Flux.fromIterable(listOfObjects)
.parallel()
.runOn(Schedulers.parallel())
.flatMap(this::getDataResponse)
.flatMap(dataResponse-> this.afterCheckVariables(dataResponse, {currentElementOfTheList}))
.sequential();
I want to set a variable in every dataResponse based on the current element of the list. Is it possible?
If i could get the index or the current element of the list, it would be great.
Many thanks in advance
May I find a solution, if you have better approach please let me know.
The solution was the following:
I needed to create other method which gives back the current element of the List.
So my code changed like this:
return Flux.fromIterable(listOfObjects)
.parallel()
.runOn(Schedulers.parallel())
.flatMap(this::getReq)
.flatMap(requestObj -> this.getDataResponse(requestObj)
.flatMap(dataResponse-> this.afterCheckVariables(dataResponse,requestObj)))
.sequential();
The getReq method looks like this:
private Mono<ObjectOfList> getReq (ObjectOfList request){
return Mono.just(request);
}

How to filter the filtered stream

I am learning Java8 with stream now.
I got List of CustomDto.
CustomDto has list of CustomDto1.
CustomDto1 has list of CustomDto2.
I need result like this.
List<CustomDto> response = data from read;
response.stream()
.filter(x-> x.getCustomDto1List.stream()
.filter(y-> y.getCustomDto2List.stream()
.filter(z-> z.getCustomDto2.getSomeColumn.equals("XXX"))
)
)
Is it possible ? and If it is, How can I get this result?
Yes, you can but you should use method called anyMatch();
.filter(x-> x.getCustomDto1List.stream()
.anyMatch(y-> y.getCustomDto2List.stream()
.anyMatch(z-> z.getCustomDto2.getSomeColumn.equals("XXX"))
)
)
It looks like you're trying to find all objects which have a certain value in a nested list. Something like this?
response.stream().filter(x -> x.getCustomDto1List.stream()
.flatMap(y-> y.getCustomDto2List.stream())
.anyMatch(z-> z.getSomeColumn.equals("XXX")))
.collect(toList());

Rest Assured - comparing the json path with another

I have json for example below
{"TestJson":{
"Result":"Passed",
"description":"Passed."},
"Students":[{
"Class":{
"Primary":"Yes"
},
"Course":{
"Enrolled":"yes",
"AccountNumber":"2387287382"
},
"AccountNumber":"2387287382",
"Paid":"Yes"
}]}
I am wondering how can I find a good solution for this.
What I currently do
.body("Students[0].Course.AccountNumber",equalTo("2387287382"))
.body("Students[0].AccountNumber",equalTo("2387287382"))
My test criteria is to check key Students[0].AccountNumber matches Students[0].Course.AccountNumber
I want to do in this way, but i am not able to find a solution something like
.body("Students[0].Course.AccountNumber",equalTo("Students[0].AccountNumber"))
The above wont work obviously, but that is how I want to compare. basically comparing the key with another key and they should match.
Is this doable?
One way to do it is:
String A =
given ().
when().
get/put/post({api/name})
.extract()
.path("Students[0].Course.AccountNumber");
String B =
given ().
when().
get/put/post({api/name})
.extract()
.path("Students[0].AccountNumber");
Assert.assertEquals(A, B);
Seems like this workaround is the only way to go.
See the Use the response to verify other parts of the response section of the rest-assured docs. You basically want to create a lambda implementing ResponseAwareMatcher<Response>. Something like this:
get("/x").then().body("href", response -> equalTo("http://localhost:8080/" + response.path("userId"));

Can Java 8 Streams use multiple items from mapping pipeline

I have some data stored in a JPA Repository that I am trying to process. I would like to be able to use Java 8 Streams to do so, but can not figure out how to get the required information. This particular 'Entity' is actually only for recovery, so it holds items that would need to be processed after something like a power-fail/restart.
Using pre-Java 8 for-loops the code would look like:
List<MyEntity> deletes = myEntityJpaRepository.findByDeletes();
for (MyEntity item : deletes) {
String itemJson = item.getData();
// use a Jackson 'objectMapper' already setup to de-serialize
MyEventClass deleteEvent = objectMapper.readValue(itemJson, MyEventClass.class);
processDelete(deleteEvent, item.getId());
}
The problem arises from the two parameter method called at the very end. Using Streams, I believe I would do:
// deletes.stream()
// .map(i -> i.getData())
// .map(event -> objectMapper.readValue(event, MyEventClass.class))
// .forEach(??? can't get 'id' here to invoke 2 parameter method);
I have a solution (without Streams) that I can live with. However I would think this problem comes up a lot, thus my question is: IN GENERAL, is there a way using Streams to accomplish what I am trying to do?
Why not a Pair return on your map operation:
.map(i -> new Pair<>(i.getData(), i.getId()))
.map(pair -> new Pair<>(objectMapper.readValue(pair.getLeft(), MyEventClass.class), pair.getRight())
.forEach(p -> processDelete(pair.getLeft(), pair.getRight()))
I did not compile this, so there might be minor things to fix. But in general, you would need a Holder to pass your objects to the next stage in such a case. Either a Pair or some type or even a array.
Why not doing it simply this way?
deletes.forEach(item ->
processDelete(objectMapper.readValue(item.getData(), MyEventClass.class),
item.getId()));
This is a start at least, I guess it is dependent on why you want to use stream and how much you want to make it more functional
List<MyEntity> deletes = myEntityJpaRepository.findByDeletes();
deletes.stream().foreach(item -> {
String itemJson = item.getData();
// use a Jackson 'objectMapper' already setup to de-serialize
MyEventClass deleteEvent = objectMapper.readValue(itemJson, MyEventClass.class);
processDelete(deleteEvent, item.getId());
});

Categories

Resources