This is an automated email from the ASF dual-hosted git repository. havret pushed a commit to branch revert-44-revert-42-AMQNET-848-Failover-Transport-Protocol-Excessive-Reconnection-Attempts-on-Credential-Failure in repository https://gitbox.apache.org/repos/asf/activemq-nms-openwire.git
commit 7d27eb2266d39057255415767ac86200baf153f7 Author: Krzysztof Porebski <h4v...@gmail.com> AuthorDate: Mon Aug 25 23:18:49 2025 +0200 Revert "Revert "AMQNET-848 Failover Transport Protocol Excessive Reconnection…" This reverts commit 720a29c4c63cedb08112aeff0918edfb6df093df. --- src/Transport/Failover/FailoverTransport.cs | 10 ++- src/Transport/InactivityMonitor.cs | 25 +++++-- src/Util/ExceptionFromBrokerError.cs | 78 ++++++++++++++++++++++ test/Transport/Inactivity/InactivityMonitorTest.cs | 47 +++++++++++++ 4 files changed, 151 insertions(+), 9 deletions(-) diff --git a/src/Transport/Failover/FailoverTransport.cs b/src/Transport/Failover/FailoverTransport.cs index ce78cc1..e551116 100644 --- a/src/Transport/Failover/FailoverTransport.cs +++ b/src/Transport/Failover/FailoverTransport.cs @@ -468,9 +468,13 @@ namespace Apache.NMS.ActiveMQ.Transport.Failover { if (CanReconnect()) { - Tracer.WarnFormat("Transport failed to {0}, attempting to automatically reconnect due to: {1}", - ConnectedTransportURI, e.Message); - reconnectOk = true; + //Check to see if the exception is a security exception + if (!(e is NMSSecurityException)) + { + Tracer.WarnFormat("Transport failed to {0}, attempting to automatically reconnect due to: {1}", + ConnectedTransportURI, e.Message); + reconnectOk = true; + } } initialized = false; diff --git a/src/Transport/InactivityMonitor.cs b/src/Transport/InactivityMonitor.cs index 4c672f6..1e2d0f0 100644 --- a/src/Transport/InactivityMonitor.cs +++ b/src/Transport/InactivityMonitor.cs @@ -19,6 +19,7 @@ using System; using System.Threading; using Apache.NMS.ActiveMQ.Commands; using Apache.NMS.ActiveMQ.Threads; +using Apache.NMS.ActiveMQ.Util; using Apache.NMS.ActiveMQ.Util.Synchronization; using Apache.NMS.Util; @@ -230,32 +231,44 @@ namespace Apache.NMS.ActiveMQ.Transport inRead.Value = true; try { - if(command.IsKeepAliveInfo) + if (command is ExceptionResponse) + { + ExceptionResponse error = command as ExceptionResponse; + NMSException exception = ExceptionFromBrokerError.CreateExceptionFromBrokerError(error.Exception); + if (exception is NMSSecurityException) + { + OnException(this, exception); + } + else + { + Tracer.WarnFormat("ExceptionResponse received from the broker:{0}", command.GetType()); + } + }else if (command.IsKeepAliveInfo) { KeepAliveInfo info = command as KeepAliveInfo; - if(info.ResponseRequired) + if (info.ResponseRequired) { try { info.ResponseRequired = false; Oneway(info); } - catch(IOException ex) + catch (IOException ex) { OnException(this, ex); } } } - else if(command.IsWireFormatInfo) + else if (command.IsWireFormatInfo) { - lock(monitor) + lock (monitor) { remoteWireFormatInfo = command as WireFormatInfo; try { StartMonitorThreads(); } - catch(IOException ex) + catch (IOException ex) { OnException(this, ex); } diff --git a/src/Util/ExceptionFromBrokerError.cs b/src/Util/ExceptionFromBrokerError.cs new file mode 100644 index 0000000..006cf80 --- /dev/null +++ b/src/Util/ExceptionFromBrokerError.cs @@ -0,0 +1,78 @@ +using Apache.NMS.ActiveMQ.Commands; +using System; +using System.Reflection; + + +namespace Apache.NMS.ActiveMQ.Util +{ + internal class ExceptionFromBrokerError + { + public static NMSException CreateExceptionFromBrokerError(BrokerError brokerError) + { + String exceptionClassName = brokerError.ExceptionClass; + + if (String.IsNullOrEmpty(exceptionClassName)) + { + return new BrokerException(brokerError); + } + + NMSException exception = null; + String message = brokerError.Message; + + // We only create instances of exceptions from the NMS API + Assembly nmsAssembly = Assembly.GetAssembly(typeof(NMSException)); + + // First try and see if it's one we populated ourselves in which case + // it will have the correct namespace and exception name. + Type exceptionType = nmsAssembly.GetType(exceptionClassName, false, true); + + // Exceptions from the broker don't have the same namespace, so we + // trim that and try using the NMS namespace to see if we can get an + // NMSException based version of the same type. We have to convert + // the JMS prefixed exceptions to NMS also. + if (null == exceptionType) + { + if (exceptionClassName.StartsWith("java.lang.SecurityException")) + { + exceptionClassName = "Apache.NMS.NMSSecurityException"; + } + else if (!exceptionClassName.StartsWith("Apache.NMS")) + { + string transformClassName; + + if (exceptionClassName.Contains(".")) + { + int pos = exceptionClassName.LastIndexOf("."); + transformClassName = exceptionClassName.Substring(pos + 1).Replace("JMS", "NMS"); + } + else + { + transformClassName = exceptionClassName; + } + + exceptionClassName = "Apache.NMS." + transformClassName; + } + + exceptionType = nmsAssembly.GetType(exceptionClassName, false, true); + } + + if (exceptionType != null) + { + object[] args = null; + if (!String.IsNullOrEmpty(message)) + { + args = new object[1]; + args[0] = message; + } + + exception = Activator.CreateInstance(exceptionType, args) as NMSException; + } + else + { + exception = new BrokerException(brokerError); + } + + return exception; + } + } +} diff --git a/test/Transport/Inactivity/InactivityMonitorTest.cs b/test/Transport/Inactivity/InactivityMonitorTest.cs index 78ef3f8..91a20e7 100644 --- a/test/Transport/Inactivity/InactivityMonitorTest.cs +++ b/test/Transport/Inactivity/InactivityMonitorTest.cs @@ -133,6 +133,53 @@ namespace Apache.NMS.ActiveMQ.Test { } } + public class TestableInactivityMonitor : InactivityMonitor + { + public TestableInactivityMonitor(ITransport next) : base(next) { } + + // Expose protected method for testing + public Task TestOnCommand(ITransport sender, Command command) + { + return OnCommand(sender, command); + } + } + [Test] + public void OnCommand_WithNMSSecurityException_ShouldCallOnException() + { + // Arrange + var brokerError = new BrokerError + { + ExceptionClass = "javax.jms.JMSSecurityException", + Message = "Authentication failed" + }; + + var exceptionResponse = new ExceptionResponse + { + Exception = brokerError + }; + + // Mock the static method call - this would require making ExceptionFromBrokerError testable + // For this test, we'll assume it returns an NMSSecurityException + var securityException = new NMSSecurityException("Authentication failed"); + TestableInactivityMonitor monitor = new TestableInactivityMonitor(this.transport); + monitor.Exception += new ExceptionHandler(OnException); + monitor.CommandAsync += new CommandHandlerAsync(OnCommand); + bool exceptionHandlerCalled = false; + Exception caughtException = null; + monitor.Exception += (sender, args) => + { + exceptionHandlerCalled = true; + caughtException = args; + }; + // Act + Task task=monitor.TestOnCommand(transport, exceptionResponse); + task.Wait(); + // Assert + Assert.IsTrue(exceptionHandlerCalled, "Exception handler should have been called"); + Assert.IsNotNull(caughtException, "Exception should have been caught"); + Assert.IsInstanceOf<NMSSecurityException>(caughtException, "Should be NMSSecurityException"); + Assert.AreEqual("Authentication failed", caughtException.Message); + } [Test, Timeout(20_000), Ignore("Flaky test, needs investigation")] public void TestNonFailureSendCase() --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@activemq.apache.org For additional commands, e-mail: commits-h...@activemq.apache.org For further information, visit: https://activemq.apache.org/contact