-
Notifications
You must be signed in to change notification settings - Fork 8
Expected
Expected
is a similar concept to Optional
in Java JDK and Option
in Scala.
We added a new concept because this one is expected to come through callbacks and is used in places where Optional
does not make sense. Also Reakt wants to use interfaces for all core concepts so others
can provide their own implementations. In addition we wanted consumers for ifPresent
and ifEmpty
.
A Expected
contains an value object which may or may not be set. This is like {@code Optional} but could be the value from an async operation. If a value is present, isPresent()
will return true
and get()
will return the value. Expected
is heavily modeled after optional (java.util.Optional
).
final Expected<Employee> empty = Expected.empty();
... //OR
final Expected<Employee> empty = Expected.ofNullable(null);
...
//isEmpty isPresent
assertTrue( empty.isEmpty() );
assertFalse( empty.isPresent() );
//ifEmpty ifPresent
empty.ifEmpty(() -> logger.info("Empty"));
empty.ifPresent(employee -> logger.info("Employee", employee));
//empty get throws a NoSuchElementException for empty expected
try {
empty.get();
reject();
} catch (NoSuchElementException nsee) {
}
final Expected<Employee> rick = Expected.ofNullable(new Employee("Rick"));
... //OR
final Expected<Employee> rick = Expected.of(new Employee("Rick"));
...
//ifEmpty ifPresent
rick.ifEmpty(() -> logger.info("Empty"));
rick.ifPresent(employee -> logger.info("Employee", employee));
//Convert employee into a sheep using map
final Sheep sheep = rick.map(employee -> new Sheep(employee.id)).get();
assertEquals("Rick", sheep.id);
//Use Filter
assertTrue(
rick.filter(employee -> employee.id.equals("Rick")
).isPresent()); //Rick is Rick
assertFalse(
rick.filter(employee -> employee.id.equals("Bob")
).isPresent()); //Rick is not Bob
package io.advantageous.reakt;
import org.junit.Test;
import java.util.NoSuchElementException;
import java.util.Optional;
import static org.junit.Assert.*;
public class ExpectedTest {
@Test
public void testEmpty() {
final Expected<Employee> empty = Expected.empty();
emptyTest(empty);
}
@Test
public void testEmptyFromNull() {
final Expected<Employee> empty = Expected.ofNullable(null);
emptyTest(empty);
}
@Test
public void testNotEmptyFromNullable() {
final Expected<Employee> rick = Expected.ofNullable(new Employee("Rick"));
notEmptyTest(rick);
}
@Test
public void testNotEmpty() {
final Expected<Employee> rick = Expected.of(new Employee("Rick"));
notEmptyTest(rick);
}
@Test
public void testNotEmptyFromOptional() {
final Expected<Employee> rick = Expected.ofOptional(Optional.of(new Employee("Rick")));
notEmptyTest(rick);
}
private void emptyTest(Expected<Employee> empty) {
final boolean[] flag = new boolean[1];
assertTrue(empty.isEmpty());
assertFalse(empty.isPresent());
/* Test ifEmpty and ifPresent. */
empty.ifEmpty(() -> flag[0] = true);
assertTrue(flag[0]);
empty.ifPresent( employee -> flag[0] = false);
assertTrue(flag[0]);
final Employee bob = empty.orElse(new Employee("bob"));
assertNotNull(bob);
try {
empty.get();
reject();
} catch (NoSuchElementException nsee) {
}
assertFalse(empty.filter(employee -> employee.id.equals("Rick")).isPresent());
assertFalse(empty.filter(employee -> employee.id.equals("Bob")).isPresent());
final Expected<Sheep> sheepValue = empty.map(employee -> new Sheep(employee.id));
assertTrue(sheepValue.isEmpty());
}
private void notEmptyTest(Expected<Employee> rick) {
final boolean[] flag = new boolean[1];
assertFalse(rick.isEmpty());
assertTrue(rick.isPresent());
flag[0] = false;
/* Test ifEmpty and ifPresent. */
rick.ifEmpty(() -> flag[0] = true);
assertFalse(flag[0]);
rick.ifPresent((Employee employee) -> flag[0] = true);
assertTrue(flag[0]);
final Employee notBob = rick.orElse(new Employee("bob"));
assertEquals("Rick", notBob.id);
final Sheep sheep = rick.map(employee -> new Sheep(employee.id)).get();
assertEquals("Rick", sheep.id);
assertTrue(rick.filter(employee -> employee.id.equals("Rick")).isPresent());
assertFalse(rick.filter(employee -> employee.id.equals("Bob")).isPresent());
/** Test equals. */
assertTrue(rick.equalsValue(new Employee("Rick")));
assertTrue(rick.equals(rick));
assertTrue(rick.equals(Expected.of(new Employee("Rick"))));
assertFalse(rick.equals(new Employee("Rick")));
rick.hashCode();
rick.toString();
}
static class Employee {
private final String id;
Employee(String id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return id != null ? id.equals(employee.id) : employee.id == null;
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
static class Sheep {
private final String id;
Sheep(String id) {
this.id = id;
}
}
}
package io.advantageous.reakt;
import io.advantageous.reakt.impl.ExpectedImpl;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* Same concept as Optional in Java JDK and Option in Scala.
* We added a new concept because this one is expected to come through callbacks and
* is used in places where Optional does not make sense.
* <p>
* Also we want to use interfaces for all core concepts.
* <p>
* In addition we wanted callback for ifPresent and ifEmpty.
* <p>
* Contains an value object which may not be set. This is like {@code Optional} but could be the value from an async operation
* which sent a null.
* <p>
* If a value is present, {@code isPresent()} will return {@code true} and
* {@code get()} will return the value.
* <p>
* This is heavily modeled after {@link java.util.Optional} optional.
*/
public interface Expected<T> {
/**
* Common instance for {@code empty()}.
*/
Expected EMPTY = new ExpectedImpl<>();
/**
* Returns an empty {@code ExpectedImpl} instance. No value is present for this
* value.
*
* @param <T> Type of the non-existent value
* @return an empty {@code ExpectedImpl}
*/
static <T> Expected<T> empty() {
@SuppressWarnings("unchecked")
Expected<T> t = EMPTY;
return t;
}
/**
* Returns an {@code ExpectedImpl} using the specified present value, which must not be null.
*
* @param <T> the class of the value
* @param value the value to be present. Must be non-null
* @return an {@code ExpectedImpl} with the value present
* @throws NullPointerException if value is null
*/
static <T> Expected<T> of(T value) {
return new ExpectedImpl<>(value);
}
/**
* Returns an {@code ExpectedImpl} describing the specified value, if non-null,
* otherwise returns an empty {@code ExpectedImpl}.
*
* @param <T> the class of the value
* @param value the possibly non-existent value
* @return an {@code ExpectedImpl} with a present value if the specified value
* is non-null, otherwise an empty {@code Optional}
*/
static <T> Expected<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
/**
* Returns an {@code ExpectedImpl} describing the specified value, if non-null,
* otherwise returns an empty {@code ExpectedImpl}.
*
* @param <T> the class of the value
* @param value the possibly non-existent value
* @return an {@code ExpectedImpl} with a present value if the specified value
* is not empty, otherwise an empty {@code Optional}
*/
static <T> Expected<T> ofOptional(Optional<T> value) {
return !value.isPresent() ? empty() : of(value.get());
}
/**
* If a value is present in this {@code Expected}, returns the value,
* otherwise throws {@code NoSuchElementException}.
*
* @return the value held by this {@code Expected}
* @throws NoSuchElementException if there is no value present
* @see Expected#isPresent()
*/
T get();
/**
* Return {@code true} if there is a value present, otherwise {@code false}.
*
* @return {@code true} if there is a value present, otherwise {@code false}
*/
boolean isPresent();
/**
* Return {@code true} if there is not a value present, otherwise {@code false}.
*
* @return {@code true} if there is not a value present, otherwise {@code false}
*/
boolean isEmpty();
/**
* If a value is present, invoke the consumer with the value.
*
* @param consumer executed if a value is present
* @throws NullPointerException if value is present and {@code consumer} is
* null
*/
Expected<T> ifPresent(Consumer<? super T> consumer);
/**
* If a value is not present, invoke the runnable.
*
* @param runnable executed if a value is not present
*/
Expected<T> ifEmpty(Runnable runnable);
/**
* If a value is present, and the value matches the given predicate,
* return an {@code ExpectedImpl} describing the value, otherwise return an
* empty {@code ExpectedImpl}.
*
* @param predicate a predicate to apply to the value, if present
* @return an {@code ExpectedImpl} the value {@code Expected}
* if present and the value matches the predicate,
* otherwise an empty {@code Expected}
* @throws NullPointerException if the predicate is null
*/
Expected<T> filter(Predicate<? super T> predicate);
/**
* If a value present, use the mapping function to it,
* and if the result is present, return an {@code ExpectedImpl} with the result.
* Otherwise return an empty value {@code Expected}.
*
* @param <U> The type of the result of the mapping function
* @param mapper a mapper to apply to the value, if present
* @return a value {@code Expected} which is the result of the mapper
* function applied to {@code Expected} value if present or an empty value.
* @throws NullPointerException if the mapper is null
*/
<U> Expected<U> map(Function<? super T, ? extends U> mapper);
/**
* Return the value if present. If not present return {@code other}.
*
* @param other value which is returned if no value present.
* @return the value, if present, or if not present return {@code other}
*/
T orElse(T other);
/**
* Indicates whether some other object is "equal to" the value.
* The other value is equal if Object.equals(value, other) returns true.
*/
boolean equalsValue(Object value);
}
Java Promises
- Promise
- Promise then*() and catchError()
- Promise thenMap()
- Promise all()
- Promise any()
- Blocking Promise
- Invokable Promise
- Reactor Replay Promises
Reactor, Stream, Results
- QBit Reactive Microservices
- Reakt Reactive Java
- Reakt Guava Bridge
- QBit Extensions
- Elekt Consul Leadership election
- Elekt Leadership election
- Reactive Microservices
What is Microservices Architecture?
QBit Java Micorservices lib tutorials
The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.
Reactive Programming, Java Microservices, Rick Hightower
Java Microservices Architecture
[Microservice Service Discovery with Consul] (http://www.mammatustech.com/Microservice-Service-Discovery-with-Consul)
Microservices Service Discovery Tutorial with Consul
[Reactive Microservices] (http://www.mammatustech.com/reactive-microservices)
[High Speed Microservices] (http://www.mammatustech.com/high-speed-microservices)
Reactive Microservices Tutorial, using the Reactor
QBit is mentioned in the Restlet blog
All code is written using JetBrains Idea - the best IDE ever!
Kafka training, Kafka consulting, Cassandra training, Cassandra consulting, Spark training, Spark consulting
Java Promises
- Promise
- Promise then*() and catchError()
- Promise thenMap()
- Promise all()
- Promise any()
- Blocking Promise
- Invokable Promise
- Reactor Replay Promises
Callback, and async Results
Reactor, Stream and Stream Result
Expected & Circuit Breaker
Scala Akka and Reakt