Uploaded image for project: 'JBoss Remoting'
  1. JBoss Remoting
  2. JBREM-954

InterruptedException should not be rethrown as CannotConnectionException

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Major
    • Resolution: Done
    • Affects Version/s: 2.2.2.SP4, 2.2.2.SP7
    • Fix Version/s: 2.2.2.SP8
    • Component/s: transport
    • Labels:
      None
    • Workaround:
      Workaround Exists
    • Workaround Description:
      Hide

      Any workaround cannot simply just rely on the client side checking
      the Exception thrown because both UnifiedInvokerHAProxy and
      ClusterChooserInterceptor remove nodes from the cluster family upon
      a CannotConnectException.

      So, there needs to be an Exception laundering phase in between the
      invoker proxy/interceptor and Remoting. In the case of EJB3, this can be
      done adding an interceptor in between ClusterChooserInterceptor and
      InvokeRemoteInterceptor.

      The laundering would involve getting the CannotConnectException and
      checking whether the cause is InterruptedException and if so, rethrow the
      InterruptedException only. Note: if the EJB3 called does not declare
      Exception or InterruptedException in its method signature, the client would
      get a java.lang.reflect.UndeclaredThrowableException wrapping the IE. In
      that case, either make the client cope with UndeclaredThrowableException or
      in the laundering interceptor, wrap the IE with a RuntimeException.

      In the case of EJB2, there's no gap to add an interceptor to do the
      laundering. The logic cannot be put into a different invocation marshaller
      either because it gets called after getting the connection.

      Show
      Any workaround cannot simply just rely on the client side checking the Exception thrown because both UnifiedInvokerHAProxy and ClusterChooserInterceptor remove nodes from the cluster family upon a CannotConnectException. So, there needs to be an Exception laundering phase in between the invoker proxy/interceptor and Remoting. In the case of EJB3, this can be done adding an interceptor in between ClusterChooserInterceptor and InvokeRemoteInterceptor. The laundering would involve getting the CannotConnectException and checking whether the cause is InterruptedException and if so, rethrow the InterruptedException only. Note: if the EJB3 called does not declare Exception or InterruptedException in its method signature, the client would get a java.lang.reflect.UndeclaredThrowableException wrapping the IE. In that case, either make the client cope with UndeclaredThrowableException or in the laundering interceptor, wrap the IE with a RuntimeException. In the case of EJB2, there's no gap to add an interceptor to do the laundering. The logic cannot be put into a different invocation marshaller either because it gets called after getting the connection.
    • Estimated Difficulty:
      Medium

      Description

      Let's say you have a Swing GUI application that calls an EJB remotely and the
      client code is waiting to get entry to client side pool (controlled by clientMaxPoolSize).
      While waiting, the user decides to cancel the operation by interrupting the thread. In
      that case, the Remoting code does not make a difference between an InterruptedException
      and any other Exception:

      MicroSocketClientInvoker.java:

      protected SocketWrapper getConnection(Marshaller marshaller,
      UnMarshaller unmarshaller,
      int timeAllowed)
      throws Exception
      {
      long start = System.currentTimeMillis();
      long timeToWait = (timeAllowed > 0) ? timeAllowed : 30000;
      boolean timedout = !semaphore.attempt(timeToWait);

      Any Exception thrown from getConnection() is treated as a CannotConnectException

      try

      { socketWrapper = getConnection(marshaller, unmarshaller, timeLeft); }

      catch (Exception e)

      { // if (bailOut) // return null; semaphore.release(); if (trace) log.trace(this + " released semaphore: " + semaphore.permits()); throw new CannotConnectException( "Can not get connection to server. Problem establishing " + "socket connection for " + locator, e); }

      The EJB3 layer wraps this in CannotConnectException in a RuntimeException like:

      throw new RuntimeException("cluster invocation failed, last exception was: ", lastException);

      This is misleading on the Remoting side. Semantically, the fact that the thread attempting
      to connect is interrupted shouldn't be translated into a CannotConnectException.

      Please find attached a test case I've created.

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  ron_sigal Ronald Sigal
                  Reporter:
                  galder.zamarreno Galder Zamarreño
                • Votes:
                  1 Vote for this issue
                  Watchers:
                  2 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: