Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Java Local Exceptions #2590

Merged

Conversation

InsertCreativityHere
Copy link
Member

@InsertCreativityHere InsertCreativityHere commented Jul 31, 2024

This PR finishes our refactoring of local exceptions by doing it in Java.
For a list of which exceptions changed to what, see this table from the original PR.

Along the way, I cross-checked my changes with the other languages.
While doing so, I noticed some bugs, inconsistencies, typos, etc. that seemed small and related enough to just fix in this PR.

@InsertCreativityHere InsertCreativityHere marked this pull request as ready for review August 5, 2024 21:44

public DatagramLimitException(Throwable cause) {
super(cause);
this("");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look correct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The C# version has a single ctor:

public DatagramLimitException()
        : base(message: "Datagram limit exceeded.", innerException: null)
    {
    }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look correct.

I fixed the message

The C# version has a single ctor

This is because of a difference in the UdpTransceiver.
In C#, we just use the default message:
throw new Ice.DatagramLimitException();
but in Java, we also include the packetSize in the message:
throw new com.zeroc.Ice.DatagramLimitException("message size of " + buf.size() + " exceeds the maximum packet size of " + packetSize);

In C++, we don't include this extra information:
throw DatagramLimitException(__FILE__, __LINE__);
So, Java is the odd-one-out here.
But this information seems useful to have... If you exceeded a limit, it's good to know what the limit was, right?

super(cause);
public final class InvocationCanceledException extends LocalException {
public InvocationCanceledException() {
super("invocation canceled");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be consistent with the InvocationTimeoutException message.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed by making it a proper sentence.

}

/** This exception is raised for errors during marshaling or unmarshaling. */
public final class MarshalException extends ProtocolException {
public MarshalException(String reason) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string parameter should be renamed 'message'.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, fixed.

/** Base class for all Ice run-time exceptions. */
public abstract class LocalException extends Exception {
/** Base class for Ice run-time exceptions. */
public class LocalException extends Exception {
public LocalException() {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove this parameterless constructor. The caller (including derived classes) must provide a message and/or a cause.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed. Now all constructors require a String message.

public LocalException(String message) {
super(message);
}

public LocalException(Throwable cause) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we need this cause-only constructor.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also removed. Now all constructors require a String message.

this.unknown = unknown;
}

public UnknownException(String unknown, Throwable cause) {
super(cause);
super("unknown exception with type ID '" + unknown + "'", cause);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is bogus.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, after discussing what this parameter actually holds.

public UnknownException(Throwable cause) {
super(cause);
this.unknown = "";
}

public UnknownException(String unknown) {
super("unknown exception with type ID '" + unknown + "'");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is bogus.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, after discussing what this parameter actually holds.

super(cause);
}

public final class UnknownLocalException extends UnknownException {
public UnknownLocalException(String unknown) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be message, not unknown.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, we only have a single constructor, which only takes a String message.

super(cause);
}

public final class UnknownUserException extends UnknownException {
public UnknownUserException(String unknown) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be message, not unknown.

Also, please don't provide a 'cause' constructor.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, we only have a single constructor, which only takes a String message.

this.id = new Identity();
this.facet = "";
this.operation = "";
this(new Identity(), "", "");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't produce a good message.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

/** This exception indicates a DNS problem. */
public final class DNSException extends SyscallException {
public DNSException(String host) {
super("Cannot resolve host '" + host + "'");
this.host = host;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We remove the host field in C#

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in Java.

/** This exception indicates a DNS problem. */
public final class DNSException extends SyscallException {
public DNSException(String host) {
super("Cannot resolve host '" + host + "'");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can do:

Suggested change
super("Cannot resolve host '" + host + "'");
this(host, null);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly surprising, but calling super(message, null) is slightly different than super(message). since these constructors do different things, and the default value for cause isn't actually null, it's self, which acts as a special sentinel value.

My understanding is that explicitly setting a null cause is used to indicate that something caused it, but for some reason it's unknown. Which is not the case here.

It probably doesn't matter here... this is a niche exception, but also I find the duplication to be pretty small anyways.

Comment on lines 8 to 9
super("Cannot resolve host '" + host + "'");
this.host = host;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we call the other constructor here?

Suggested change
super("Cannot resolve host '" + host + "'");
this.host = host;
this(host, null);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly surprising, but calling super(message, null) is slightly different than super(message). since these constructors do different things, and the default value for cause isn't actually null, it's self, which acts as a special sentinel value.

My understanding is that explicitly setting a null cause is used to indicate that something caused it, but for some reason it's unknown. Which is not the case here.


public DatagramLimitException(Throwable cause) {
super(cause);
this("");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The C# version has a single ctor:

public DatagramLimitException()
        : base(message: "Datagram limit exceeded.", innerException: null)
    {
    }

public Exception(String message) {
super(message);
}

public Exception(Throwable cause) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this constructor?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I deleted it.

I thought that UserException derived from this class, but apparently it doesn't in Java (because of checked vs unchecked exceptions).

@@ -22,26 +9,11 @@
*/
public class RequestFailedException extends LocalException {
public RequestFailedException() {
this.id = new Identity();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constructor should not call the other.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, my bad.
Fixed.


public RequestFailedException(Identity id, String facet, String operation, Throwable cause) {
super(cause);
super(createMessage("RequestFailedException", id, facet, operation));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The derived classes must pass the typeName, we don't want to use RequestFailedException in the message.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, I forgot to add a typename parameter to this constructor.

public UnknownException() {
this.unknown = "";
}

public UnknownException(Throwable cause) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other mappings have a single constructor with the message.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java makes frequent use of the constructor, mostly in cases where we encounter a competely unknown exception, that we know nothing else about, and just wrap in an UnknownException.
Looking at the corresponding code in C#, we don't handle these exceptions, and just let them throw upwards.
But, some of those places have comments which suggests the Java behavior is more correct.

For example in ConnectionI, java has an extra catch for truly unknown exceptions:

} catch (LocalException ex) {
  dispatchException(ex, requestCount);
} catch (RuntimeException | java.lang.Error ex) {
  // A runtime exception or an error was thrown outside of servant code (i.e., by Ice code).
  // Note that this code does NOT send a response to the client.
  var uex = new UnknownException(ex);

and in C#, we just have a TODO.

catch (LocalException ex) // TODO: catch all exceptions
{
    dispatchException(ex, requestCount);
}

Or in LoggerAdminLoggerI, java has an extra else to handle truly unknown exceptions,

if (ex instanceof com.zeroc.Ice.CommunicatorDestroyedException) {
  // Expected if there are outstanding calls during communicator destruction.
} else if (ex instanceof com.zeroc.Ice.LocalException) {
  _loggerAdmin.deadRemoteLogger(
      p, _localLogger, (com.zeroc.Ice.LocalException) ex, "log");
} else {
  _loggerAdmin.deadRemoteLogger(
      p, _localLogger, new com.zeroc.Ice.UnknownException(ex), "log");
}

whereas C# looks like it just silently ignores unknown errors here:

catch (AggregateException ae)
{
    if (ae.InnerException is Ice.CommunicatorDestroyedException)
    {
        // expected if there are outstanding calls during communicator destruction
    }
    if (ae.InnerException is Ice.LocalException)
    {
        _loggerAdmin.deadRemoteLogger(p, _localLogger,
                                      (Ice.LocalException)ae.InnerException, "log");
    }
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should definitely remove Throwable from all UnknownException constructors and fix any code that use a UnknownException Throwable constructor.

The name Unknown is confusing but we can't change it. An UnknownException is not unknown. It's a very specific exception that means a dispatch failed with an "other" exception (other than local exception or user exception).
Whoever wrote the Java code you're showing above was unfortunately confused by the name.

We also don't want users to think "I'll throw an UnknownException that wraps some random exception - Ice likes that and will send something sensible to the client" because that's not the case.


ex.unknown = unknown;
throw ex;
String unknownId = is.readString();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We read the message:

String message = ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, I had misunderstood what this unknown field truly held.

@@ -348,6 +348,7 @@ function skipSlice(obj)
catch e
reason = sprintf('constructor failed for type %s with compact id %d', ...
eval(sprintf('IceCompactId.TypeId_%d.typeId', compactId)), compactId);
% TODO does this type still exist in MATLAB?
ex = Ice.NoValueFactoryException('', reason, reason, '');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems this is the only occurrence, better create a separate issue to fix it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bernardnormier beat me to opening an issue, and already opened a PR to fix this: #2626

@@ -2581,7 +2581,7 @@ Slice::Gen::TypeScriptVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p)
_out << nl << " * @param communicator - The communicator for the new proxy.";
_out << nl << " * @param proxyString - The string representation of the proxy.";
_out << nl << " * @returns The new " << prx << " proxy.";
_out << nl << " * @throws ProxyParseException - Thrown if the proxyString is not a valid proxy string.";
_out << nl << " * @throws ParseException - Thrown if the proxyString is not a valid proxy string.";
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProxyParseException was replaced with ParseException

@@ -203,7 +203,7 @@ public Reference create(string s, string propertyPrefix)
end = Ice.UtilInternal.StringUtil.checkQuote(s, beg);
if (end == -1)
{
throw new ParseException($"mismatched quotes around value for '{option}' option in proxy string '{s}'");
throw new ParseException($"mismatched quotes around value for {option} option in proxy string '{s}'");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everywhere else in this file, we don't put quotes around the {option} (ex: -c, -t, -h, ...)

@@ -233,12 +233,12 @@ protected override bool checkOption(string option, string argument, string endpo
_timeout = int.Parse(argument, CultureInfo.InvariantCulture);
if (_timeout < 1)
{
throw new ParseException($"invalid timeout value '{argument}' in endpoint {endpoint}");
throw new ParseException($"invalid timeout value '{argument}' in endpoint '{endpoint}'");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In every other place in this PR, we always wrapped the {endpoint} in single quotes

@@ -337,7 +337,7 @@ protected override bool checkOption(string option, string argument, string endpo
{
if (argument == null)
{
throw new ParseException($"unexpected argument '{argument}' provided for {option} option in endpoint '{endpoint}'");
throw new ParseException($"no argument provided for {option} option in endpoint '{endpoint}'");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looked like an over-zealous copy/paste.
This is what the message used to be, and continues to be in other place we test for a null argument.
Also it's kind of weird to check argument == null, then try to print it...

@@ -1441,7 +1441,7 @@ private List<EndpointI> parseEndpoints(string endpts, bool oaEndpoints)
EndpointI endp = _instance.endpointFactoryManager().create(s, oaEndpoints);
if (endp is null)
{
throw new ParseException($"invalid object adapter endpoint {s}'");
throw new ParseException($"invalid object adapter endpoint '{s}'");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mismatched single quotes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like this should also be a full sentence, but I'm going to leave it alone for now.

@@ -22,26 +9,11 @@
*/
public class RequestFailedException extends LocalException {
public RequestFailedException() {
this.id = new Identity();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, my bad.
Fixed.


public RequestFailedException(Identity id, String facet, String operation, Throwable cause) {
super(cause);
super(createMessage("RequestFailedException", id, facet, operation));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, I forgot to add a typename parameter to this constructor.

public UnknownException() {
this.unknown = "";
}

public UnknownException(Throwable cause) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java makes frequent use of the constructor, mostly in cases where we encounter a competely unknown exception, that we know nothing else about, and just wrap in an UnknownException.
Looking at the corresponding code in C#, we don't handle these exceptions, and just let them throw upwards.
But, some of those places have comments which suggests the Java behavior is more correct.

For example in ConnectionI, java has an extra catch for truly unknown exceptions:

} catch (LocalException ex) {
  dispatchException(ex, requestCount);
} catch (RuntimeException | java.lang.Error ex) {
  // A runtime exception or an error was thrown outside of servant code (i.e., by Ice code).
  // Note that this code does NOT send a response to the client.
  var uex = new UnknownException(ex);

and in C#, we just have a TODO.

catch (LocalException ex) // TODO: catch all exceptions
{
    dispatchException(ex, requestCount);
}

Or in LoggerAdminLoggerI, java has an extra else to handle truly unknown exceptions,

if (ex instanceof com.zeroc.Ice.CommunicatorDestroyedException) {
  // Expected if there are outstanding calls during communicator destruction.
} else if (ex instanceof com.zeroc.Ice.LocalException) {
  _loggerAdmin.deadRemoteLogger(
      p, _localLogger, (com.zeroc.Ice.LocalException) ex, "log");
} else {
  _loggerAdmin.deadRemoteLogger(
      p, _localLogger, new com.zeroc.Ice.UnknownException(ex), "log");
}

whereas C# looks like it just silently ignores unknown errors here:

catch (AggregateException ae)
{
    if (ae.InnerException is Ice.CommunicatorDestroyedException)
    {
        // expected if there are outstanding calls during communicator destruction
    }
    if (ae.InnerException is Ice.LocalException)
    {
        _loggerAdmin.deadRemoteLogger(p, _localLogger,
                                      (Ice.LocalException)ae.InnerException, "log");
    }
}


ex.unknown = unknown;
throw ex;
String unknownId = is.readString();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, I had misunderstood what this unknown field truly held.

@@ -348,6 +348,7 @@ function skipSlice(obj)
catch e
reason = sprintf('constructor failed for type %s with compact id %d', ...
eval(sprintf('IceCompactId.TypeId_%d.typeId', compactId)), compactId);
% TODO does this type still exist in MATLAB?
ex = Ice.NoValueFactoryException('', reason, reason, '');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bernardnormier beat me to opening an issue, and already opened a PR to fix this: #2626

public UnknownException() {
this.unknown = "";
}

public UnknownException(Throwable cause) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should definitely remove Throwable from all UnknownException constructors and fix any code that use a UnknownException Throwable constructor.

The name Unknown is confusing but we can't change it. An UnknownException is not unknown. It's a very specific exception that means a dispatch failed with an "other" exception (other than local exception or user exception).
Whoever wrote the Java code you're showing above was unfortunately confused by the name.

We also don't want users to think "I'll throw an UnknownException that wraps some random exception - Ice likes that and will send something sensible to the client" because that's not the case.

* exceptions declared in the <code>throws</code> clause can be raised.
* The dispatch returned a {@link UserException} that was not declared in the operation's exception
* specification (the <code>throws</code> clause). This is necessary in order to not violate the
* contract established by an operation's signature: Only local exceptions and user exceptions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doc comment is bogus.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? Do we allow arbitrary user exceptions to be thrown now?


public UnknownUserException(String unknown, Throwable cause) {
super(unknown, cause);
public UnknownUserException(String message, Throwable cause) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please no Throwable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this.
In Java, we used to store the actual UserException in this field, so we could put it's stack trace in the expectedDetails.
Removing this does means that the details will be less... detailed now.

@@ -179,7 +179,7 @@ Ice::ThreadHookPlugin::ThreadHookPlugin(
{
if (communicator == nullptr)
{
throw PluginInitializationException(__FILE__, __LINE__, "Communicator cannot be null");
throw PluginInitializationException(__FILE__, __LINE__, "Communicator cannot be null.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please revert.
In C++, the style we adopted is lowercase and no period. It should actually be communicator here.

I'm just trying to keep all the error messages consistent across languages.

We don't want to do that. The goal is for error messages in language X to be consistent with error message in language X. Not adopt our own cross-language Ice style.

@@ -934,7 +934,7 @@ Ice::ObjectAdapterI::initialize(optional<RouterPrx> router)
//
if (router == nullopt && noProps)
{
throw InitializationException(__FILE__, __LINE__, "object adapter `" + _name + "' requires configuration");
throw InitializationException(__FILE__, __LINE__, "Object adapter `" + _name + "' requires configuration.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert all these updates.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, now that I have a bearing for what the intent is, I'll revert/fix my changes as necessary.
Unfortunately, we're very inconsistent about which message style we use across our languages, so extrapolated the wrong idea.

One day we should consider a cleanup pass to fix all these messages...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed all my changes to the messages, not by reverting them, but by changing them to be correct in each language.
Since most of them didn't follow the guidelines you laid out...

@@ -171,7 +171,7 @@ public void close(ConnectionClose mode)
setState(
StateClosing,
new ConnectionClosedException(
"The connection was closed gracefully by the application.",
"Connection closed gracefully by the application.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The preferred style in C# is a full sentence. So I would keep "Ther connection was ..." and fix the message below.

@@ -44,7 +44,7 @@ public void initializePlugins()
{
if (_initialized)
{
throw new InitializationException("Plug-ins already initialized.");
throw new InitializationException("plug-ins already initialized");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should follow each programming language best practices. In C#, it's full sentences, starting with a capital letter and ending with a period. Please revert this update.

@@ -256,15 +254,15 @@ private OutgoingResponse createOutgoingResponseCore(Throwable exc) {
} else if (exc instanceof UnknownLocalException ex) {
exceptionId = ex.ice_id();
replyStatus = ReplyStatus.UnknownLocalException;
unknownExceptionMessage = ex.unknown;
unknownExceptionMessage = ex.toString();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct. The message of an UnknownXxxException is returned by getMessage, not toString.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also fixed.

@@ -285,13 +283,17 @@ private OutgoingResponse createOutgoingResponseCore(Throwable exc) {
|| replyStatus == ReplyStatus.UnknownException)) {
ostr.writeByte(replyStatus.value());
if (unknownExceptionMessage == null) {
unknownExceptionMessage = "Dispatch failed with " + exceptionId + ": " + exc.getMessage();
unknownExceptionMessage = "Dispatch failed with " + exc.toString();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct.

if (rfe.id.name.isEmpty()) {
rfe.id = id;
rfe.facet = facet;
Identity id = rfe.id;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find defining local variables that hide fields pretty confusing and unexpected, especially in a big method like this one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to changing it, but this is what we're doing in every language, so I'd like to change it in all of them.
See #2345

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other languages, this code is not in Current, but in a separate class. So id/facet/operation don't hide fields.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, I added a prefix in Java to disambiguate them.

@@ -5,7 +5,7 @@
/** This exception indicates socket errors. */
public class SocketException extends SyscallException {
public SocketException() {
super();
super((String) null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference between super() and super((String)null)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameterless constructor was removed from SyscallException, and Java doesn't support default parameters, so here we explicitly pass null to say that we don't have any useful message.

But SyscallException has 2 constructors which only take 1 parameter:
SyscallException(Throwable cause) and SyscallException(String message)
so passing null is ambiguous, so we have to do this awkward looking cast to let the compiler know which constructor we want to call.

@externl externl removed their request for review August 7, 2024 14:23
@bernardnormier bernardnormier self-requested a review August 7, 2024 15:47
@InsertCreativityHere
Copy link
Member Author

@bernardnormier

We should definitely remove Throwable from all UnknownException constructors and fix any code that use a UnknownException Throwable constructor.

I removed it from UnknownUserException and UnknownLocalException, but I'm going to do the remainder in a separate PR.
The Java mapping wraps all kinds of (seemingly) random exceptions in UnknownException, and untangling those feels unrelated to consolidating the LocalExceptions themselves.

if (rfe.operation.isEmpty()) {
rfe.operation = operation;
}
String operation = rfe.operation.isEmpty() ? this.operation : rfe.operation;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

operation also shadows a field

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@InsertCreativityHere InsertCreativityHere merged commit b1277ef into zeroc-ice:main Aug 7, 2024
19 checks passed
InsertCreativityHere added a commit to InsertCreativityHere/compiler-comparison that referenced this pull request Jan 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants