I trying to do something with Spring Webflux but I am really confused with some of the reactive concepts.
I have some REST services protected with Form Authentication, before I could call my Business REST Service, I have to call 'login' URL that is provided via Spring Security, pass my credentials and placed the returned Cookie to the further calls to other REST Services.
Below is the Snippet of the call to the REST Business Service....
@RequestMapping(value = "/endpoint1", method = RequestMethod.POST)
public Mono<String> businessService(@RequestBody ApiManagementWrapper apiManagementWrapper, ServerWebExchange httpRequest) {
log.info("Handling /enpoint1");
Mono<String> t = fetch(apiManagementWrapper, httpRequest);
return t;
}
private Mono<String> fetch(ApiManagementWrapper apiManagementWrapper, ServerWebExchange httpRequest) {
return this.webClientProxy
.post()
.uri("http://localhost:8081/something")
.headers(httpHeaders -> httpRequest.getRequest().getHeaders())
.cookies(httpCookies -> httpRequest.getRequest().getCookies())
.body(BodyInserters.fromPublisher(Mono.just(apiManagementWrapper.getEnterpriseMessage()), Object.class))
.exchange()
.flatMap(response -> response.bodyToMono(String.class));
}
which works perfectly my problem is how to combine this to the call login services..
I thought about following login() method...
private void login(ApiManagementWrapper apiManagementWrapper) {
LinkedMultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("username", "user1");
formData.add("password", "user1");
Mono<ClientResponse> response = this.webClientRouteConfirmation
.post()
.uri("http://localhost:8383/login")
.body(BodyInserters.fromFormData(formData))
.exchange();
response.subscribe(clientResponse -> {
handleLogin(clientResponse.cookies().getFirst("JSESSION_ID"), apiManagementWrapper);
});
}
private void handleLogin(ResponseCookie loginCookie, ApiManagementWrapper apiManagementWrapper){
Mono<Route> route = loadRoute(apiManagementWrapper.getEnterptiseContext(), loginCookie);
if(route == null) {
return;
}
}
private Mono<Route> loadRoute(EnterpriseContext enterpriseContext, ResponseCookie loginCookie) {
Mono<Route> route = this.webClientRouteConfirmation
.get()
.uri("http://localhost:8383/routes/search/findByServiceIdAndClientId?serviceName=" + enterpriseContext.getTarget() + "&clientName" + enterpriseContext.getSource())
.cookie("JSESSION_ID", loginCookie.getValue())
.exchange()
.flatMap(clientResponse -> clientResponse.bodyToMono(Route.class));
route.subscribe(r -> {
handleRoute(enterpriseContext, loginCookie);
});
}
with the 'login()' method I can get the 'JSESSION_ID' Cookie but while it returns a Mono I can't access the Cookie value (well I can with clientResponse.block() but I know it is evil so try not to do it), so I tried to subscribe to clientResponse with a callback, but if I try to do that I will be decoupled from the 'businessService()' method and will not able to return the values I like to...
So what I want to achieve as pseudo-code is following....
@RequestMapping(value = "/endpoint1", method = RequestMethod.POST)
public Mono<String> businessService(@RequestBody ApiManagementWrapper apiManagementWrapper, ServerWebExchange httpRequest) {
log.info("Handling /netty1");
Route route = login(apiManagementWrapper);
Mono<String> t = null;
if(route != null) {
t = fetch(apiManagementWrapper, httpRequest);
}
return t;
}
but I have no idea how to go there without using Mono.block()..
It does not make any sense to return 'Route' object from 'handleLogin()' because if I understand Reactive concepts correctly, 'fetch()' method will not wait for it anyway....
Any tips?
Something that you can apply globally:
Mono<T>
or Flux<T>
subscribe
in your web application, since it decouples the execution from the current request/response and gives no guarantee about the completion of that taskYou can then compose those reactive types using the available operators. Something like:
Mono<LoginInformation> login = doLogin();
Mono<String> value = login.flatMap(info -> callRemoteService(info));
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