How to get String from Mono<String> in reactive java - java

I have a method which accepts Mono as a param.
All I want is to get the actual String from it. Googled but didn't find answer except calling block() over Mono object but it will make a blocking call so want to avoid using block(). Please suggest other way if possible.
The reason why I need this String is because inside this method I need to call another method say print() with the actual String value.
I understand this is easy but I am new to reactive programming.
Code:
public String getValue(Mono<String> monoString) {
// How to get actual String from param monoString
// and call print(String) method
}
public void print(String str) {
System.out.println(str);
}

Getting a String from a Mono<String> without a blocking call isn't easy, it's impossible. By definition. If the String isn't available yet (which Mono<String> allows), you can't get it except by waiting until it comes in and that's exactly what blocking is.
Instead of "getting a String" you subscribe to the Mono and the Subscriber you pass will get the String when it becomes available (maybe immediately). E.g.
myMono.subscribe(
value -> System.out.println(value),
error -> error.printStackTrace(),
() -> System.out.println("completed without a value")
)
will print the value or error produced by myMono (type of value is String, type of error is Throwable). At https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html you can see other variants of subscribe too.

According to the doc you can do:
String getValue(Mono<String> mono) {
return mono.block();
}
be aware of the blocking call

Finally what worked for me is calling flatMap method like below:
public void getValue(Mono<String> monoString)
{
monoString.flatMap(this::print);
}

What worked for me was the following:
monoString.subscribe(this::print);

Simplest answer is:
String returnVal = mono.block();

This should work
String str = monoString.toProcessor().block();

Better
monoUser.map(User::getId)

Related

Kotlin - Is it possible to return a variable from a higher order function?

I have a Kotlin function from a separate library that takes a function as a parameter and gets the variable I need from the callback:
object Session {
fun get(callback: (accessToken: String?) -> Unit): Boolean {
SomeOtherClass(callback).get()
return true
}
}
Then to call it from another class I make the call (in java):
public String getToken() {
Session.INSTANCE.get((accessToken) -> {
// I want the method getToken() to be able to 'return accessToken;'
// but this call back returns Unit and the get method itself returns Boolean
});
}
Is there a way to return the variable accessToken from getToken() directly, or at least the equivalent value? Session.get is async so creating a "global" variable returns null because the value hasn't been assigned yet. This is one thing I have tried:
public String getToken() {
String temp;
Session.INSTANCE.get((accessToken) -> {
temp = accessToken;
});
return temp;
}
Relatively new to functional programming so any help is appreciated!
If the call to get the access token is async then you can't just grab right away. This is because the code inside the get call is running on another thread while your code keeps going. It would look like this:
public String getToken() {
String temp; // 1. you make a variable
Session.INSTANCE.get((accessToken) -> { // 2. get call starts processing
temp = accessToken;
});
return temp; // 3. now you return your uninitialized variable
}
and then after your function ends the token callback happens, but its to late, you already returned nothing. If you run it in a debugger with a break point on each line and keep running you will see the order that the code is executed and it may make more sense.
Your best bet is to just handle what you need in the callback rather than returning it in getToken()...
Not sure if you wanted an answer in kotlin or java but your code may look something like this in kotlin:
Session.get { token ->
onToken(token)
}
where onToken handles whatever code you needed the token for
fun onToken(token: String) {
// do whatever code you would've executed after getToken() here
}
Hope I explained that alright.
You can't return a callback's eventual result from the method that calls it without blocking the thread that made the call. The reason callbacks exist is so you won't block the thread that's making the call. On Android, your app will crash with an Application Not Responding message if you block the main thread for a few seconds.
If you use Kotlin, you can wrap library callbacks using suspendCancellableCoroutine to make them coroutine-compatible. Coroutine suspend functions do allow you to return delayed results.

Java Optional return value only if present

Is it possible to return the Optional value from method only if it's present, but if it's not just continue with a normal method flow. Something like this:
public Message processMessage(Message message) {
// ErrorMessage is subclass of Message; only returned if validator found some violations, otherwise empty optional
Optional<ErrorMessage> error = validator.validate(message);
if (error.isPresent()) return error.get();
// returns different possible subclasses of Message
return service.processMessage(message);
}
Is there any prettier way to write this?
Your problem is indeed that the return types do not match. orElseGet only works when the supplier returns a subtype of the Optional type.
To work around this, you can force a cast to the parent type first:
return error.<Message>map(m -> m).orElseGet(() -> service.processMessage(message));
or equivalently:
return error.map(m -> (Message) m).orElseGet(() -> service.processMessage(message));
I simply would go with Optional.orElseGet and an explicit cast in between:
public Message processMessage(final Message message) {
return validator.validate(message)
.map(Message.class::cast)
.orElseGet(() -> service.processMessage(message));
}
I am not able to test it currently but it may give u an idea, may be you can implement something like below
return Optional.ofNullable(message)
.map(validator::validate)
.orElseGet(service::processMessage)
Looking at that snippet, it looks like the validate method on the validator doesn't quite have the proper return type. Consider using e.g. io.vavr.control.Either or io.vavr.control.Validation monad. Take a look at a possible signature for validate:
Either<SpecificError, ? extends Message> validate(Message message);
Now the map and fold combinators can be used like so:
validator
.validate(message)
.map(message -> service.processMessage(message))
.fold(error -> new ErrorMessage(error), success -> success); // the left function can be replaced by Function.identity()
to yield Message.

Java - sync call inside async thenCompose

Consider below code as I am not able to find better words to ask the question:
CompletionStage<Manager> callingAsyncFunction(int developerId) {
return getManagerIdByDeveloperId(developerId)
.thenCompose(id ->
getManagerById(id, mandatoryComputationToGetManager(id)))
}
mandatoryComputationToGetManager() returns a CompletionStage
Now the doubt which I have is :
I wanted to call mandatoryComputationToGetManager() and after its computation I want getManagerById(...) to be called.
I know there can be one way i.e. calling thenCompose() first to do mandatoryComputationToGetManager() and then do another thenCompose() on previous result for getManagerById(). But I wanted to figure out if there is a way without piping one thenCompose() o/p to another by which I can hold until mandatoryComputationToGetManager() result is ready.
As far as I understand, in the above code getManagerById() will get called even if the result is not yet ready from mandatoryComputationToGetManager(), which I want to wait for so that once mandatoryComputationToGetManager() give the result getManagerById() should get computed asynchronously.
Ideally, we should pipe one thenCompose o/p to another, but there is a way by which we can achieve what you are trying to do.
CompletionStage<String> callingAsyncFunction(int developerId) {
return getManagerIdByDeveloperId(developerId)
.thenCompose(id -> getManagerById(id, mandatoryComputationToGetManager()));
}
private CompletionStage<String> getManagerById(
Integer id, CompletionStage<String> stringCompletionStage) {
return stringCompletionStage.thenApply(__ -> "test");
}
private CompletionStage<String> mandatoryComputationToGetManager() {
return CompletableFuture.completedFuture("test");
}

Java 8 Optional instead of if

I have problem with Optional and I don't know how to handle it.
public void check(String name) {
if (name != null)
doSomething(name);
else
doMore();
}
How to change this if into Optional?
There is a very neat method for that, but present in jdk-9...
public void check(String name){
Optional.ofNullable(name)
.ifPresentOrElse(YourClass::doSomething, YourClass::doMore);
}
assuming doSomething and doMore are static methods... If not an instance should be used, like this::doSomething or this::doMore
While there certainly is a way to create the same code using Optionals (e.g. see Eugene's answer) you should not use Optionals here (imho).
Either you would get the Optional passed into your method which creates a overhead for the caller and does not really make sense looking at why / for what use case Optional was introduced.
Or you would create the Optional yourself inside the method. That is more "okay" but very cumbersome, obscures what is actually happening and I would request it to be changed if I came across it during a code review. Just compare the snippet using an Optional and your current code - your code is probably shorter in terms of characters, it is obvious what is happening. The only upside of using Optionals here is that it seems to become a one-liner which is firstly nothing that is more important than readability and furthermore it is something you could achieve without it anyway if you would add some braces.
Bottom line: Your code is perfectly fine as it is.
There is no reason to change your implementation. There is no way to do what you want in java 8 with an Optional without having an if, while respecting the idea of not using 'map' for side-effects.
I mean, you could have
public void check(String name) {
Optional<String> nameOpt = Optional.ofNullable(name);
nameOpt.ifPresent(n -> doSomething(n));
if (!nameOpt.isPresent()) {
doMore();
}
}
but that has no sense. here you have a good article what Optional tries to resolve (and hence for what it's meant to be used): mainly for return types. Other stuff is just overusing it.
You can avoid if statement by utilizing Java 8 Optional.map() and Optional.orElseGet() methods. Check following example:
import java.util.Optional;
import java.util.function.Consumer;
final class OptionalTestMain {
public static void main(String[] args) {
check("test", str -> {
System.out.println("Yay, string is not null!");
System.out.println("It's: " + str);
}, () -> {
System.out.println("Crap, string is a null...");
System.out.println("There is nothing for me to do.");
});
check(null, str -> {
System.out.println("Yay, string is not null!");
System.out.println("It's: " + str);
}, () -> {
System.out.println("Crap, string is a null...");
System.out.println("There is nothing for me to do.");
});
}
static void check(String str, Consumer<String> ifPresent, Runnable ifNotPresent) {
Optional.ofNullable(str)
.map(s -> { ifPresent.accept(s); return s; })
.orElseGet(() -> { ifNotPresent.run(); return null; });
}
}
It will produce following output:
Yay, string is not null!
It's: test
Crap, string is a null...
There is nothing for me to do.
Method check expects 3 parameters:
a String (it may be null)
a Consumer lambda expression that does something with this value and does not mutate input value.
a Runnable lambda with no parameters to do something when input String is null.
Of course you could easily modify following method and then utilize the whole potential of Optional class, e.g.:
static String checkAndReturn(String str, Function<String, String> ifPresent, Supplier<String> ifNotPresent) {
return Optional.ofNullable(str)
.map(ifPresent)
.orElseGet(ifNotPresent);
}
Then:
System.out.println(checkAndReturn("test", String::toUpperCase, () -> "no value"));
System.out.println(checkAndReturn(null, String::toUpperCase, () -> "no value"));
will produce following output:
TEST
no value
I hope it helps.

How can I verify that one of two methods was called using Mockito?

Suppose I have a class with two methods where I don't care which is called...
public class Foo {
public String getProperty(String key) {
return getProperty(key, null);
}
public String getProperty(String key, String defaultValue) {
//...
}
}
Both the below (from another class, still in my application) should pass my test:
public void thisShouldPass(String key) {
// ...
String theValue = foo.getProperty(key, "blah");
// ...
}
public void thisShouldAlsoPass(String key) {
// ...
String theValue = foo.getProperty(key);
if (theValue == null) {
theValue = "blah";
}
// ...
}
I don't care which was called, I just want one of the two variants to be called.
In Mockito, I can generally do things like this:
Mockito.verify(foo, atLeastOnce()).getProperty(anyString());
Or:
Mockito.verify(foo, atLeastOnce()).getProperty(anyString(), anyString());
Is there a native way to say "verify either one or the other occurred at least once"?
Or do I have to do something as crude as:
try {
Mockito.verify(foo, atLeastOnce()).getProperty(anyString());
} catch (AssertionError e) {
Mockito.verify(foo, atLeastOnce()).getProperty(anyString(), anyString());
}
You could use atLeast(0) in combination with ArgumentCaptor:
ArgumentCaptor<String> propertyKeyCaptor = ArgumentCaptor.forClass(String.class);
Mockito.verify(foo, atLeast(0)).getProperty(propertyKeyCaptor.capture(), anyString());
ArgumentCaptor<String> propertyKeyCaptor2 = ArgumentCaptor.forClass(String.class);
Mockito.verify(foo, atLeast(0)).getProperty(propertyKeyCaptor2.capture());
List<String> propertyKeyValues = propertyKeyCaptor.getAllValues();
List<String> propertyKeyValues2 = propertyKeyCaptor2.getAllValues();
assertTrue(!propertyKeyValues.isEmpty() || !propertyKeyValues2.isEmpty()); //JUnit assert -- modify for whatever testing framework you're using
Generally, if you're calling verify on a "getter" of any sort, you're assuming too much about the implementation. Mockito is generally designed for flexible tests (compared to "brittle" test that need to change even if the code is correct); your test should care more about whether the value is correct as opposed to which methods were used to get that value. A better solution might be to stub both getters to return a predictable value, and then use a normal assertion against the same value to ensure it plumbs through to the correct place.
when(mockFoo.getProperty("bar")).thenReturn("bar value");
when(mockFoo.getProperty("bar", anyString())).thenReturn("bar value");
// ...
assertEquals("bar value", new SystemUnderTest(mockFoo).getBarProperty());
Mockito's documentation spells this out:
Although it is possible to verify a stubbed invocation, usually it's just redundant. Let's say you've stubbed foo.bar(). If your code cares what foo.bar() returns then something else breaks (often before even verify() gets executed). If your code doesn't care what get(0) returns then it should not be stubbed.
That said, if this is a pattern you're required to support (or a method call with both overloads and side-effects) you can get a lot of information via Mockito.mockingDetails and MockingDetails.getInvocations, including invocations as of Mockito 1.10.0. You would need to loop through the Invocation objects to check against multiple methods.
boolean found = false;
Method method1 = Foo.class.getMethod("getProperty", String.class);
Method method2 = Foo.class.getMethod("getProperty", String.class, String.class);
for (Invocation invocation : Mockito.mockingDetails(foo).getInvocations()) {
if (method1.equals(invocation.getMethod())
|| method2.equals(invocation.getMethod()) {
found = true;
break;
}
}
assertTrue("getProperty was not invoked", found);
Note that this second solution is a little dangerous, as it does not benefit from automatic refactoring tools built into IDEs, and may be harder to read than some other solutions. (The above may also be missing calls to isIgnoredForVerification, markVerified, and other niceties.) However, if you foresee needing this frequently across a large codebase, then using Mockito's built-in APIs may afford you much more flexibility than you would have otherwise.
In your particular case, getProperty(String) calls getProperty(String, String) internally.
public String getProperty(String key) {
/*
* getProperty(String, String) is called anyway.
* Why not simply verify the occurrence of that?
*/
return getProperty(key, null);
}
Simply verifying the second method would be equivalent to verifying the occurrence of either one or the other at least once.
Mockito.verify(foo, atLeastOnce()).getProperty(anyString(), anyString());

Categories