英文:
How to return a value inside or outside a Spring Webflux Mono Subscribe depending on specific test result inside the subscribe
问题
I'm a beginner in Spring Web Flux and in Java Stream.
I need to call a method that returns a Mono twice depending on the result content of the first call.
But I don't know how to make it work and how to respect best practices, i.e., not to have 2 return statements in my method.
Of course, the code below does not work, but I want to show the kind of behavior that I would like to have. But I don't know how to have it in a Stream way...
英文:
I'm a beginner in Spring Web flux and in java Stream.
I need to call a method that returns a Mono twice depending on the result content of the first call.
But I don't know how to make it works and how to respect best practices i.e not to have 2 return statements in my method.
Off course the code below does not work but I want to show the kind of behaviour that I would like to have. But Don't know how to have it in a Stream way...
@Slf4j
@Service
public class Compare {
@Autowired
Myservice myService;
public Mono<MyResponse> compute(String firstItem,String secondItem, String thirdItem){
// First Comparison between firstItem and secondItem
Mono<MyResponse> firstResponse = myService.sendRequestToCompare(firstItem,secondItem);
firstResponse.subscribe(result -> { // Issue on the subscribe method according to my IDE
if ((result.getResponse().getStatus().toString() == "NOT_SAME") && (result.getResponse().getErrorCode() == 201)) {
// Second Comparison with a third value if the previous first one does not match
Mono<MyResponse> secondResponse = myService.sendRequestToCompare(firstItem,thirdItem);
return secondResponse; // Error raised in IDE says change to return; or change method retrun type to Mono<MyResponse> which is already the case
break;
}
}, error -> {
log.error("The following error happened on getResponse method from myService!", error);
});
return firstResponse;
}
}
答案1
得分: 2
你可能需要调用 Mono.flatMap()
。它需要作为参数一个从第一个 Mono 的结果到另一个 Mono 的对象的函数,并返回一个 Mono。如果你正在寻找调用链(调用服务A,然后服务B,并获取服务B的响应)- 这是 Mono.flatMap()
的典型用例。
英文:
You probably have to call Mono.flatMap()
. It requires as an argument a function from the first Mono result to another Mono object and returns Mono. If you are looking for chain of calls (call service A, then service B and get service B response) - that's a typical case for the Mono.flatMap()
.
答案2
得分: 2
我看不到`java.util.stream.*`的使用和需要(虽然它们可以共存/交互,但没有必要复杂化),但这里是你方法的一个(示例,`String`)版本:
public Mono<String> compute(String first, String second, String third) {
Mono<String> firstResponse =
// 仅为演示,实际中调用真实的服务:
Mono.just(first);
return firstResponse.flatMap(s -> { // !
if (s.equals("Hello")) { // 一些(演示)条件
Mono<String> secondResponse =
// 仅为演示,实际中调用真实的服务:
Mono.just(s + second + third);
return secondResponse;
} else {
return Mono.just(";("); // Mono.empty()/抛出异常/...
}
});
}
它:
1. 当`firstResponse`发出的项目等于`"Hello"`时,返回`secondResponse`(即满足某些条件)。
2. 否则返回`Mono`(即“发布者”)的`";("`(伤心表情:)
(去掉注释和(演示)变量后,它是一个“一行代码”)。
这是一个相应的(junit5,反应器)测试的样子:
@Test
void testMyCompute() {
testee.compute("Hello", " World", "!")
.as(StepVerifier::create)
.expectNext("Hello World!")
.verifyComplete();
testee.compute("", "", "")
.as(StepVerifier::create)
.expectNext(";(")
.verifyComplete();
NullPointerException npe = assertThrows(NullPointerException.class,() -> testee.compute(null, null, null));
assertNotNull(npe);
}
因此,重点关注[`flatMap`][1]操作符。
> *异步*转换此Mono发出的项目,返回另一个Mono发出的值
(与[`map`][2]操作符相反,它在*同步*时执行相同的操作,返回*值*(而不是Mono/Publisher)..例如,当`secondResponse`是“阻塞”的/`String`而不是`Mono<String>`时)
有用的链接:
- [核心参考文档(#which-operator?)][3]
- [测试参考文档](https://projectreactor.io/docs/core/release/reference/index.html#testing)
[1]: https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#flatMap-java.util.function.Function-
[2]: https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#map-java.util.function.Function-
[3]: https://projectreactor.io/docs/core/release/reference/#which-operator
英文:
I see no use and need of java.util.stream.*
(though they can co-exist/interact, no need to complicate), but here a (sample, String
) version of your method:
public Mono<String> compute(String first, String second, String third) {
Mono<String> firstResponse =
// just demo, call real service instead:
Mono.just(first);
return firstResponse.flatMap(s -> { // !
if (s.equals("Hello")) { // some (demo) condition
Mono<String> secondResponse =
// just demo, call real service instead:
Mono.just(s + second + third);
return secondResponse;
} else {
return Mono.just(";("); // Mono.empty()/throw exception/...
}
});
}
It:
- returns
secondResponse
, when the item emitted byfirstResponse
equals to"Hello"
(i.e. meets some condition) - otherwise a
Mono
(i.e. "publisher") of";("
(sad emoji:)
(without comments and (demo) variables, it is a "one-liner";)
This how an according (junit5, reactor) test can look like:
@Test
void testMyCompute() {
testee.compute("Hello", " World", "!")
.as(StepVerifier::create)
.expectNext("Hello World!")
.verifyComplete();
testee.compute("", "", "")
.as(StepVerifier::create)
.expectNext(";(")
.verifyComplete();
NullPointerException npe = assertThrows(NullPointerException.class,() -> testee.compute(null, null, null));
assertNotNull(npe);
}
So most attention on flatMap
operator.
>Transform the item emitted by this Mono asynchronously, returning <s>the value emitted by</s> another Mono
(In opposite to map
operator, which does the same synchronously, returning the value (not a Mono/Publisher) ..e.g. when secondResponse
would be "blocking"/String
not Mono<String>
)
Useful Links:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论