UndeclaredThrowableException

40 views
Skip to first unread message

Johannes Ernst

unread,
Apr 2, 2012, 9:21:00 PM4/2/12
to jcl...@googlegroups.com
I'm invoking, at Rackspace,
Set<? extends NodeMetadata> nodes = comput.createNodesInGroup( "something", 1, tmpl );

and I'm getting an
UndeclaredThrowableException

with this stack trace:
at $Proxy149.listServers(Unknown Source)
at org.jclouds.cloudservers.compute.strategy.CloudServersComputeServiceAdapter.listNodes(CloudServersComputeServiceAdapter.java:81)
at org.jclouds.compute.strategy.impl.AdaptingComputeServiceStrategies.listDetailsOnNodesMatching(AdaptingComputeServiceStrategies.java:108)
at org.jclouds.compute.strategy.impl.AdaptingComputeServiceStrategies.listNodes(AdaptingComputeServiceStrategies.java:103)
at org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.getNextNames(CreateNodesWithGroupEncodedIntoNameThenAddToSet.java:143)
at org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.execute(CreateNodesWithGroupEncodedIntoNameThenAddToSet.java:123)
at org.jclouds.compute.internal.BaseComputeService.createNodesInGroup(BaseComputeService.java:200)

and this undeclaredThrowable:
TimeoutException

which in turn has this cause:
java.util.concurrent.ExecutionException: task submitted from the following trace
at org.jclouds.concurrent.config.ExecutorServiceModule$DescribedFuture.ensureCauseHasSubmissionTrace(ExecutorServiceModule.java:272)
at org.jclouds.concurrent.config.ExecutorServiceModule$DescribedFuture.get(ExecutorServiceModule.java:256)
at com.google.common.util.concurrent.ForwardingFuture.get(ForwardingFuture.java:69)
at com.google.common.util.concurrent.Futures$ChainingListenableFuture.get(Futures.java:661)
at org.jclouds.concurrent.ExceptionParsingListenableFuture.get(ExceptionParsingListenableFuture.java:74)
at org.jclouds.concurrent.internal.SyncProxy.invoke(SyncProxy.java:137)
at $Proxy149.listServers(Unknown Source)
at org.jclouds.cloudservers.compute.strategy.CloudServersComputeServiceAdapter.listNodes(CloudServersComputeServiceAdapter.java:81)
at org.jclouds.compute.strategy.impl.AdaptingComputeServiceStrategies.listDetailsOnNodesMatching(AdaptingComputeServiceStrategies.java:108)
at org.jclouds.compute.strategy.impl.AdaptingComputeServiceStrategies.listNodes(AdaptingComputeServiceStrategies.java:103)
at org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.getNextNames(CreateNodesWithGroupEncodedIntoNameThenAddToSet.java:143)
at org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.execute(CreateNodesWithGroupEncodedIntoNameThenAddToSet.java:123)
at org.jclouds.compute.internal.BaseComputeService.createNodesInGroup(BaseComputeService.java:200)

This is 1.4.0 I believe.

It seems to me:
* APIs, jclouds or otherwise, should not really throw UndeclaredThrowableExceptions. It would be an unusual developer who writes code that handles that … :-)
* In spite of the exception, Rackspace does seem to have created the server. But none of the thrown data contains any information (that I can find) that tells me about it, so I cannot write error handling code that kills it again. In other words, I keep accumulating "forgotten" servers in my Rackspace account
* And most importantly, just what went wrong here?

Cheers,


Johannes.

Adrian Cole

unread,
Apr 2, 2012, 10:19:33 PM4/2/12
to jcl...@googlegroups.com, jclou...@googlegroups.com
Hi, Johannes.
Unfortunately, the cause of your UndeclaredThrowableException is a
checked exception: TimeoutException, which is fact not declared :P

One way is to significantly up timeouts. Another is to do the EJB1
RemoteException thing and make all methods declare TimeoutException :)
Any other ideas?

-A

> --
> You received this message because you are subscribed to the Google Groups "jclouds" group.
> To post to this group, send email to jcl...@googlegroups.com.
> To unsubscribe from this group, send email to jclouds+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/jclouds?hl=en.
>

Johannes Ernst

unread,
Apr 3, 2012, 12:55:45 AM4/3/12
to jclou...@googlegroups.com, jcl...@googlegroups.com
Hi Adrian,

as a user of the API, it is very important to me that Exceptions are declared and documented. Because people like me like to use the jclouds API as a black box abstraction, the signature of a method (and accompanying prose) is about all the information that I have (and would like to need) to understand what might possibly happen if I invoke the method. Currently, the abstraction is leaky in various ways, e.g. UndeclaredThrowableException.

It seems to me that there are four major things that can go wrong when invoking the API: (correctly, that is)

1. the underlying cloud provider couldn't do what I, the client, requested, e.g. because they ran out of bits or such.
2. the cloud provider took longer than I, the client, was willing to wait
3. the "credibility" that I currently have with the cloud provider is insufficient for what I want, e.g. I'm not authenticated sufficiently, or my credit card is no good etc., or the budget I have set is too small for the requested operation. This includes things like "you must get approval from ops before you can provision more than X resources in Y timeframe".
4. jclouds had a bug / implemented something in an incomplete way etc.

I think I'd like to suggest that the public API could declare some (abstract) superclass exceptions for each of those four categories, and then throw appropriate subclasses. The client exception-handling code is most likely going to be structured along those lines anyway. To your point, TimeoutException is definitely one of those.

I don't think that a catch-all "JCloudsException" would do any good.

I'd also think that each of those exceptions must carry enough information so that I can "undo" whatever part of the operation did work. RunNodesException does this well; not all other exceptions do. Perhaps the coolest form of making this work would be an "undo" method on all exceptions thrown by jclouds with the promise that if I invoked it, the world would be as if I had never attempted the operation that failed.

And finally, on the timeouts, you have all these rather sophisticated mechanisms in place to specify variable lists of options to various operations. Shouldn't "and I want you to wait for N time and no longer" be one of those? Nothing wrong with (more or less) global defaults, but it would be nice if one could override them on a per-invocation basis, e.g. "I know this is a big image that will take a long time to provision".

I know I'm being one of "those" "customers" that always have those weird ideas that would take a lot of work, without having any of the ability to implement their crazy ideas. But I hope that at the least, usage feedback is useful and some input on how the ideal world would look like from a mere user of the API...

Cheers,


Johannes.

> You received this message because you are subscribed to the Google Groups "jclouds-dev" group.
> To post to this group, send email to jclou...@googlegroups.com.
> To unsubscribe from this group, send email to jclouds-dev...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/jclouds-dev?hl=en.
>

Adrian Cole

unread,
Apr 3, 2012, 1:05:30 AM4/3/12
to jcl...@googlegroups.com, jclou...@googlegroups.com
Dude. awesome feedback. Thanks for taking the time on it! Let's do
some plumbing and fix those leaks.

For starters, here's where some of the exception cases you've noted are.

http://www.jclouds.org/documentation/reference/jclouds-api

Let's see where we can get, and make this actionable.

On Mon, Apr 2, 2012 at 9:55 PM, Johannes Ernst <johanne...@gmail.com> wrote:
> Hi Adrian,
>
> as a user of the API, it is very important to me that Exceptions are declared and documented. Because people like me like to use the jclouds API as a black box abstraction, the signature of a method (and accompanying prose) is about all the information that I have (and would like to need) to understand what might possibly happen if I invoke the method. Currently, the abstraction is leaky in various ways, e.g. UndeclaredThrowableException.
>
> It seems to me that there are four major things that can go wrong when invoking the API: (correctly, that is)
>
> 1. the underlying cloud provider couldn't do what I, the client, requested, e.g. because they ran out of bits or such.

So, this is either an error (HttpResponseException) or
org.jclouds.rest.InsufficientResourcesException

> 2. the cloud provider took longer than I, the client, was willing to wait

Right now, we'd need to make an unchecked version of TimeoutException,
which we can totally do

> 3. the "credibility" that I currently have with the cloud provider is insufficient for what I want, e.g. I'm not authenticated sufficiently, or my credit card is no good etc., or the budget I have set is too small for the requested operation. This includes things like "you must get approval from ops before you can provision more than X resources in Y timeframe".

one of
org.jclouds.rest.AuthorizationException
org.jclouds.rest.InsufficientResourcesException

> 4. jclouds had a bug / implemented something in an incomplete way etc.

NullPointerException :p JK, but not really.. We do tend to use
IllegalStateException, but then again, we also use
IllegalStateException for retryable commands, so this is probably not
best.

>
> I think I'd like to suggest that the public API could declare some (abstract) superclass exceptions for each of those four categories, and then throw appropriate subclasses. The client exception-handling code is most likely going to be structured along those lines anyway. To your point, TimeoutException is definitely one of those.

K want to help choose names for the ones missing

>
> I don't think that a catch-all "JCloudsException" would do any good.

absolutely agree.. I hate exceptions like that.

>
> I'd also think that each of those exceptions must carry enough information so that I can "undo" whatever part of the operation did work. RunNodesException does this well; not all other exceptions do. Perhaps the coolest form of making this work would be an "undo" method on all exceptions thrown by jclouds with the promise that if I invoked it, the world would be as if I had never attempted the operation that failed.

That's cool, slightly unrealistic, but.. hey we can try! exception.tellMeLies()
Seriously, we could make an exception about a resource, which can have
a hook to delete said resource?

>
> And finally, on the timeouts, you have all these rather sophisticated mechanisms in place to specify variable lists of options to various operations. Shouldn't "and I want you to wait for N time and no longer" be one of those? Nothing wrong with (more or less) global defaults, but it would be nice if one could override them on a per-invocation basis, e.g. "I know this is a big image that will take a long time to provision".

So this is generally what the *AsyncClient stuff is for. now, if we
wanted to, we could probably do some thread-locally guice scope to
override stuff on a per-request basis. Any ideas?

>
> I know I'm being one of "those" "customers" that always have those weird ideas that would take a lot of work, without having any of the ability to implement their crazy ideas. But I hope that at the least, usage feedback is useful and some input on how the ideal world would look like from a mere user of the API...

No, I really enjoyed reading this. awesome!!

Adrian Cole

unread,
Apr 3, 2012, 1:09:26 AM4/3/12
to jcl...@googlegroups.com, jclou...@googlegroups.com
Also, there's an exception you might like: ScriptStillRunningException

Basically, if you createNodesInGroup and there are parallel operations
that call scripts, you can get one of these, which gives you a way to
wait longer, or, well, not :) Maybe we could generalize this.

Johannes Ernst

unread,
Apr 3, 2012, 12:15:48 PM4/3/12
to jclou...@googlegroups.com, jcl...@googlegroups.com

On Apr 2, 2012, at 22:09, Adrian Cole wrote:

> Also, there's an exception you might like: ScriptStillRunningException

I do like it. We have something like this in InfoGrid:

http://infogrid.org/files/downloads/infogrid-2.9.5-javadoc/ig-utils/modules/org.infogrid.util/dist/javadoc/org/infogrid/util/RemoteQueryTimeoutException.QueryIsOngoing.html

Now if Java Exceptions supported generics ...

Johannes Ernst

unread,
Apr 3, 2012, 12:18:31 PM4/3/12
to jclou...@googlegroups.com, jcl...@googlegroups.com
Here's another that should be a TimeoutException?

1) IllegalStateException on node 20730430:
java.lang.IllegalStateException: node(20730430) didn't achieve the state running within 1800 seconds, final state: RUNNING
at org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.call(CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.java:141)
at org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.apply(CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.java:170)
at org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.apply(CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.java:57)
at com.google.common.util.concurrent.Futures$4.apply(Futures.java:503)
at com.google.common.util.concurrent.Futures$4.apply(Futures.java:501)
at com.google.common.util.concurrent.Futures$3.apply(Futures.java:279)
at com.google.common.util.concurrent.Futures$ChainingListenableFuture.run(Futures.java:729)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)

Adrian Cole

unread,
Apr 3, 2012, 2:20:36 PM4/3/12
to jcl...@googlegroups.com, jclou...@googlegroups.com
thx.

I've been thinking about this, and I agree it is better to have
predictable means to deal with runtime errors. There's also a desire
to not redo things already in progress.

We've started using a lot of the guava code under the scenes in
efforts to rip out things we've otherwise invented. One very relevant
thing to this conversation is the following:

http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/util/concurrent/Futures.html#get%28java.util.concurrent.Future,%20long,%20java.util.concurrent.TimeUnit,%20java.lang.Class%29

What if we we used a subtype of RuntimeException like this suggests?
Then, one can inspect cause for known types as opposed to making up
new exception types. Ex.
org.jclouds.rest.RemoteCallStillRunningException extends
JCloudsException where getCause() must be TimeoutException? and has a
reference to the Future still running?

wdyt?
-A

Johannes Ernst

unread,
Apr 3, 2012, 3:03:45 PM4/3/12
to jclou...@googlegroups.com, jcl...@googlegroups.com
<bias importance="feel-free-to-ignore">
* I prefer checked Exceptions over RuntimeExceptions for APIs. As a user of an API who often doesn't read documentation in detail, I like the compiler to tell me that I need to read the documentation.
* From the link you sent: "…created by choosing an arbitrary public constructor…" Hmm … Personally I prefer factories over magic.
</bias>

Having said that, something like that will probably work. Having consistency is more important than agreement on style, as long as error handling isn't too complex. For example, it'd be great if the basic invocation could look something like this:

try {
return jclouds.someOperation();
} catch( CloudProviderMessedUpException ex ) {
user.tell( "Your cloud provider messed up" );
} catch( TimeoutException ex ) {
user.tell( "You said you are in a hurry." );
(the four exception types I listed earlier)

If I have to look at causes and types of causes etc. I'm likely not going to write the error handling code correctly, and as jclouds evolves, chances are it will suddenly return additional types and things I didn't expect, which will produce unexpected error conditions in production.

Just my two cents.

> You received this message because you are subscribed to the Google Groups "jclouds-dev" group.
> To post to this group, send email to jclou...@googlegroups.com.
> To unsubscribe from this group, send email to jclouds-dev...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/jclouds-dev?hl=en.
>

Adrian Cole

unread,
Apr 3, 2012, 3:12:43 PM4/3/12
to jcl...@googlegroups.com, jclou...@googlegroups.com

So lets do this?

Make a runtime type for fubar related things (aka system concerns) like the four types you mention. 

We can also declare/@throws relevant exceptions on methods likely to return one: (ex. InsufficientResourcesException can happen anywhere, but 90% of the time, it will be on createResource)

Without breaking everything these will likely need to use runtimeexceptions until/unless we migrate to new types.

Sound good?

-A
P.s. Where's the best place in javadoc to describe the four types? In the common parent?

Johannes Ernst

unread,
Apr 3, 2012, 3:35:01 PM4/3/12
to jclou...@googlegroups.com, jcl...@googlegroups.com
On Apr 3, 2012, at 12:12, Adrian Cole wrote:

So lets do this?

Make a runtime type for fubar related things (aka system concerns) like the four types you mention. 

We can also declare/@throws relevant exceptions on methods likely to return one: (ex. InsufficientResourcesException can happen anywhere, but 90% of the time, it will be on createResource)

Without breaking everything these will likely need to use runtimeexceptions until/unless we migrate to new types.

Sound good?

-A
P.s. Where's the best place in javadoc to describe the four types? In the common parent?

I'd suggest a page on the wiki, and a link from all methods that might throw any of them.

Alternatively, in a package.html in a suitable package. That might be easier to version.
Reply all
Reply to author
Forward
0 new messages