Hi David:

Discussion below…

Cheers,

Greg Trasuk.

> On Jun 11, 2015, at 4:45 AM, Dawid Loubser <da...@travellinck.com> wrote:
> 
> I agree wholeheartedly with Palash Ray. The problem with this principle
> of "RemoteException" in River, which I have never agreed with, is twofold:
> 
>  * The most common and correct interpretation of checked / unchecked
>    exceptions in Java, seen in the light of design-by-contract, is
>      o Unchecked exceptions (RuntimeException) are an abstraction for
>        an unexpected *system error* at that level of granularity. This
>        could range from a code bug (NullPointerException) to some
>        underlying database server being down. Neither are the caller's
>        fault, and the caller should not be forced to handle the
>        individual failure possibilities by *type* - because literally
>        anything can go wrong. Underlying comms failure
>        (RemoteException) logically falls in this class of service, but
>        doesn't by type (i.e. it is not a RuntimeException)
>      o Checked exceptions are a signal for *refusing a service* because
>        a *precondition was not met* (e.g. withdrawing money from an
>        account with no funds). This is expected, and part of the normal
>        operation of the system. The client should, as part of engaging
>        with a contract, have a plan of action for all refusal
>        scenarios, and the compiler helps us here with checked exceptions.

I always like to think in terms of system exceptions and application (or 
business) exceptions.  In that classification scheme, IOException stemming from 
a call to a proxy for my remote pizza-ordering service would be a system 
exception, while  a BadItemsException that means “No, I won’t put pineapples 
with on the same pizza with olives” would be an application exception.  I don’t 
think checked/unchecked implies any mapping to system/application. 

Checked exceptions (I think) were an attempt to enforce exception handling at 
compile-time, as a reaction to the usually terrible error handling that most of 
us wrote in ‘C’ programs.  Unfortunately, it turns out that developers were 
just as determined to subvert the checked-exception mechanism, with things like 
empty catch statements, “log-and-forget” code, etc.  So in the end, we got code 
cruft without the expected benefits.  Further, checked exceptions work against 
our current love for dependency injection and CDI-type programming.

So I’m kind of with you on getting rid of the checked exceptions.  Except…

>  * Interfaces are, and should be, designed based on the pure
>    functionality that they provide. I should not have to add
>    SQLException to an interface because some implementation uses a SQL
>    database, and similarly, I should not add RemoteException because
>    some implementation is a proxy to a remote object. In both cases, at
>    that particular level of granularity, the exception denotes an
>    unexpected System error. It's nice to classify the nature of these
>    errors, but for that, the RuntimeException could wrap the
>    RemoteException or SQLException as 'cause’
> 
> Plug-ability of components are severely compromised if I have to change
> my interface because of an implementation change (i.e. remote to local).
> I understand that it's useful to "remind" people of things, but the
> thing that should, rather, be reminded of is whether a service exhibits
> call-by-reference of call-by-value semantics (regardless of whether it's
> "remote" or not). The wholesale move away from traditional
> object-oriented style to services-oriented style means that very few
> people write services with expected call-by-reference semantics in
> anyway, so I don't think this is a significant problem.

…except that remote calls are an extremely leaky abstraction (as per “A Note on 
Distributed Computing” and experience).  If you have a communications failure 
(IOException), it means just that - there was a communications failure. You 
don’t know whether it happened on sending the call to the remote actor or on 
receiving the reply.  What’s the right way to handle it?  Try it again?  Tell 
the user we couldn’t do the operation?  Cancel the transaction?  Store the call 
in a log file to checkup on it later?  I don’t know.  It depends on the 
application and the service contract, and inevitably, the service consumer has 
to make the decision.  Things really are different on a network.  And the 
developer writing a service consumer needs to be aware of that.

Tagging an interface “Remote” does that, but also implies an implementation 
choice, which doesn’t seem right.  So when I create a service interface, I 
don’t tag it Remote, but I have the methods throw IOException (not 
RemoteException, because that implies implementation with RMI.  Although in a 
sense, RemoteException is more accurate than IOException because it properly 
connotes the ambiguity around when the exception happened.  Ugh!).  I agree it 
would be kind of nice to have an unchecked version of IOException or 
RemoteException.

> 
> If I could have one feature in River, it would be the following:
> 
>  * Make RemoteException extend RuntimeException (i.e. be unchecked)

yeah, I agree.  Practically, we’d have to create a new exception, since 
RemoteException is in the Java API.  Would also imply changes to the Exporter 
contract and implementations.

>  * Introduce (or use, if present) a mechanism - annotation? - to
>    indicate by-ref/by-value calling semantics (on inputs/outputs of a
>    service)

not sure if that’s all that useful.  Seems like javadoc would cover it.  
Wouldn’t surprise me if there’s an annotation out there already.

>  * It's perfectly fine to still enforce service implementations to
>    declare RemoteException, as a "tag" / "reminder", but honestly, it's
>    not the client's concern. Depending on the reliability requirements
>    of the client, they need to handle unexpected failure in anyway, and
>    RemoteException is functionally no different than, say, a NullPointer.

I disagree.  In my experience, communications exceptions need to be carefully 
considered by the service consumer.

> 
> Many people may not agree with this take on the matter. I'm merely
> reflecting on many years of building pluggable, services-oriented
> systems in Java. This is the one flaw in River that propagates up to a
> "design" (contract, interface) level.
> 
> regards,
> 
> Dawid Loubser
> 
> 
> On 09/06/2015 14:45, Greg Trasuk wrote:
>> If you’re making remote calls, then there is a definite chance that you will 
>> have communications errors.  So, it’s probably not a good idea to just hide 
>> the errors, especially since the application handling/response to a 
>> communications error really should be different from the handling of an 
>> applications error.  With a communications error, (1) it may be worthwhile 
>> to just try it again later, (2) you don’t really know whether the other end 
>> processed the call, so the response is somewhat indeterminate.  As a result, 
>> we typically don’t recommend using unchecked exceptions.  The Remote 
>> interface and the IOException that’s thrown from a remote call is meant to 
>> remind developers that things are different on a network.
>> 
>> For more thoughts on this, you should read “A Note on Distributed Computing” 
>> (http://eecs.harvard.edu/~waldo/Readings/waldo-94.pdf 
>> <http://eecs.harvard.edu/~waldo/Readings/waldo-94.pdf>).  This paper really 
>> forms the basis of the Jini philosophy, along with the Eight Fallacies 
>> (http://en.wikipedia.org/wiki/Fallacies_of_distributed_computing 
>> <http://en.wikipedia.org/wiki/Fallacies_of_distributed_computing>).
>> 
>> Having said that, if you really want to use unchecked exceptions, just write 
>> a smart proxy that converts the IOExceptions to some runtime exception (you 
>> could probably even do this generically using “java.lang.reflect.Proxy”), 
>> and register the smart proxy with Reggie rather than the actual exported 
>> endpoint.
>> 
>> Cheers,
>> 
>> Greg Trasuk
>> 
>>> On Jun 8, 2015, at 3:49 PM, Palash Ray <paa...@gmail.com> wrote:
>>> 
>>> Devs,
>>> 
>>> I have long struggled with the fact that we have to declare a
>>> RemoteException for every Remote method that I expose. I do not like
>>> the try catch, which is pretty verbose, and in our application, when
>>> we do encounter a RemoteExceotion, its always fatal, and there is no
>>> way we can, or want, to recover from it.
>>> 
>>> I would like to explore the possibility of using an unchecked
>>> exception, instead.
>>> 
>>> I guess it would work if I extend the BasicIlFactory and override the
>>> method, which checks for the presence of the RemoteException in the
>>> remote method. However, it seems to me to be a bit hacky.
>>> 
>>> Is there an elegant solution to this problem? Thoughts please.
>>> 
>>> Thanks,
>>> Palash.
>> 
> 

Reply via email to