brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject [4/6] brooklyn-server git commit: PR #390: incorporate more review comments
Date Wed, 02 Nov 2016 10:06:25 GMT
PR #390: incorporate more review comments


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/8601d219
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/8601d219
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/8601d219

Branch: refs/heads/master
Commit: 8601d219f4a5bec4ab751257b7c022545bfdd92b
Parents: cee60cc
Author: Aled Sage <aled.sage@gmail.com>
Authored: Tue Nov 1 17:48:46 2016 +0000
Committer: Aled Sage <aled.sage@gmail.com>
Committed: Tue Nov 1 20:50:58 2016 +0000

----------------------------------------------------------------------
 .../spi/dsl/methods/BrooklynDslCommon.java      |   2 +
 .../brooklyn/spi/dsl/methods/DslComponent.java  |  62 ++++++---
 .../brooklyn/camp/brooklyn/dsl/DslTest.java     | 134 ++++++++++++++++++-
 .../AbstractConfigurationSupportInternal.java   |   2 +-
 .../util/core/task/ValueResolverTest.java       |  25 ++--
 5 files changed, 191 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8601d219/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
index f508db9..8fb48cf 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@ -584,6 +584,8 @@ public class BrooklynDslCommon {
 
         @Override
         public final Maybe<Object> getImmediately() {
+            // Note this call to getConfig() is different from entity.getConfig.
+            // We expect it to not block waiting for other entities.
             ManagementContextInternal managementContext = DslExternal.managementContext();
             return Maybe.<Object>of(managementContext.getExternalConfigProviderRegistry().getConfig(providerName,
key));
         }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8601d219/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
index cded853..720dfae 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
@@ -37,6 +37,7 @@ import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.core.mgmt.internal.EntityManagerInternal;
 import org.apache.brooklyn.core.sensor.DependentConfiguration;
 import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.util.core.task.ImmediateSupplier;
 import org.apache.brooklyn.util.core.task.TaskBuilder;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.exceptions.Exceptions;
@@ -91,11 +92,7 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity>
{
 
     @Override
     public final Maybe<Entity> getImmediately() {
-        try {
-            return Maybe.of(new EntityInScopeFinder(scopeComponent, scope, componentId).call());
-        } catch (Exception e) {
-            throw Exceptions.propagate(e);
-        }
+        return new EntityInScopeFinder(scopeComponent, scope, componentId).getImmediately();
     }
 
     @Override
@@ -108,7 +105,7 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity>
{
                 .build();
     }
     
-    protected static class EntityInScopeFinder implements Callable<Entity> {
+    protected static class EntityInScopeFinder implements Callable<Entity>, ImmediateSupplier<Entity>
{
         protected final DslComponent scopeComponent;
         protected final Scope scope;
         protected final String componentId;
@@ -119,33 +116,55 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity>
{
             this.componentId = componentId;
         }
 
-        protected EntityInternal getEntity() {
-            if (scopeComponent!=null) {
-                return (EntityInternal)scopeComponent.get();
-            } else {
-                return entity();
+        @Override 
+        public Maybe<Entity> getImmediately() {
+            try {
+                return callImpl(true);
+            } catch (Exception e) {
+                throw Exceptions.propagate(e);
             }
         }
-        
+
         @Override
         public Entity call() throws Exception {
+            return callImpl(false).get();
+        }
+
+        protected Maybe<Entity> getEntity(boolean immediate) {
+            if (scopeComponent != null) {
+                if (immediate) {
+                    return scopeComponent.getImmediately();
+                } else {
+                    return Maybe.of(scopeComponent.get());
+                }
+            } else {
+                return Maybe.<Entity>of(entity());
+            }
+        }
+        
+        protected Maybe<Entity> callImpl(boolean immediate) throws Exception {
+            Maybe<Entity> entityMaybe = getEntity(immediate);
+            if (immediate && entityMaybe.isAbsent()) {
+                return entityMaybe;
+            }
+            EntityInternal entity = (EntityInternal) entityMaybe.get();
+            
             Iterable<Entity> entitiesToSearch = null;
-            EntityInternal entity = getEntity();
             Predicate<Entity> notSelfPredicate = Predicates.not(Predicates.<Entity>equalTo(entity));
 
             switch (scope) {
                 case THIS:
-                    return entity;
+                    return Maybe.<Entity>of(entity);
                 case PARENT:
-                    return entity.getParent();
+                    return Maybe.<Entity>of(entity.getParent());
                 case GLOBAL:
                     entitiesToSearch = ((EntityManagerInternal)entity.getManagementContext().getEntityManager())
                         .getAllEntitiesInApplication( entity().getApplication() );
                     break;
                 case ROOT:
-                    return entity.getApplication();
+                    return Maybe.<Entity>of(entity.getApplication());
                 case SCOPE_ROOT:
-                    return Entities.catalogItemScopeRoot(entity);
+                    return Maybe.<Entity>of(Entities.catalogItemScopeRoot(entity));
                 case DESCENDANT:
                     entitiesToSearch = Entities.descendantsWithoutSelf(entity);
                     break;
@@ -165,8 +184,9 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity>
{
             
             Optional<Entity> result = Iterables.tryFind(entitiesToSearch, EntityPredicates.configEqualTo(BrooklynCampConstants.PLAN_ID,
componentId));
             
-            if (result.isPresent())
-                return result.get();
+            if (result.isPresent()) {
+                return Maybe.of(result.get());
+            }
             
             // TODO may want to block and repeat on new entities joining?
             throw new NoSuchElementException("No entity matching id " + componentId+
@@ -340,9 +360,9 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity>
{
         public final Maybe<Object> getImmediately() {
             Maybe<Entity> targetEntityMaybe = component.getImmediately();
             if (targetEntityMaybe.isAbsent()) return Maybe.absent("Target entity not available");
-            Entity targetEntity = targetEntityMaybe.get();
+            EntityInternal targetEntity = (EntityInternal) targetEntityMaybe.get();
             
-            return Maybe.of(targetEntity.getConfig(ConfigKeys.newConfigKey(Object.class,
keyName)));
+            return targetEntity.config().getNonBlocking(ConfigKeys.newConfigKey(Object.class,
keyName));
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8601d219/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslTest.java
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslTest.java
index 8db3720..69a0aee 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslTest.java
@@ -32,6 +32,8 @@ import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
 import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
 import org.apache.brooklyn.core.test.entity.TestApplication;
@@ -47,6 +49,8 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
 import com.google.common.base.Supplier;
 import com.google.common.util.concurrent.ListenableScheduledFuture;
 import com.google.common.util.concurrent.ListeningScheduledExecutorService;
@@ -116,6 +120,74 @@ public class DslTest extends BrooklynAppUnitTestSupport {
     }
 
     @Test
+    public void testConfig() throws Exception {
+        ConfigKey<String> configKey = ConfigKeys.newStringConfigKey("testConfig");
+        BrooklynDslDeferredSupplier<?> dsl = BrooklynDslCommon.config(configKey.getName());
+        new ConfigTestWorker(app, configKey, dsl).run();
+    }
+
+    @Test
+    public void testConfigWithDsl() throws Exception {
+        ConfigKey<?> configKey = ConfigKeys.newConfigKey(Entity.class, "testConfig");
+        BrooklynDslDeferredSupplier<?> dsl = BrooklynDslCommon.config(configKey.getName());
+        Supplier<ConfigValuePair> valueSupplier = new Supplier<ConfigValuePair>()
{
+            @Override public ConfigValuePair get() {
+                return new ConfigValuePair(BrooklynDslCommon.root(), app);
+            }
+        };
+        new ConfigTestWorker(app, configKey, valueSupplier, dsl).run();
+    }
+
+    @Test
+    public void testConfigWithDslNotReadyImmediately() throws Exception {
+        final ConfigKey<String> configKey = ConfigKeys.newStringConfigKey("testConfig");
+        BrooklynDslDeferredSupplier<?> dsl = BrooklynDslCommon.config(configKey.getName());
+        Function<Entity, ConfigValuePair> valueSupplier = new Function<Entity, ConfigValuePair>()
{
+            private ListenableScheduledFuture<?> future;
+            @Override
+            public ConfigValuePair apply(final Entity entity) {
+                try {
+                    // If executed in a loop, then wait for previous call's future to complete.
+                    // If previous assertion used getImmediately, then it won't have waited
for the future to complete.
+                    if (future != null) {
+                        future.get(Asserts.DEFAULT_LONG_TIMEOUT.toMilliseconds(), TimeUnit.MILLISECONDS);
+                        future = null;
+                    }
+    
+                    // Reset sensor - otherwise if run in a loop the old value will be picked
up, before our execute sets the new value
+                    entity.sensors().set(TestApplication.MY_ATTRIBUTE, null);
+                    
+                    final String expectedValue = Identifiers.makeRandomId(10);
+                    Runnable job = new Runnable() {
+                        public void run() {
+                            entity.sensors().set(TestApplication.MY_ATTRIBUTE, expectedValue);
+                        }
+                    };
+                    future = executor.schedule(job, random.nextInt(20), TimeUnit.MILLISECONDS);
+    
+                    BrooklynDslDeferredSupplier<?> attributeDsl = BrooklynDslCommon.attributeWhenReady(TestApplication.MY_ATTRIBUTE.getName());
+                    return new ConfigValuePair(attributeDsl, expectedValue);
+
+                } catch (Exception e) {
+                    throw Exceptions.propagate(e);
+                }
+            }
+        };
+        new ConfigTestWorker(app, configKey, valueSupplier, dsl).satisfiedAsynchronously(true).resolverIterations(2).run();
+    }
+    
+    @Test
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public void testConfigImmediatelyDoesNotBlock() throws Exception {
+        ConfigKey<String> configKey = ConfigKeys.newStringConfigKey("testConfig");
+        BrooklynDslDeferredSupplier<?> attributeDsl = BrooklynDslCommon.attributeWhenReady(TestApplication.MY_ATTRIBUTE.getName());
+        app.config().set((ConfigKey)configKey, attributeDsl); // ugly cast because val is
DSL, resolving to a string
+        BrooklynDslDeferredSupplier<?> configDsl = BrooklynDslCommon.config(configKey.getName());
+        Maybe<?> actualValue = execDslImmediately(configDsl, configKey.getType(), app,
true);
+        assertTrue(actualValue.isAbsent());
+    }
+
+    @Test
     public void testSelf() throws Exception {
         BrooklynDslDeferredSupplier<?> dsl = BrooklynDslCommon.self();
         new SelfTestWorker(app, dsl).run();
@@ -263,7 +335,6 @@ public class DslTest extends BrooklynAppUnitTestSupport {
             // Reset sensor - otherwise if run in a loop the old value will be picked up,
before our execute sets the new value
             entity.sensors().set(sensor, null);
         }
-
     }
 
     private static class SelfTestWorker extends DslTestWorker {
@@ -292,6 +363,67 @@ public class DslTest extends BrooklynAppUnitTestSupport {
             assertEquals(actualValue.get(), parent);
         }
     }
+    
+    private class ConfigTestWorker extends DslTestWorker {
+        private ConfigKey<?> config;
+        private Object expectedValue;
+        private Function<? super Entity, ConfigValuePair> valueFunction;
+        
+        public ConfigTestWorker(TestApplication parent, ConfigKey<?> config, BrooklynDslDeferredSupplier<?>
dsl) {
+            this(parent, config, newRandomConfigValueSupplier(), dsl);
+        }
+
+        public ConfigTestWorker(TestApplication parent, ConfigKey<?> config, Supplier<ConfigValuePair>
valueSupplier, BrooklynDslDeferredSupplier<?> dsl) {
+            this(parent, config, Functions.forSupplier(valueSupplier), dsl);
+        }
+        
+        public ConfigTestWorker(TestApplication parent, ConfigKey<?> config, Function<?
super Entity, ConfigValuePair> valueFunction, BrooklynDslDeferredSupplier<?> dsl)
{
+            super(parent, dsl, config.getType());
+            this.config = config;
+            this.valueFunction = valueFunction;
+        }
+
+        @Override
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        protected void preResolve(final TestEntity entity) {
+            ConfigValuePair pair = valueFunction.apply(entity);
+            expectedValue = pair.expectedResolvedVal;
+            entity.config().set((ConfigKey)config, pair.configVal); // nasty cast, because
val might be a DSL
+        }
+
+        @Override
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        protected void postResolve(TestEntity entity, Maybe<?> actualValue, boolean
isImmediate) throws Exception {
+            if (satisfiedAsynchronously && isImmediate) {
+                // We accept a maybe.absent if we called getImmediately when satisfiedAsynchronously
+                assertTrue(actualValue.isAbsent() || expectedValue.equals(actualValue.get()),
"actual="+actualValue+"; expected="+expectedValue);
+            } else {
+                assertEquals(actualValue.get(), expectedValue);
+            }
+            
+            // Reset config - otherwise if run in a loop the old value will be picked up,
before our execute sets the new value
+            entity.config().set((ConfigKey)config, (Object)null); // ugly cast from ConfigKey<?>
+        }
+    }
+
+    static class ConfigValuePair {
+        public final Object configVal;
+        public final Object expectedResolvedVal;
+        
+        public ConfigValuePair(Object configVal, Object expectedResolvedVal) {
+            this.configVal = configVal;
+            this.expectedResolvedVal = expectedResolvedVal;
+        }
+    }
+
+    private static Supplier<ConfigValuePair> newRandomConfigValueSupplier() {
+        return new Supplier<ConfigValuePair>() {
+            @Override public ConfigValuePair get() {
+                String val = Identifiers.makeRandomId(10);
+                return new ConfigValuePair(val, val);
+            }
+        };
+    }
 
     static Maybe<?> execDslImmediately(final BrooklynDslDeferredSupplier<?> dsl,
final Class<?> type, final Entity context, boolean execInTask) throws Exception {
         // Exec'ing immediately will call DSL in current thread. It needs to find the context
entity,

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8601d219/core/src/main/java/org/apache/brooklyn/core/objs/AbstractConfigurationSupportInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractConfigurationSupportInternal.java
b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractConfigurationSupportInternal.java
index 61dc513..3465ecf 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractConfigurationSupportInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractConfigurationSupportInternal.java
@@ -139,7 +139,7 @@ public abstract class AbstractConfigurationSupportInternal implements
BrooklynOb
         Object resolved = Tasks.resolving(unresolved)
                 .as(Object.class)
                 .defaultValue(marker)
-                .timeout(ValueResolver.REAL_REAL_QUICK_WAIT)
+                .immediately(true)
                 .context(getContext())
                 .swallowExceptions()
                 .get();

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8601d219/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 b13d2b5..b7e9085 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
@@ -60,29 +60,31 @@ public class ValueResolverTest extends BrooklynAppUnitTestSupport {
     }
 
     public void testCompletedTaskReturnsResultImmediately() {
-        // Call ValueResolver.getMaybe() from this thread, which has no execution context.
-        // However, the task has already been submitted and we have waited for it to complete.
-        // Therefore the ValueResolver can simply check for task.isDone() and return its
result immediately.
         Task<String> t = newSleepTask(Duration.ZERO, "foo");
         app.getExecutionContext().submit(t).getUnchecked();
+        
+        // Below, we call ValueResolver.getMaybe() from this thread, which has no execution
context.
+        // However, the task has already been submitted and we have waited for it to complete.
+        // Therefore the ValueResolver can simply check for task.isDone() and return its
result immediately.
         Maybe<String> result = Tasks.resolving(t).as(String.class).timeout(Duration.ZERO).getMaybe();
         Assert.assertEquals(result.get(), "foo");
     }
 
     public void testUnsubmittedTaskWhenNoExecutionContextFails() {
-        // ValueResolver.getMaybe() is called with no execution context. Therefore it will
not execute the task.
         Task<String> t = newSleepTask(Duration.ZERO, "foo");
+        
+        // Below, we call ValueResolver.getMaybe() with no execution context. Therefore it
will not execute the task.
         Maybe<String> result = Tasks.resolving(t).as(String.class).timeout(Duration.ZERO).getMaybe();
         
         Assert.assertTrue(result.isAbsent(), "result="+result);
-        Exception exception = ((Maybe.Absent<?>)result).getException();
+        Exception exception = Maybe.getException(result);
         Assert.assertTrue(exception.toString().contains("no execution context available"),
"exception="+exception);
     }
 
     public void testUnsubmittedTaskWithExecutionContextExecutesAndReturns() {
-        // ValueResolver.getMaybe() is called in app's execution context. Therefore it will
execute the task.
         final Task<String> t = newSleepTask(Duration.ZERO, "foo");
         
+        // Below, we call ValueResolver.getMaybe() in app's execution context. Therefore
it will execute the task.
         Maybe<String>  result = app.getExecutionContext()
                 .submit(new Callable<Maybe<String> >() {
                     public Maybe<String>  call() throws Exception {
@@ -94,9 +96,10 @@ public class ValueResolverTest extends BrooklynAppUnitTestSupport {
     }
 
     public void testUnsubmittedTaskWithExecutionContextExecutesAndTimesOut() {
-        // ValueResolver.getMaybe() is called in app's execution context. Therefore it will
execute the task.
         final Task<String> t = newSleepTask(Duration.ONE_MINUTE, "foo");
         
+        // Below, we call ValueResolver.getMaybe() in app's execution context. Therefore
it will execute the task.
+        // However, it will quickly timeout as the task will not have completed.
         Maybe<String>  result = app.getExecutionContext()
                 .submit(new Callable<Maybe<String> >() {
                     public Maybe<String>  call() throws Exception {
@@ -105,7 +108,7 @@ public class ValueResolverTest extends BrooklynAppUnitTestSupport {
                 .getUnchecked();
         
         Assert.assertTrue(result.isAbsent(), "result="+result);
-        Exception exception = ((Maybe.Absent<?>)result).getException();
+        Exception exception = Maybe.getException(result);
         Assert.assertTrue(exception.toString().contains("not completed when immediate completion
requested"), "exception="+exception);
     }
 
@@ -140,11 +143,11 @@ public class ValueResolverTest extends BrooklynAppUnitTestSupport {
         assertContainsCallingMethod(callInfo.stackTrace, "testGetImmediately");
     }
     
-    public void testGetImmediateSupplierWithTimeoutUsesBlocking() {
+    public void testImmediateSupplierWithTimeoutUsesBlocking() {
         MyImmediateAndDeferredSupplier supplier = new MyImmediateAndDeferredSupplier();
         CallInfo callInfo = Tasks.resolving(supplier).as(CallInfo.class).context(app).timeout(Asserts.DEFAULT_LONG_TIMEOUT).get();
         assertNotNull(callInfo.task);
-        assertNotContainsCallingMethod(callInfo.stackTrace, "testGetImmediately");
+        assertNotContainsCallingMethod(callInfo.stackTrace, "testImmediateSupplierWithTimeoutUsesBlocking");
     }
     
     public void testGetImmediatelyInTask() throws Exception {
@@ -167,7 +170,7 @@ public class ValueResolverTest extends BrooklynAppUnitTestSupport {
         CallInfo callInfo = Tasks.resolving(supplier).as(CallInfo.class).context(app).immediately(true).get();
         assertNotNull(callInfo.task);
         assertEquals(BrooklynTaskTags.getContextEntity(callInfo.task), app);
-        assertNotContainsCallingMethod(callInfo.stackTrace, "testGetImmediately");
+        assertNotContainsCallingMethod(callInfo.stackTrace, "testGetImmediatelyFallsBackToDeferredCallInTask");
     }
     
     private static class MyImmediateAndDeferredSupplier implements ImmediateSupplier<CallInfo>,
DeferredSupplier<CallInfo> {


Mime
View raw message