As the title suggests, I'm trying to connect to ActiveMQ running on WildFly 10 from a standalone client. If I use Oracle's SDK, without changing the code or configuration, I'm able to connect, but if, instead, I switch to IBM's SDK, it fails with the following exception:
javax.jms.JMSException: Failed to create session factory
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnectionInternal(ActiveMQConnectionFactory.java:727)
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:233)
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:229)
at pt.sibs.epms.JmsClient.main(JmsClient.java:50)
Caused by: ActiveMQNotConnectedException[errorType=NOT_CONNECTED message=AMQ119007: Cannot connect to server(s). Tried with all available servers.]
at org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl.createSessionFactory(ServerLocatorImpl.java:777)
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnectionInternal(ActiveMQConnectionFactory.java:724)
... 3 more
My question is: Is this something just not possible and I'm wasting my time or is it just a matter of some extra tweaking?
NOTE: Unfortunately, I've to use IBM's SDK, because the client will run on an AIX machine.
After doing some bytecode manipulation, I was able to identify the point of divergence.
Oracle's SDK flow of events:
method start() from org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector
context javax.net.ssl.SSLContext@58c1c010
this.channelClazzclass io.netty.channel.socket.nio.NioSocketChannel
isStarted() true
------------------------------------------------------------------------------------------------------------
method doConnect() from io/netty/bootstrap/Bootstrap
channel.isOpen() true
regFuture.isDone() true
------------------------------------------------------------------------------------------------------------
method createConnection() from org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector
future class io.netty.channel.DefaultChannelPromise
channel class io.netty.channel.socket.nio.NioSocketChannel
channel.isOpen() true
------------------------------------------------------------------------------------------------------------
method openTransportConnection() from org/apache/activemq/artemis/core/client/impl/ClientSessionFactoryImpl
connector.isStarted() true
------------------------------------------------------------------------------------------------------------
Everything's working fine.
IBM's SDK flow of events:
method start() from org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector
context javax.net.ssl.SSLContext@71b0b083
this.channelClazzclass io.netty.channel.socket.nio.NioSocketChannel
isStarted() true
------------------------------------------------------------------------------------------------------------
method doConnect() from io/netty/bootstrap/Bootstrap
channel.isOpen() true
regFuture.isDone() false
------------------------------------------------------------------------------------------------------------
method doClose() from io/netty/channel/socket/nio/NioSocketChannel
------------------------------------------------------------------------------------------------------------
method createConnection() from org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector
future class io.netty.channel.DefaultChannelPromise
channel class io.netty.channel.socket.nio.NioSocketChannel
channel.isOpen() false
mar 10, 2017 7:59:35 AM org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnector createConnection
ERROR: AMQ214016: Failed to create netty connection
java.nio.channels.ClosedChannelException
------------------------------------------------------------------------------------------------------------
method openTransportConnection()from org/apache/activemq/artemis/core/client/impl/ClientSessionFactoryImpl
connector.isStarted() false
------------------------------------------------------------------------------------------------------------
As you can see, createConnection()
fails because the channel isn't open and doClose()
from NioSocketChannel
is being explicitly invoked.
I've changed doClose()
to throw and catch an exception so I could see when it's being invoked:
java.lang.Exception: CLOSE INVOKED
at io.netty.channel.socket.nio.NioSocketChannel.doClose(NioSocketChannel.java:238)
at io.netty.channel.AbstractChannel$AbstractUnsafe.doClose0(AbstractChannel.java:611)
at io.netty.channel.AbstractChannel$AbstractUnsafe.close(AbstractChannel.java:590)
at io.netty.channel.AbstractChannel$AbstractUnsafe.close(AbstractChannel.java:534)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.closeOnRead(AbstractNioByteChannel.java:71)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:158)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
at java.lang.Thread.run(Thread.java:785)
The close operation happens normally, it is not caused by any exceptional event. Is this a bug?
After several days of investigation, I eventually figured out the problem. I noticed that, although the client was using Java 8, TLSv1 was being used for the handshake (no exception was being thrown). I tried to force TLSv1.2 in several ways, but it was only when I found a poorly documented property that I was able to solve the problem:
-Dcom.ibm.jsse2.overrideDefaultTLS=true
The property needs to be set on the client side.