1

My use case warrants the use of a publish-subscribe model, so I'm using topics that are defined in my Spring Boot client. I've used the tool MQTT.fx and two Spring Boot clients to test things. The two Spring Boot clients are able to communicate with each other, but the MQTT.fx client only connects to the broker and does not produce or consume messages. The two Spring Boot clients both connect to port 61616, and the MQTT.fx client connects to port 1883.

For my project, I need to get the MQTT.fx client working as it is highly representative of the microcontroller that is intended to work with the server. Failure on MQTT.fx is failure on the microcontroller.

The acceptor configuration in my broker.xml file is as show below.

<acceptors>
     <!-- Acceptor for every supported protocol -->
     <acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;amqpMinLargeMessageSize=102400;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpDuplicateDetection=true;supportAdvisory=false;suppressInternalManagementObjects=false</acceptor>

     <!-- AMQP Acceptor.  Listens on default AMQP port for AMQP traffic.-->
     <acceptor name="amqp">tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpMinLargeMessageSize=102400;amqpDuplicateDetection=true</acceptor>

     <!-- STOMP Acceptor. -->
     <acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true</acceptor>

     <!-- HornetQ Compatibility Acceptor.  Enables HornetQ Core and STOMP for legacy HornetQ clients. -->
     <acceptor name="hornetq">tcp://0.0.0.0:5445?anycastPrefix=jms.queue.;multicastPrefix=jms.topic.;protocols=HORNETQ,STOMP;useEpoll=true</acceptor>

     <!-- MQTT Acceptor -->
     <acceptor name="mqtt">tcp://0.0.0.0:1883?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=MQTT;useEpoll=true</acceptor>
</acceptors>

The logs when the Spring Boot clients communicate are as below. First, a message is sent to the topic server.weatherForecast, and consequently, after some processing, a response is sent to AMEBAA000105.device.weatherForecast.

2021-10-04 14:14:04,860 [AUDIT](Thread-8 (activemq-netty-threads)) 

AMQ601715: User admin(admins)@127.0.0.1:1125 successfully authenticated
2021-10-04 14:14:04,860 [AUDIT](Thread-8 (activemq-netty-threads)) AMQ601267: User admin(admins)@127.0.0.1:1125 is creating a core session on target resource ActiveMQServerImpl::name=0.0.0.0 [with parameters: [3b141c41-24ef-11ec-aa52-00155d831300, null, ****, 102400, RemotingConnectionImpl [ID=6280c69f, clientID=null, nodeID=b719c384-1d0a-11ec-8b7c-00155d831300, transportConnection=org.apache.activemq.artemis.core.remoting.impl.netty.NettyServerConnection@417b6fef[ID=6280c69f, local= /127.0.0.1:61616, remote=/127.0.0.1:1125]], true, true, false, false, null, org.apache.activemq.artemis.core.protocol.core.impl.CoreSessionCallback@103d417f, true, OperationContextImpl [61828916] [minimalStore=9223372036854775807, storeLineUp=0, stored=0, minimalReplicated=9223372036854775807, replicationLineUp=0, replicated=0, paged=0, minimalPage=9223372036854775807, pageLineUp=0, errorCode=-1, errorMessage=null, executorsPending=0, executor=OrderedExecutor(tasks=[])], {}]]
2021-10-04 14:14:04,864 [AUDIT](Thread-7 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$6@b62d79)) AMQ601500: User admin(admins)@127.0.0.1:1125 is sending a message CoreMessage[messageID=528267,durable=true,userID=3b146a62-24ef-11ec-aa52-00155d831300,priority=4, timestamp=Mon Oct 04 14:14:04 IST 2021,expiration=0, durable=true, address=jms.topic.server.weatherForecast,size=314,properties=TypedProperties[__AMQ_CID=3b13ce1f-24ef-11ec-aa52-00155d831300]]@1994364957, with Context: RoutingContextImpl(Address=null, routingType=null, PreviousAddress=null previousRoute:null, reusable=null, version=0)
..................................................

2021-10-04 14:14:04,865 [AUDIT](Thread-7 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$6@b62d79)) AMQ601501: User admin(admins)@127.0.0.1:1110 is consuming a message from 41207748-6ed3-42d2-b75e-044805212686: Reference[528267]:RELIABLE:CoreMessage[messageID=528267,durable=true,userID=3b146a62-24ef-11ec-aa52-00155d831300,priority=4, timestamp=Mon Oct 04 14:14:04 IST 2021,expiration=0, durable=true, address=jms.topic.server.weatherForecast,size=314,properties=TypedProperties[__AMQ_CID=3b13ce1f-24ef-11ec-aa52-00155d831300]]@1994364957
2021-10-04 14:14:04,868 [AUDIT](Thread-4 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$6@b62d79)) AMQ601502: User admin(admins)@127.0.0.1:1110 is acknowledging a message from 41207748-6ed3-42d2-b75e-044805212686: CoreMessage[messageID=528267,durable=true,userID=3b146a62-24ef-11ec-aa52-00155d831300,priority=4, timestamp=Mon Oct 04 14:14:04 IST 2021,expiration=0, durable=true, address=jms.topic.server.weatherForecast,size=314,properties=TypedProperties[__AMQ_CID=3b13ce1f-24ef-11ec-aa52-00155d831300]]@1994364957
2021-10-04 14:14:08,059 [AUDIT](Thread-8 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$6@b62d79)) AMQ601500: User admin(admins)@127.0.0.1:1110 is sending a message CoreMessage[messageID=528349,durable=true,userID=3cfc1623-24ef-11ec-aa52-00155d831300,priority=4, timestamp=Mon Oct 04 14:14:08 IST 2021,expiration=0, durable=true, address=null,size=190,properties=TypedProperties[__AMQ_CID=d04d0e87-24ee-11ec-aa52-00155d831300]]@600964226, with Context: RoutingContextImpl(Address=jms.topic.AMEBAA000105.device.weatherForecast, routingType=null, PreviousAddress=jms.topic.AMEBAA000105.device.weatherForecast previousRoute:null, reusable=null, version=0)
..................................................

The logs when using MQTT.fx are as below. Initially AMEBAA000105.device.weatherForecast is subscribed to, and then a message is sent to server.weatherForecast. The Spring Boot client meant to receive these messages does not receive anything, and consequently does not send anything to AMEBAA000105.device.weatherForecast. When the publication of a message to AMEBAA000105.device.weatherForecast from the Spring Boot client is triggered by another Spring Boot client, MQTT.fx does not capture the message.

2021-10-04 14:24:35,443 [AUDIT](Thread-17 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$6@b62d79)) AMQ601265: User admin(admins)@192.168.0.107:18640 is creating a core consumer on target resource ServerSessionImpl() [with parameters: [534062, MQTT_FX_Client.AMEBAA000105.device.weatherForecast, null, 0, false, false, -1]]
2021-10-04 14:24:43,719 [AUDIT](Thread-10 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$6@b62d79)) AMQ601500: User admin(admins)@192.168.0.107:18640 is sending a message CoreMessage[messageID=534380,durable=false,userID=null,priority=0, timestamp=0,expiration=0, durable=false, address=server.weatherForecast,size=200,properties=TypedProperties[mqtt.message.retain=false,mqtt.qos.level=0]]@1214406991, with Context: RoutingContextImpl(Address=server.weatherForecast, routingType=null, PreviousAddress=null previousRoute:null, reusable=null, version=0)

The above logs are the audit logs. In the artemis.log file, MQTT.fx keeps pinging the broker.

2021-10-04 14:30:43,727 TRACE [org.apache.activemq.artemis.core.protocol.mqtt] MQTT(MQTT_FX_Client): OUT >> PINGRESP
2021-10-04 14:31:43,728 TRACE [org.apache.activemq.artemis.core.protocol.mqtt] MQTT(MQTT_FX_Client): OUT >> PINGRESP
2021-10-04 14:32:43,729 TRACE [org.apache.activemq.artemis.core.protocol.mqtt] MQTT(MQTT_FX_Client): OUT >> PINGRESP
2021-10-04 14:33:43,731 TRACE [org.apache.activemq.artemis.core.protocol.mqtt] MQTT(MQTT_FX_Client): OUT >> PINGRESP
2021-10-04 14:34:43,732 TRACE [org.apache.activemq.artemis.core.protocol.mqtt] MQTT(MQTT_FX_Client): OUT >> PINGRESP
2021-10-04 14:35:43,733 TRACE [org.apache.activemq.artemis.core.protocol.mqtt] MQTT(MQTT_FX_Client): OUT >> PINGRESP

Logs when subscribing or publishing from MQTT.fx in the artemis.log file are as below

2021-10-04 14:22:27,702 TRACE [org.apache.activemq.artemis.core.protocol.mqtt] MQTT(MQTT_FX_Client): IN << SUBSCRIBE(3)
AMEBAA000105.device.weatherForecast : AT_MOST_ONCE
2021-10-04 14:24:43,718 TRACE [org.apache.activemq.artemis.core.protocol.mqtt] MQTT(MQTT_FX_Client): IN << PUBLISH(-1) topic=server.weatherForecast, qos=AT_MOST_ONCE, retain=false, dup=false, payload={"serialNumber" : "AMEBAA000105"}

Any help is much appreciated.

Justin Bertram
  • 29,372
  • 4
  • 21
  • 43
  • Hi Justin, this application is meant to connect to a microcontroller that transmits data in a char[]. The consumer in my post is a part of some existing code and since it accepts a char[], I coded the test producer to send a char[] to the consumer. However, I've tried the same with a String instead of char[] to no avail. – ShreyasJavahar Sep 30 '21 at 06:26
  • @JustinBertram I've edited my question. Please do let me know if there's anything else I can provide that would help. – ShreyasJavahar Oct 01 '21 at 08:06
  • @JustinBertram I've cleaned up the post and included the spring boot client and MQTT.fx client logs. – ShreyasJavahar Oct 04 '21 at 09:18

2 Answers2

1

You say that when you're testing the Spring Boot clients you send a message to server.weatherForecast and the after some processing a response is sent to AMEBAA000105.device.weatherForecast. However, that is not what the logs show. The logs indicate that you send a message to jms.topic.server.weatherForecast and jms.topic.AMEBAA000105.device.weatherForecast respectively. Notice the jms.topic. prefix.

I believe this is the root of your problem because according to the logs the MQTT actually will use server.weatherForecast and AMEBAA000105.device.weatherForecast. Since the two clients aren't using matching names then they can never work together with your current configuration.

My guess is that you're using a legacy Artemis 1.x client from your Spring Boot applications and that is why the jms.topic. prefix is being used. You should either move to a newer client (e.g. one that matches the broker version you're using) or configure the anycastPrefix and multicastPrefix to support the legacy 1.x client. The default broker.xml has a comment which explains how to do this:

<!-- Note: If an acceptor needs to be compatible with HornetQ and/or Artemis 1.x clients add
           "anycastPrefix=jms.queue.;multicastPrefix=jms.topic." to the acceptor url.
           See https://issues.apache.org/jira/browse/ARTEMIS-1644 for more information. -->

This comment appears in the acceptors block by default, but it looks like you removed it since it's not in the XML you pasted.

If you want to confirm which library the client is using the simplest way to to find out is simply to inspect the client's environment. However, if that doesn't work and you have access to the broker logs then you can enable TRACE logging for org.apache.activemq.artemis.core.protocol.core.impl.RemotingConnectionImpl and then look at the version passed in the CreateSessionMessage. If it's < 131 then it's not a 2.18.0 client.

Justin Bertram
  • 29,372
  • 4
  • 21
  • 43
  • I did notice the prefix in the logs, I'm using Artemis 2.18.0 and the spring boot starter Artemis dependency version is 2.5.5 (the latest one). Subscribing to jms.topic.topicName on MQTT.fx did do the trick; messages are being sent there, but any idea why the prefix is still being added? I even tried explicitly setting the multicastPrefix to "nothing" in the acceptor included in the next comment, but to no avail. Not sure if that's the right way to go about it. How do I get rid of the prefix? – ShreyasJavahar Oct 05 '21 at 03:45
  • tcp://0.0.0.0:61616?multicastPrefix=;tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;amqpMinLargeMessageSize=102400;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpDuplicateDetection=true;supportAdvisory=false;suppressInternalManagementObjects=false – ShreyasJavahar Oct 05 '21 at 03:47
  • The prefixed used is determined by the client. You can't change the client's prefix by changing the broker's configuration. However, if change the `acceptor` configuration as I recommended it will *strip* the prefix from the Spring Boot JMS client and both clients can use `server.weatherForecast` and `AMEBAA000105.device.weatherForecast`. The `multicastPrefix` and `anycastPrefix` are empty by default so your change had no real impact. I wonder if perhaps you're building with 2.5.5 and then using 1.x at runtime. The 2.5.5 client shouldn't use any prefix. – Justin Bertram Oct 05 '21 at 13:28
  • I did change the acceptor as you outlined, but the prefix is still being added. Pardon me if this is a silly question, but how do I check what version is being used at runtime? Couldn't find anything about that in the audit logs. Does the spring-boot-starter-parent version have any bearing on this? I'm using 1.4.1, an old version, I'm aware, but migrating up isn't my decision to make currently. – ShreyasJavahar Oct 06 '21 at 04:58
  • What exactly do you mean by, "the prefix is still being added"? – Justin Bertram Oct 06 '21 at 16:35
  • I updated my answer to address your question about determining the client's version. – Justin Bertram Oct 06 '21 at 16:50
  • I meant that the "jms.topic." prefix was still being added to the topic name I defined. I enabled TRACE logging for the RemotingConnectionImpl and saw that in the `CreateSessionResponseMessage`, the `serverVersion` attribute was 131, and in the `CreateSessionMessage`, the `version` attribute was 127. Could you please help me understand why this is happening and how to ensure a lower version isn't used by the client at runtime? Please do let me know if you need any further information about my configuration. – ShreyasJavahar Oct 07 '21 at 07:18
  • Protocol version `127` was only used by ActiveMQ Artemis 1.3.0 which was released in June of 2016 so it's quite old now. Clearly your application is using the 1.3.0 client. I can't tell you how or why it's doing this as I don't know anything about it. That's really up to you to determine since you're building and running it. – Justin Bertram Oct 07 '21 at 15:01
  • Regardless of the client version, the `anycastPrefix=jms.queue.;multicastPrefix=jms.topic.` on the `acceptor` should deal with the prefixes. When you say, 'the "jms.topic." prefix was still being added to the topic name I defined,' where *exactly* are you seeing the prefix added? It's normal to still see the prefix in some of the logging, but ultimately the prefix should be stripped and the client should use an address without the prefix. Can you confirm that you've configured the `acceptor` correctly and that the client is using that `acceptor`? – Justin Bertram Oct 07 '21 at 15:04
  • The relevant acceptor in my broker.xml looks like this `tcp://0.0.0.0:61617?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;anycastPrefix=jms.queue;multicastPrefix=jms.topic.;sslEnabled=true;keyStorePath=E:/path;keyStorePassword=changeit;trustStorePath=E:/path;trustStorePassword=changeit;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE` – ShreyasJavahar Oct 07 '21 at 15:34
  • The connection factory is configured as `ActiveMQConnectionFactory artemisConnectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61617?&" + "sslEnabled=true&" + "trustStorePath=" + pathToTrustStore + "&trustStorePassword=changeit&anycastPrefix=jms.queue&multicastPrefix=jms.topic.");` – ShreyasJavahar Oct 07 '21 at 15:35
  • I see the `jms.topic.` prefix for one, in the logs, secondly, I subscribe to the topics `AMEBAA000105.device.weatherForecast` and `jms.topic.AMEBAA000105.device.weatherForecast` on the MQTT.fx client and when a message is published from the spring boot client that uses the connection factory setup in my previous comment, the message is received only on the latter topic. The spring boot client publishes to the former topic, but the message is received only on the latter due to the prefix. – ShreyasJavahar Oct 07 '21 at 15:39
  • For what it's worth, you don't need to configure the `anycastPrefix` and `multicastPrefix` on your `ConnectionFactory` URL. Those parameters are only relevant for an `acceptor` in `broker.xml`. – Justin Bertram Oct 07 '21 at 18:16
  • As to why the `jms.topic.` prefix is not being stripped as expected I can't say for sure. There are multiple tests in the test-suite which verify this functionality before release and those were (and still are) all passing for 2.18.0. There must be some other factor involved that is not clear. I think a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) would be required to investigate further. – Justin Bertram Oct 07 '21 at 18:16
  • Hi @JustinBertram, I've asked a question pertaining to this specific issue [here](https://stackoverflow.com/questions/69551967/activemq-artemis-prefixes-jms-topic-to-all-topic-names-defined-on-spring-boot). – ShreyasJavahar Oct 13 '21 at 08:26
0

Changing the signature of consumeWeatherForecastRequest method to private void consumeWeatherForecastRequest(String incomingMessage) should fix your issue.

  • Thanks for your response Domenico, using String didn't do the trick. I've edited my post to include port information and the acceptor configuration on my broker. Please do let me know if you've got any other solutions. – ShreyasJavahar Sep 30 '21 at 06:32