In my project I have a requirement where I need to call a third party api authentic url to get the the access token. I need to set that access token in every subsequent request header .The access token has some lifetime and when the lifetime expired I need to regenerate the access token.
application.yml
I have hardcoded the client_id,client_secret,auth_url and grant_type .
AuthController.java
here I have created an endpoint to generate the access token.
**`AuthService.java`**
@Services
@Slf4j
public class AuthService{
@Autowired
private WebClient webClient;
static String accessToken="";
public Mono<SeekResponse> getAccessToken(AuthRequest authRequest) throws InvalidTokenException{
Mono<AuthResponse> authResponse=webClient.post()
.bodyValue(authRequest)
.accept(MediaType.APPLICATION_JSON)
.retrive()
.bodyToMono(AuthResponse.class);
authResponse.doOnNext(response->{
String value=response.getAccess_token();
accessToken=accessToken+value;
})
}
}
Although I have updated the "accessToken" value but it will return me null. I understand as I have made async call this value coming as null. I can't use blocking mechanism here. Is there any other way to generate the access token and pass it as a header for the subsequent request for authentication. Or how can I use the accessToken value globally so that I can set those token value to my subsequent api request call.
I have tried with oAuth2 by following the below article: https://medium.com/@asce4s/oauth2-with-spring-webclient-761d16f89cdd But when I execute I am getting the below error : "An expected CSRF token cannot found".
I'm also learning Webflux. Here's my thought. Please correct me if I'm wrong.
We are not going to rely on doOnNext()
nor doOnSuccess()
nor other similar method to try to work on an pre-defined variable accessToken
(That's not a way to let Mono flow). What we should focus on is converting a mono to another mono, for example converting mono response to mono access token.
The way to do that is .flatmap()
/.map()
/.zipwith()
/...
For example,
Mono<string> tokenMono = responseMono.flatmap(
// in the map or flatmap, we get the chance to operate on variables/objects.
resp -> {
string token = response.getAccess_token();
return Mono.just(token); // with Mono.just(), we are able to convert object to Mono again.
}
) // this example is not practical, as map() is better to do the same thing. flatmap with Mono.just() is meaningless here.
Mono<string> tokenMono2 = responseMono.map(
resp -> {
string token = response.getAccess_token();
return token;
}
)
Everything starting from Mono should be always Mono until subscribed or blocked. And they provide us ways to operate on those variables
inside Mono<variables>
. Those are map()
flatmap()
, zipwith()
, etc.
https://stackoverflow.com/a/60105107/18412317
Referring to a point this author said, doOnNext()
is for side effect such as logging.