I'm trying to get my around a current issue I'm facing.
I have a function that returns an Optional type (an object with a few properties)
One of the properties is an url that might be present or not. I extract that url in order to make an HTTP request
injectedClass.method(tenant.clientKey()).flatMap(optionalProperty ->
optionalProperty.ifPresentOrElse(fi -> {
Blocking.get(() -> httpClientProvider.withHttpClient((HttpClient httpClient) ->
httpClient.request(URI.create(optionalProperty.webTriggerUrl()), (RequestSpec spec) -> {
LogstashMarker markers = append("webTriggerUrl", fi.webTriggerUrl()).and(append("method", "Post").and(append("behaviour", objectMapper.writeValueAsString(baseDTO))));
logger.debug(markers, "Executed a Post request to something webTriggerUrl");
spec.method(HttpMethod.POST);
spec.getBody().type(HttpHeaderValues.APPLICATION_JSON).text(objectMapper.writeValueAsString(baseDTO), CharsetUtil.UTF_8);
final MutableHeaders headers = spec.getHeaders();
headers
.set(HttpHeaderNames.USER_AGENT, userAgent);
headers.set(CorrelationId.HEADER_NAME, correlationId.id());
})
)).then(resp -> logger.info("ok"));
}, () -> logger.error("something"))
Blocking.get brings back a Promise and I get an error in my code basically saying that the expected return type of ifPresentOrElse
should be void and not Promise
Is there a functional and better way to achieve this?
CodePudding user response:
Yes there are ways, but you also have to decide what to do if the Optional
is empty. Currently you want to return a Promise
if the optional is present, and return nothing ("void") if it is empty. This doesn't work, the types for both branches need to be the same.
You can just use optionalProperty.map()
to map your original Optional
to a Optional<Promise>
, and then use ifPresentOrElse
, to do something with either the Promise or with the empty Optional, e.g. logging as you seem to be doing in your case.
But you also have a higher-level flatMap
which I'm unclear from which type it is. Does this flatmap a Promise
? Then you must return a Promise also from the other branch of the optional, and you could use optionalProperty.map(...).orElse( <create empty Promise here> )
.
Also check out orElseGet()
instead of orElse()
, if you want to create the empty branch lazily (via Supplier
).
CodePudding user response:
ifPresentOrElse
returns void
. What you probably want is a combination of map
and orElseGet
:
optionalProperty.map(/* code to return a Promise */)
.orElseGet(() -> /* code to return a Promise that is immediately resolved */);
Inside the supplier to orElseGet()
you can put your logger.error
statement.