From 1f4e22c6c9b25713d5dd0ee1e954178d527da56d Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sat, 29 Sep 2012 14:01:51 -0700 Subject: [PATCH] reveal underlying exception that causes a guice provider to fail --- .../concurrent/internal/SyncProxy.java | 8 ++++- .../RegionIdsFromRegionIdToURIKeySet.java | 8 ++++- .../rest/internal/AsyncRestClientProxy.java | 35 +++++++++++-------- .../rest/internal/BaseRestApiExpectTest.java | 1 - .../internal/RestAnnotationProcessorTest.java | 20 +++++++++-- 5 files changed, 53 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/jclouds/concurrent/internal/SyncProxy.java b/core/src/main/java/org/jclouds/concurrent/internal/SyncProxy.java index 13b30caf7f..bd6450ca82 100644 --- a/core/src/main/java/org/jclouds/concurrent/internal/SyncProxy.java +++ b/core/src/main/java/org/jclouds/concurrent/internal/SyncProxy.java @@ -21,6 +21,7 @@ package org.jclouds.concurrent.internal; import static com.google.common.base.Preconditions.checkState; import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; @@ -41,6 +42,7 @@ import org.jclouds.util.Throwables2; import com.google.common.base.Function; import com.google.common.base.Optional; +import com.google.common.base.Throwables; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -158,7 +160,11 @@ public class SyncProxy implements InvocationHandler { } return returnVal; } else if (syncMethodMap.containsKey(method)) { - return syncMethodMap.get(method).invoke(delegate, args); + try { + return syncMethodMap.get(method).invoke(delegate, args); + } catch (InvocationTargetException e) { + throw Throwables.propagate(e.getCause()); + } } else { try { return ((ListenableFuture) methodMap.get(method).invoke(delegate, args)).get(timeoutMap.get(method), diff --git a/core/src/main/java/org/jclouds/location/suppliers/derived/RegionIdsFromRegionIdToURIKeySet.java b/core/src/main/java/org/jclouds/location/suppliers/derived/RegionIdsFromRegionIdToURIKeySet.java index 6808ae5a13..c0e1bc4481 100644 --- a/core/src/main/java/org/jclouds/location/suppliers/derived/RegionIdsFromRegionIdToURIKeySet.java +++ b/core/src/main/java/org/jclouds/location/suppliers/derived/RegionIdsFromRegionIdToURIKeySet.java @@ -18,6 +18,7 @@ */ package org.jclouds.location.suppliers.derived; +import java.lang.reflect.UndeclaredThrowableException; import java.net.URI; import java.util.Map; import java.util.Set; @@ -28,6 +29,7 @@ import org.jclouds.location.Region; import org.jclouds.location.suppliers.RegionIdsSupplier; import com.google.common.base.Supplier; +import com.google.common.base.Throwables; import com.google.inject.Inject; /** @@ -45,6 +47,10 @@ public class RegionIdsFromRegionIdToURIKeySet implements RegionIdsSupplier { @Override public Set get() { - return regionIdToURISupplier.get().keySet(); + try { + return regionIdToURISupplier.get().keySet(); + } catch (UndeclaredThrowableException e) { + throw Throwables.propagate(e.getCause()); + } } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java b/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java index b670359028..5732010210 100644 --- a/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java +++ b/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java @@ -22,7 +22,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.util.NoSuchElementException; import java.util.concurrent.ExecutionException; import javax.annotation.Resource; @@ -49,12 +48,14 @@ import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Supplier; +import com.google.common.base.Throwables; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.inject.Binding; +import com.google.inject.ConfigurationException; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; @@ -176,8 +177,10 @@ public class AsyncRestClientProxy implements InvocationHandler { try { Annotation qualifier = Iterables.find(ImmutableList.copyOf(method.getAnnotations()), isQualifierPresent); return getInstanceOfTypeWithQualifier(genericReturnType, qualifier); - } catch (NoSuchElementException e) { - return getInstanceOfType(genericReturnType); + } catch (ProvisionException e) { + throw Throwables.propagate(e.getCause()); + } catch (RuntimeException e) { + return instanceOfTypeOrPropagate(genericReturnType, e); } } catch (ProvisionException e) { AuthorizationException aex = Throwables2.getFirstThrowableOfType(e, AuthorizationException.class); @@ -188,19 +191,23 @@ public class AsyncRestClientProxy implements InvocationHandler { } // TODO: tidy - private Object getInstanceOfType(Type genericReturnType) { - // look for an existing binding - Binding binding = injector.getExistingBinding(Key.get(genericReturnType)); - if (binding != null) - return binding.getProvider().get(); + private Object instanceOfTypeOrPropagate(Type genericReturnType, RuntimeException e) { + try { + // look for an existing binding + Binding binding = injector.getExistingBinding(Key.get(genericReturnType)); + if (binding != null) + return binding.getProvider().get(); - // then, try looking via supplier - binding = injector.getExistingBinding(Key.get(Types.newParameterizedType(Supplier.class, genericReturnType))); - if (binding != null) - return Supplier.class.cast(binding.getProvider().get()).get(); + // then, try looking via supplier + binding = injector.getExistingBinding(Key.get(Types.newParameterizedType(Supplier.class, genericReturnType))); + if (binding != null) + return Supplier.class.cast(binding.getProvider().get()).get(); - // else try to create an instance - return injector.getInstance(Key.get(genericReturnType)); + // else try to create an instance + return injector.getInstance(Key.get(genericReturnType)); + } catch (ConfigurationException ce) { + throw e; + } } // TODO: tidy diff --git a/core/src/test/java/org/jclouds/rest/internal/BaseRestApiExpectTest.java b/core/src/test/java/org/jclouds/rest/internal/BaseRestApiExpectTest.java index dfe4789c48..b922cbec82 100644 --- a/core/src/test/java/org/jclouds/rest/internal/BaseRestApiExpectTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/BaseRestApiExpectTest.java @@ -73,7 +73,6 @@ import org.jclouds.providers.ProviderMetadata; import org.jclouds.rest.RestApiMetadata; import org.jclouds.rest.config.CredentialStoreModule; import org.jclouds.util.Strings2; -import org.testng.annotations.Test; import org.w3c.dom.Node; import com.google.common.annotations.Beta; diff --git a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java index 0bce56fcd5..3050d2eba5 100644 --- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java @@ -43,6 +43,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -2476,6 +2477,10 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { @Provides Set exception(); + @Named("NoSuchElementException") + @Provides + Set noSuchElementException(); + @POST @Path("/") void oneForm(@PathParam("bucket") String path); @@ -2497,7 +2502,12 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { public void testProvidesWithGenericQualifiedAuthorizationException() throws SecurityException, NoSuchMethodException { injector.getInstance(AsyncClientFactory.class).create(TestClassForm.class).exception(); } - + + @Test(expectedExceptions = NoSuchElementException.class) + public void testProvidesWithGenericQualifiedNoSuchElementException() throws SecurityException, NoSuchMethodException { + injector.getInstance(AsyncClientFactory.class).create(TestClassForm.class).noSuchElementException(); + } + @Test public void testBuildOneClassForm() throws SecurityException, NoSuchMethodException { Method oneForm = TestClassForm.class.getMethod("oneForm", String.class); @@ -2664,7 +2674,13 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { Set exception() { throw new AuthorizationException(); } - + + @Provides + @Named("NoSuchElementException") + Set noSuchElementException() { + throw new NoSuchElementException(); + } + })).buildInjector(); parserFactory = injector.getInstance(ParseSax.Factory.class); crypto = injector.getInstance(Crypto.class);