Class ReactiveValue<T>

java.lang.Object
com.machinezoo.hookless.ReactiveValue<T>
Type Parameters:
T - type of the result carried by this ReactiveValue

@DraftDocs("link to reactive value/output articles") public class ReactiveValue<T> extends Object
Container for output of reactive computation consisting of return value, exception, and reactive blocking flag. ReactiveValue can be split into its constituent components by calling result(), exception(), and blocking(). It can be recreated from these components by calling ReactiveValue(Object, Throwable, boolean) or some other constructor. ReactiveValue is immutable.

Reactive code usually takes the form of a method and communicates its output like a method, i.e. via return value or an exception. Reactive code may additionally signal reactive blocking by calling CurrentReactiveScope.block(). Return value, exception, and signaling of reactive blocking constitutes implicit output of reactive computation. ReactiveValue offers an explicit representation of the same. Conversion between explicit and implicit representations is performed by methods get() and capture(Supplier).

ReactiveValue does not carry reactive dependencies. Use ReactiveScope for that.

See Also:
  • Constructor Details

    • ReactiveValue

      public ReactiveValue(T result, Throwable exception, boolean blocking)
      Constructs new ReactiveValue from return value, exception, and reactive blocking flag. Only one of result and exception can be non-null. The parameters can be later retrieved via result(), exception(), and blocking().
      Parameters:
      result - component representing return value of reactive computation that can be later retrieved via result()
      exception - component representing exception thrown by reactive computation that can be later retrieved via exception()
      blocking - true if the constructed ReactiveValue should represent blocking reactive computation, false otherwise
      Throws:
      IllegalArgumentException - if both result and exception are non-null
      See Also:
    • ReactiveValue

      public ReactiveValue()
      Constructs new ReactiveValue. The new ReactiveValue represents reactive computation that successfully completed with null result and without blocking. The ReactiveValue will have null result() and exception() and false blocking() flag.
      See Also:
    • ReactiveValue

      public ReactiveValue(T result)
      Constructs new ReactiveValue from return value. The new ReactiveValue represents reactive computation that successfully completed without blocking. The ReactiveValue will have null exception() and false blocking() flag.
      Parameters:
      result - return value of the reactive computation the new ReactiveValue represents
      See Also:
    • ReactiveValue

      public ReactiveValue(Throwable exception)
      Constructs new ReactiveValue from exception. The new ReactiveValue represents reactive computation that threw an exception without blocking. The ReactiveValue will have null result() and false blocking() flag.
      Parameters:
      exception - exception thrown by the reactive computation the new ReactiveValue represents
      See Also:
    • ReactiveValue

      public ReactiveValue(T result, boolean blocking)
      Constructs new ReactiveValue from return value and blocking flag. The new ReactiveValue represents reactive computation that successfully completed and possibly signaled blocking. The ReactiveValue will have null exception().
      Parameters:
      result - return value of the reactive computation the new ReactiveValue represents
      blocking - true if the constructed ReactiveValue should represent blocking reactive computation, false otherwise
      See Also:
    • ReactiveValue

      public ReactiveValue(Throwable exception, boolean blocking)
      Constructs new ReactiveValue from exception and blocking flag. The new ReactiveValue represents reactive computation that threw an exception and possibly signaled blocking. The ReactiveValue will have null result().
      Parameters:
      exception - exception thrown by the reactive computation the new ReactiveValue represents
      blocking - true if the constructed ReactiveValue should represent blocking reactive computation, false otherwise
      See Also:
  • Method Details

    • result

      public T result()
      Gets the return value component of this ReactiveValue. Only one of result() and exception() can be non-null.
      Returns:
      return value component of ReactiveValue
      See Also:
    • exception

      public Throwable exception()
      Gets the exception component of this ReactiveValue. Only one of result() and exception() can be non-null.
      Returns:
      exception component of ReactiveValue
      See Also:
    • blocking

      public boolean blocking()
      Gets the reactive blocking flag from this ReactiveValue. Blocking flag is set if this ReactiveValue represents output of reactive computation that signaled blocking during its execution by calling CurrentReactiveScope.block().
      Returns:
      true if this ReactiveValue represents output of blocking reactive computation, false otherwise
      See Also:
    • get

      public T get()
      Unpacks explicit reactive output represented by this ReactiveValue into implicit reactive output. If exception() is not null, it is thrown wrapped in CompletionException. Otherwise result() is returned. In either case, if blocking() is true, CurrentReactiveScope.block() is called.
      Returns:
      value of result()
      Throws:
      CompletionException - if exception() is not null
      See Also:
    • capture

      public static <T> ReactiveValue<T> capture(Supplier<T> supplier)
      Captures implicit reactive output of provided Supplier and returns it encapsulated in new ReactiveValue. If the supplier throws, returned ReactiveValue will have exception() set to the caught exception. Otherwise the ReactiveValue will have result() set to value returned from the supplier.

      If the supplier reactively blocks by calling CurrentReactiveScope.block(), blocking() flag will be set on the returned ReactiveValue. This method obtains blocking flag by calling CurrentReactiveScope.blocked() after calling the supplier, which means the returned ReactiveValue will have blocking() flag set also if the current ReactiveScope was already blocked by the time this method was called. This is reasonable behavior, because the supplier might be itself derived from information produced by blocking operations executed earlier during the current reactive computation, which means that supplier's output cannot be trusted to be non-blocking.

      If there is no current ReactiveScope, i.e. ReactiveScope.current() returns null, this method creates temporary ReactiveScope and executes the supplier in it, so that blocking flag can be captured. This is particularly useful in unit tests.

      Type Parameters:
      T - type of value returned by the supplier
      Parameters:
      supplier - reactive code to execute
      Returns:
      ReactiveValue encapsulating implicit reactive output of the supplier
      See Also:
    • equals

      public boolean equals(Object obj)
      Compares this ReactiveValue to another object for equality. ReactiveValue can only equal another ReactiveValue. Two ReactiveValue instances are equal if their result(), exception(), and blocking() flags are equal. Value equality is used for both result() and exception(). Two exceptions are equal when their stringified form (including stack trace and causes) compares equal.

      Full value equality checking may be expensive or even undesirable. Use same(ReactiveValue) to compute shallow reference equality.

      Overrides:
      equals in class Object
      Parameters:
      obj - object to compare this ReactiveValue to or null
      Returns:
      true if the objects compare equal, false otherwise
      See Also:
    • hashCode

      public int hashCode()
      Computes hash code of this ReactiveValue. Hash code is calculated in such a way that if two ReactiveValue instances are equal as checked by equals(Object), then their hash codes are equal too. This makes ReactiveValue usable as a key in a Map.

      Both result() and exception() are included in hash code calculation. Exceptions are hashed in such a way that two exceptions with the same stringified form (including stack traces and causes) will have the same hash code.

      Overrides:
      hashCode in class Object
      Returns:
      hash code of this ReactiveValue
      See Also:
    • same

      public boolean same(ReactiveValue<?> other)
      Checks reference equality between two ReactiveValue instances. Another ReactiveValue is reference-equal to this instance according to this method if it is not null and its result(), exception(), and blocking() components are all reference-equal to corresponding components of this ReactiveValue.

      This method is useful when equals(Object) would be too expensive or where reference equality is desirable.

      Parameters:
      other - ReactiveValue to compare this instance to or null
      Returns:
      true if the two ReactiveValue instances are reference-equal, false otherwise
      See Also:
    • toString

      public String toString()
      Returns a string representation of this ReactiveValue. The returned string is suitable for debug output and includes string representation of result() or exception() as well as indication whether the ReactiveValue is blocking().
      Overrides:
      toString in class Object
      Returns:
      string representation of this ReactiveValue