Throwing Exceptions in RPCHandler

I’ve set up an RPCHandler like in the Ignition Programmer’s Guide. If I try to throw an exception to be caught on a component from the RPCHandler then things go wrong. Both on the RPCHandler and on the interface it implements I’ve specified “throws MyException”. I think at some point my thrown exception gets wrapped as a GatewayException. I’m guessing because my RPCHandler doesn’t specify that it throws GatewayExceptions (which I don’t think it’s even possible for it throw a gateway exception because GatewayException is defined in client scope), the GatewayException is then wrapped in an UndeclaredThrowableException. How can I get my original exception back to the function caller without unwrapping all the layers?

I don’t think custom exception types can be propagated from gateway to client/designer through the module RPC system. Any exceptions caught have their cause, message, stack trace… extracted and sent to the client, where it re-assembles it as a new Throwable that I think you can find embedded in the GatewayException.

I think this all happens mostly due to some complex serialization issues.

I see. Is it possible to specify all my functions in the RPCHandler throw GatewayExceptions so I can at least avoid the UndeclaredThrowableException? I tried to import com.inductiveautomation.ignition.client.gateway_interface.GatewayException but the gateway complains it can’t be found. Is it a good idea to try to import GatewayException into my RPCHandler and see if I can adjust the build to make it work? Or is there some other way?

Assuming I can get the functions in my RPCHandler to throw GatewayExceptions, would you catch gatewayexceptions with something like this:

try{ rpc.doStuff() } catch(GatewayException e){ if(e.getCause()!=null){ if(e.getCause() is MyException){ //handle MyException } else if (e.getCause() is MyOtherException){ //handle MyOtherException } } }

I’m not quite sure where the UndeclaredThrowableException is coming from - I don’t think it’s us.

If you change your handler so it just throws a vanilla Exception what happens?

Kevin, you are correct. The UndeclaredThrowable isn’t from you guys (edit: not directly at least).

My function signature is:

void doStuff() throws MyException;

When calling rpc.doStuff(), java expects that it won’t throw a GatewayException so when it does throw a GatewayException, it wraps it in UndeclaredThrowableException.

I want my function’s signature to be:

void doStuff() throws GatewayException;

But I believe I cannot do that because GatewayException is a client-side thing.

And throwing Exception I think is considered bad practice because then anywhere that I call rpc.doStuff(), I either have to rethrow Exception everywhere or catch the original and throw a runtime Exception instead.

EDIT: I should add that throwing Exception does indeed stop the UndeclaredThrowableException, but it’s not ideal.

It’s not ideal, but I think it’s all get you get with the RPC system - either your functions don’t throw at all, or they throw a generic Exception.

I figured that might be the case :frowning:. Thanks for your help though :smiley:

One other workaround, kind of a hack, but still: Never throw from the RPC calls, and instead return a “result” object of your own creation, that can hold both a good/success result and a throwable/exception in the case of failure. The throwable inside your result object will not be touched by the RPC and serialization logic.