Repository: brooklyn-server Updated Branches: refs/heads/master dc5bc6d19 -> a4e69956e
Add iterator to ValueResolver Resolves the initial object iteratively until either failure or object can't be resolved any more. Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/5f66e8fe Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/5f66e8fe Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/5f66e8fe Branch: refs/heads/master Commit: 5f66e8fe4ecdf91a8121ff6e16da4ca0607cf0f1 Parents: 972a0d8 Author: Svetoslav Neykov <svetoslav.ney...@cloudsoftcorp.com> Authored: Mon Jan 16 18:37:46 2017 +0200 Committer: Svetoslav Neykov <svetoslav.ney...@cloudsoftcorp.com> Committed: Mon Jan 23 18:16:49 2017 +0200 ---------------------------------------------------------------------- .../spi/dsl/DslDeferredFunctionCall.java | 30 +-- .../brooklyn/util/core/task/ValueResolver.java | 37 +++- .../util/core/task/ValueResolverIterator.java | 196 +++++++++++++++++ .../core/task/ValueResolverIteratorTest.java | 217 +++++++++++++++++++ .../util/core/task/ValueResolverTest.java | 4 +- 5 files changed, 451 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/5f66e8fe/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java index f511926..0b2963d 100644 --- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java +++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java @@ -25,7 +25,6 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.brooklyn.api.mgmt.Task; import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon; -import org.apache.brooklyn.core.entity.EntityInternal; import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; import org.apache.brooklyn.util.core.task.Tasks; import org.apache.brooklyn.util.exceptions.Exceptions; @@ -142,29 +141,12 @@ public class DslDeferredFunctionCall extends BrooklynDslDeferredSupplier<Object> } protected Maybe<?> resolve(Object object, boolean immediate) { - if (object instanceof DslFunctionSource || object == null) { - return Maybe.of(object); - } - - Maybe<?> resultMaybe = Tasks.resolving(object, Object.class) - .context(entity().getExecutionContext()) - .deep(true) - .immediately(immediate) - .recursive(false) - .getMaybe(); - - if (resultMaybe.isPresent()) { - // No nice way to figure out whether the object is deferred. Try to resolve it - // until it matches the input value as a poor man's replacement. - Object result = resultMaybe.get(); - if (result == object) { - return resultMaybe; - } else { - return resolve(result, immediate); - } - } else { - return resultMaybe; - } + return Tasks.resolving(object, Object.class) + .context(entity().getExecutionContext()) + .deep(true) + .immediately(immediate) + .iterator() + .nextOrLast(DslFunctionSource.class); } private static void checkCallAllowed(Method m) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/5f66e8fe/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java b/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java index 650ccc9..f81594e 100644 --- a/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java @@ -56,7 +56,7 @@ import com.google.common.reflect.TypeToken; * <p> * Fluent-style API exposes a number of other options. */ -public class ValueResolver<T> implements DeferredSupplier<T> { +public class ValueResolver<T> implements DeferredSupplier<T>, Iterable<Maybe<Object>> { // TODO most of these usages should be removed when we have // an ability to run resolution in a non-blocking mode @@ -166,14 +166,29 @@ public class ValueResolver<T> implements DeferredSupplier<T> { /** returns a copy of this resolver which can be queried, even if the original (single-use instance) has already been copied */ @Override public ValueResolver<T> clone() { - ValueResolver<T> result = new ValueResolver<T>(value, type) + return cloneReplacingValueAndType(value, type); + } + + <S> ValueResolver<S> cloneReplacingValueAndType(Object newValue, Class<S> superType) { + // superType expected to be either type or Object.class + if (!superType.isAssignableFrom(type)) { + throw new IllegalStateException("superType must be assignable from " + type); + } + ValueResolver<S> result = new ValueResolver<S>(newValue, superType) .context(exec).description(description) .embedResolutionInTask(embedResolutionInTask) .deep(forceDeep) .timeout(timeout) .immediately(immediately) .recursive(recursive); - if (returnDefaultOnGet) result.defaultValue(defaultValue); + if (returnDefaultOnGet) { + if (!superType.isInstance(defaultValue)) { + throw new IllegalStateException("Existing default value " + defaultValue + " not compatible with new type " + superType); + } + @SuppressWarnings("unchecked") + S typedDefaultValue = (S)defaultValue; + result.defaultValue(typedDefaultValue); + } if (swallowExceptions) result.swallowExceptions(); return result; } @@ -287,13 +302,18 @@ public class ValueResolver<T> implements DeferredSupplier<T> { } @Override + public ValueResolverIterator<T> iterator() { + return new ValueResolverIterator<T>(this); + } + + @Override public T get() { Maybe<T> m = getMaybe(); if (m.isPresent()) return m.get(); if (returnDefaultOnGet) return defaultValue; return m.get(); } - + public Maybe<T> getMaybe() { Maybe<T> result = getMaybeInternal(); if (log.isTraceEnabled()) { @@ -324,7 +344,7 @@ public class ValueResolver<T> implements DeferredSupplier<T> { if (timerU==null && timeout!=null) timerU = timeout.countdownTimer(); final CountdownTimer timer = timerU; - if (timer!=null && !timer.isRunning()) + if (timer!=null && !timer.isNotPaused()) timer.start(); checkTypeNotNull(); @@ -499,9 +519,12 @@ public class ValueResolver<T> implements DeferredSupplier<T> { if (parentOriginalValue!=null) return parentOriginalValue; return value; } - + protected Class<T> getType() { + return type; + } + @Override public String toString() { return JavaClassNames.cleanSimpleClassName(this)+"["+JavaClassNames.cleanSimpleClassName(type)+" "+value+"]"; } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/5f66e8fe/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolverIterator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolverIterator.java b/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolverIterator.java new file mode 100644 index 0000000..0e6fe4d --- /dev/null +++ b/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolverIterator.java @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.util.core.task; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.apache.brooklyn.util.core.flags.TypeCoercions; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.guava.Maybe; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; + +/** + * Resolve one step at a time, returning intermediate results or absent if there's a resolve error. + * Each step is a single one-level evaluation of the previous value. + * Use this if you are interested in intermediate suppliers wrapping the end result. Use ValueResolver if you need the deeper-most value. + */ +public class ValueResolverIterator<T> implements Iterator<Maybe<Object>> { + private static final Maybe<Object> NEXT_VALUE = Maybe.absent(); + private ValueResolver<T> resolver; + private Maybe<Object> prev; + + // * Present when resolving is successful + // * Absent when resolving failed + // * null when last value reached; can't resolve further either due to error or value is non-resolvable + private Maybe<Object> next; + + public ValueResolverIterator(ValueResolver<T> resolver) { + this.resolver = resolver; + this.prev = Maybe.of(resolver.getOriginalValue()); + this.next = prev; + } + + /** + * @return the current element in the iterator. If {@link Maybe#absent()} there was a resolve error. + */ + public Maybe<Object> peek() { + return prev; + } + + /** + * Returns {@code true} if the current value is resolvable. + */ + @Override + public boolean hasNext() { + fetchNext(); + return next != null; + } + + /** + * Resolves the value recursively, returning the immediately resolved value. + * If there's a resolve failure a {@link Maybe#absent()} is returned containing + * the failure description as the last element. + */ + @Override + public Maybe<Object> next() { + if (!hasNext()) { + if (prev.isPresent()) { + throw new NoSuchElementException("The value " + prev.get() + " is non-resolvable"); + } else { + throw new NoSuchElementException("Last resolve failed: " + prev); + } + } + prev = next; + next = NEXT_VALUE; + return prev; + } + + private void fetchNext() { + if (next == NEXT_VALUE) { + if (prev.isPresent()) { + Object prevValue = prev.get(); + if (prevValue != null) { + ValueResolver<Object> nextResolver = createIterativeResolver(prevValue); + try { + next = nextResolver.getMaybe(); + } catch (Exception e) { + Exceptions.propagateIfFatal(e); + next = Maybe.absent("Failed resolving " + prev + " with resolver " + resolver, e); + } + if (next.isPresent() && next.get() == prev.get()) { + // Resolved value same as previous value, last element reached + next = null; + } + } else { + // Can't resolve null further + // Same as previous case, just cuts on on the resolver calls + next = null; + } + } else { + // Resolve error, can't continue + next = null; + } + } + } + + @Override + public void remove() { + throw new IllegalStateException("Operation not supported"); + } + + private ValueResolver<Object> createIterativeResolver(Object value) { + return resolver.cloneReplacingValueAndType(value, Object.class) + .recursive(false); + } + + /** + * @return the first resolved value satisfying the {@code stopCondition}. + * If none is found return the last element. + */ + public Maybe<Object> nextOrLast(Predicate<Object> stopCondition) { + if (!hasNext()) { + return prev; + } + Maybe<Object> item; + do { + item = next(); + if (item.isAbsent() || stopCondition.apply(item.get())) { + return item; + } + } while (hasNext()); + return item; + } + + /** + * @return the first resolved value instance of {@code type}. + * If none is found return the last element. + */ + public Maybe<Object> nextOrLast(Class<?> type) { + return nextOrLast(Predicates.instanceOf(type)); + } + + /** + * @return the first resolved value instance of {@code type}. + * If not found returns {@link Maybe#absent()} either due to + * the end reached or a resolve error. To check if there was a + * resolve error call {@code peek().isAbsent()}. + */ + public <S> Maybe<S> next(Class<S> type) { + while (hasNext()) { + Maybe<Object> item = next(); + if (item.isAbsent() || type.isInstance(item.get())) { + @SuppressWarnings("unchecked") + Maybe<S> typedItem = (Maybe<S>) item; + return typedItem; + } + } + return Maybe.absent("Did not find items of type " + type + " in " + resolver); + } + + /** + * @return the last element of the iterator reached either because + * resolving no longer possible or there was a resolve error. + */ + @SuppressWarnings("unchecked") + public Maybe<T> last() { + Maybe<Object> last = peek(); + while (hasNext()) { + last = next(); + if (last.isAbsent()) { + return (Maybe<T>) last; + } + } + return coerceValue(last, resolver.getType()); + } + + private Maybe<T> coerceValue(Maybe<Object> valueMaybe, Class<T> type) { + if (valueMaybe.isPresent()) { + T coercedValue = TypeCoercions.coerce(valueMaybe.get(), type); + return Maybe.of(coercedValue); + } else { + @SuppressWarnings("unchecked") + Maybe<T> uncheckedValue = (Maybe<T>) valueMaybe; + return uncheckedValue; + } + } + +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/5f66e8fe/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverIteratorTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverIteratorTest.java b/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverIteratorTest.java new file mode 100644 index 0000000..c6ea9dd --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverIteratorTest.java @@ -0,0 +1,217 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.util.core.task; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import java.util.NoSuchElementException; + +import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; +import org.apache.brooklyn.test.Asserts; +import org.apache.brooklyn.util.core.task.ValueResolverTest.FailingImmediateAndDeferredSupplier; +import org.apache.brooklyn.util.core.task.ValueResolverTest.WrappingImmediateAndDeferredSupplier; +import org.apache.brooklyn.util.guava.Maybe; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import com.google.common.base.Predicates; + +public class ValueResolverIteratorTest extends BrooklynAppUnitTestSupport { + enum ResolveType { + IMMEDIATE(true), + BLOCKING(false); + + private boolean immediate; + + ResolveType(boolean immediate) { + this.immediate = immediate; + } + + public boolean isImmediate() { + return immediate; + } + } + + @DataProvider + public Object[][] resolveTypes() { + return new Object[][] {{ResolveType.IMMEDIATE}, {ResolveType.BLOCKING}}; + } + + @Test(dataProvider="resolveTypes") + public void testIteratorFailing(ResolveType resolveType) { + FailingImmediateAndDeferredSupplier failingExpected = new FailingImmediateAndDeferredSupplier(); + WrappingImmediateAndDeferredSupplier wrapperExpected = new WrappingImmediateAndDeferredSupplier(failingExpected); + ValueResolver<Object> resolver = Tasks.resolving(wrapperExpected) + .as(Object.class) + .context(app) + .immediately(resolveType.isImmediate()); + ValueResolverIterator<Object> iter = resolver.iterator(); + assertTrue(iter.hasNext(), "expected wrapper"); + Maybe<Object> wrapperActual = iter.next(); + assertEquals(wrapperActual.get(), wrapperExpected); + assertEquals(wrapperActual, iter.peek()); + assertTrue(iter.hasNext()); + Maybe<Object> failingActual = iter.next(); + assertEquals(failingActual.get(), failingExpected); + assertEquals(failingActual, iter.peek()); + assertTrue(iter.hasNext()); + Maybe<Object> absent = iter.next(); + assertTrue(absent.isAbsent()); + + assertFalse(iter.hasNext(), "expected absent due to resolve failure"); + try { + iter.next(); + Asserts.shouldHaveFailedPreviously("no more elements in iterator"); + } catch (NoSuchElementException e) { + // expected + } + + Maybe<Object> last = iter.nextOrLast(Predicates.alwaysTrue()); + assertTrue(last.isAbsent(), "expected absent because previous resolve failed"); + assertEquals(last, iter.peek()); + + try { + iter.remove(); + Asserts.shouldHaveFailedPreviously("can't remove elements"); + } catch (IllegalStateException e) { + // expected + } + } + + @Test(dataProvider="resolveTypes") + public void testIterator(ResolveType resolveType) { + Integer o3ExpectedLast = Integer.valueOf(10); + String o3Expected = o3ExpectedLast.toString(); //test coercion + WrappingImmediateAndDeferredSupplier o2Expected = new WrappingImmediateAndDeferredSupplier(o3Expected); + WrappingImmediateAndDeferredSupplier o1Expected = new WrappingImmediateAndDeferredSupplier(o2Expected); + ValueResolver<Integer> resolver = Tasks.resolving(o1Expected) + .as(Integer.class) + .context(app) + .immediately(resolveType.isImmediate()); + ValueResolverIterator<Integer> iter = resolver.iterator(); + assertTrue(iter.hasNext(), "expected o1"); + Maybe<Object> o1Actual = iter.next(); + assertEquals(o1Actual.get(), o1Expected); + assertEquals(o1Actual, iter.peek()); + assertTrue(iter.hasNext()); + Maybe<Object> o2Actual = iter.next(); + assertEquals(o2Actual.get(), o2Expected); + assertEquals(o2Actual, iter.peek()); + assertTrue(iter.hasNext()); + Maybe<Object> o3Actual = iter.next(); + assertEquals(o3Actual.get(), o3Expected); + assertEquals(o3Actual, iter.peek()); + + assertFalse(iter.hasNext(), "expected no more elements"); + try { + iter.next(); + Asserts.shouldHaveFailedPreviously("no more elements in iterator"); + } catch (NoSuchElementException e) { + // expected + } + + Maybe<Object> lastUntyped = iter.nextOrLast(Predicates.alwaysTrue()); + assertTrue(lastUntyped.isPresent(), "expected present - all resolves successful"); + // Note these are NOT equal because peek doesn't coerce + assertEquals(lastUntyped, iter.peek()); + assertEquals(lastUntyped.get(), o3Expected); + } + + @Test(dataProvider="resolveTypes") + public void testNull(ResolveType resolveType) { + ValueResolver<Void> resolver = Tasks.resolving(null) + .as(Void.class) + .context(app) + .immediately(resolveType.isImmediate()); + assertNull(resolver.get()); + ValueResolverIterator<Void> iter = resolver.iterator(); + assertTrue(iter.hasNext()); + assertNull(iter.next().get()); + assertFalse(iter.hasNext()); + + Maybe<Object> voidOrLast = resolver.iterator().nextOrLast(Void.class); + assertNull(voidOrLast.get()); + + Maybe<Void> voidItem = resolver.iterator().next(Void.class); + assertTrue(voidItem.isAbsent()); + + Maybe<Void> lastItem = resolver.iterator().last(); + assertNull(lastItem.get()); + } + + @Test(dataProvider="resolveTypes") + public void testNextOrLastFound(ResolveType resolveType) { + FailingImmediateAndDeferredSupplier failingExpected = new FailingImmediateAndDeferredSupplier(); + WrappingImmediateAndDeferredSupplier wrapperExpected = new WrappingImmediateAndDeferredSupplier(failingExpected); + ValueResolver<Object> resolver = Tasks.resolving(wrapperExpected) + .as(Object.class) + .context(app) + .immediately(resolveType.isImmediate()); + ValueResolverIterator<Object> iter = resolver.iterator(); + Maybe<Object> actual = iter.nextOrLast(FailingImmediateAndDeferredSupplier.class); + assertTrue(actual.isPresent()); + assertNotEquals(actual, iter.last()); + } + + @Test(dataProvider="resolveTypes") + public void testNextOrLastNotFound(ResolveType resolveType) { + FailingImmediateAndDeferredSupplier failingExpected = new FailingImmediateAndDeferredSupplier(); + WrappingImmediateAndDeferredSupplier wrapperExpected = new WrappingImmediateAndDeferredSupplier(failingExpected); + ValueResolver<Object> resolver = Tasks.resolving(wrapperExpected) + .as(Object.class) + .context(app) + .immediately(resolveType.isImmediate()); + ValueResolverIterator<Object> iter = resolver.iterator(); + Maybe<Object> actual = iter.nextOrLast(Void.class); + assertFalse(actual.isPresent()); + assertEquals(actual, iter.last()); + } + + @Test(dataProvider="resolveTypes") + public void testNextTypeFound(ResolveType resolveType) { + FailingImmediateAndDeferredSupplier failingExpected = new FailingImmediateAndDeferredSupplier(); + WrappingImmediateAndDeferredSupplier wrapperExpected = new WrappingImmediateAndDeferredSupplier(failingExpected); + ValueResolver<Object> resolver = Tasks.resolving(wrapperExpected) + .as(Object.class) + .context(app) + .immediately(resolveType.isImmediate()); + ValueResolverIterator<Object> iter = resolver.iterator(); + Maybe<FailingImmediateAndDeferredSupplier> actual = iter.next(FailingImmediateAndDeferredSupplier.class); + assertTrue(actual.isPresent()); + assertNotEquals(actual, iter.last()); + } + + @Test(dataProvider="resolveTypes") + public void testNextTypeNotFound(ResolveType resolveType) { + FailingImmediateAndDeferredSupplier failingExpected = new FailingImmediateAndDeferredSupplier(); + WrappingImmediateAndDeferredSupplier wrapperExpected = new WrappingImmediateAndDeferredSupplier(failingExpected); + ValueResolver<Object> resolver = Tasks.resolving(wrapperExpected) + .as(Object.class) + .context(app) + .immediately(resolveType.isImmediate()); + ValueResolverIterator<Object> iter = resolver.iterator(); + Maybe<Void> actual = iter.next(Void.class); + assertFalse(actual.isPresent()); + assertEquals(actual, iter.last()); + } +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/5f66e8fe/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java b/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java index 8e2581c..e47e4c9 100644 --- a/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java +++ b/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java @@ -249,7 +249,7 @@ public class ValueResolverTest extends BrooklynAppUnitTestSupport { } } - private static class WrappingImmediateAndDeferredSupplier implements ImmediateSupplier<Object>, DeferredSupplier<Object> { + static class WrappingImmediateAndDeferredSupplier implements ImmediateSupplier<Object>, DeferredSupplier<Object> { private Object value; public WrappingImmediateAndDeferredSupplier(Object value) { @@ -268,7 +268,7 @@ public class ValueResolverTest extends BrooklynAppUnitTestSupport { } - private static class FailingImmediateAndDeferredSupplier implements ImmediateSupplier<Object>, DeferredSupplier<Object> { + static class FailingImmediateAndDeferredSupplier implements ImmediateSupplier<Object>, DeferredSupplier<Object> { @Override public Object get() {