What's new in Apache ActiveMQ 5.16.2 ?

Apache ActiveMQ 5.15.15 and 5.16.2 has been released.

5.15.15 is the last planned one on the 5.15.x branch, and contains only bug fixes. If you use ActiveMQ 5.15.x, you should upgrade to 5.16.x.

Now, we are focusing on 5.16.x and coming 5.17.x (see later in this blog).

ActiveMQ 5.16.2 brings important fixes and improvements. Let's take a quick tour ;)

Fix on failover priorityBackup

When you have brokers located on different networks, failver priortyBackup allows you to specify a preference to "local" broker.

For instance, you can use a broker URL like this:


failover:(tcp://local:61616,tcp://remote:61616)?randomize=false&priorityBackup=true

With this URL, client will try to connect to tcp://local:61616 and stay connected there. The client will connect to remote only if local is not there. However, client will constantly try to reconnect to local. Once the client can do it (when local is back), he will automatically reconnect.

By default, the first URI in the list is considered as local. If you have several local brokers you want to prioritize, then you can use priorityURIs:


failover:(tcp://local1:61616,tcp://local2:61616,tcp://remote:61616)?randomize=false&priorityBackup=true&priorityURIs=tcp://local1:61616,tcp://local2:61616

Unfortunately, we introduced a regression on priorityBackup where a bunch of connections was open, heading broker to be out of resources.

We fixed that in ActiveMQ 5.15.15 and 5.16.2, so, you can use priorityBackup without problem now.

Improvements on the HTTP transport connector

We did couple of improvements on the HTTP transport connector.

First, for security reason, we now hide the embedded Jetty version.

You can use a HTTP related transport connector (http, http, ws, ...) in your activemq.xml:


...
  <transportConnector name="http" uri="http://0.0.0.0:8080"/>
...

If we do a port scan on our broker, you can see:

#nmap -sV -p8080 localhost
Starting Nmap 7.70 ( https://nmap.org ) at 2018-04-23 18:16 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000098s latency).

PORT STATE SERVICE VERSION
8080/tcp open http Jetty 9.2.22.v20170606

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.34 seconds

We can see that we can know the Jetty version used by ActiveMQ. This information should not be displated as it can maliciously used to exploit a Jetty security issue.

So, for security reason, starting from ActiveMQ 5.15.15 and 5.16.2, the Jetty version is not provided anymore on client side.

We also improved the "packaging" of the ActiveMQ HTTP artifact.

Both ActiveMQ HTTP and ActiveMQ STOMP uses XStream to marshal/unmarshal messages. To avoid code duplication, XStream code has been put into ActiveMQ STOMP, and so ActiveMQ HTTP depends to STOMP. It was not very elegant, as HTTP depends to the whole STOMP artifact just to XStream.

We improved this by moving XStream code directy at ActiveMQ client level, used by both HTTP and STOMP connectors.

JDK 9+/16 improvements (support JDK16, fix on the ConfigurationRuntimePlugin)

One of the purpose of ActiveMQ 5.16.x is to support JDK 9+.

If the runtime works fine with JDK9+ since 5.16.0, we identified an issue with the RuntimeConfigurationPlugin.

The RuntimeConfigurationPlugin is a plugin that "control" ActiveMQ broker startup, and is able to detect changes in the configuration (in activemq.xml) to automatically restart the broker to take configuration changes.

To use the configuration plugin, you have to disable autostart of the broker (the broker is actually started/controller by the runtime configuration plugin) and add the plugin:


<broker xmlns="http://activemq.apache.org/schema/core" start="false" ... >
    ...
    <plugins>
      <runtimeConfigurationPlugin checkPeriod="1000" />
    </plugins>
    ...
</broker>

The configuration plugin is checking configuration changes on the network connector, destination policies, authorization plugin, destination interceptors.

The checkPeriod is the time (in milliseconds) between checks for changes. If checkPeriod is set to 0, there is not automatic check, but you can trigger a manual check via JMX.

The runtime configuration plugin actually uses JAXB and STaX behind the hood to parse the configuration XML and detect changes.

As JDK9+ doesn't provide JAXB anymore out of the box, we need JAXB (and couple of other dependencies) in the ActiveMQ lib in order for the runtime configuration plugin to work.

With ActiveMQ 5.16.1, it was up to the user to "manually" add these dependencies in the ActiveMQ lib folder.

For convenience, ActiveMQ 5.16.2 embeds the required dependencies out of the box.

Fix broker redelivery plugin

A message is redelivery to a client if:
  • A transacted session is used and rollback() is called.
  • A transacted session is closed before commit() is called.
  • A session is using CLIENT_ACKNOWLEDGE and Session.recover() is called.
  • A client connection times out (perhaps the code being executed takes longer than the configured time-out period).
By default, the maximum redelivery is 6. When the message reaches the maximum redelivery, then the message is sent to DLQ.

The redelivery can be configured on the client connection factory, or on the broker configuration.

For instance, on the broker side, you can use the redelivery plugin:


<broker ... schedulerSupport="true">
        ...
        <plugins>
            <edeliveryPlugin fallbackToDeadLetter="true" 
                              sendToDlqIfMaxRetriesExceeded="true">
                <redeliveryPolicyMap>
                    <redeliveryPolicyMap>
                        >redeliveryPolicyEntries>
                            <!-- a destination specific policy -->
                            <redeliveryPolicy queue="MyQueue" 
                                              maximumRedeliveries="4" 
                                              redeliveryDelay="10000"/>
                        </redeliveryPolicyEntries>
                        
                        <defaultEntry>
                            <!-- the fallback policy for all other destinations -->
                            <redeliveryPolicy maximumRedeliveries="4" 
                                              initialRedeliveryDelay="5000"
                                              redeliveryDelay="10000"/>
                        </defaultEntry>
                    </redeliveryPolicyMap>
                </redeliveryPolicyMap>
            </redeliveryPlugin>
        </plugins>
        ...
</broker>

You can see that, internally, ActiveMQ uses a scheduler (schedulerSupport="true") to deal with message redelivery.

Unfortunately, if redelivery works fine with ActiveMQ 5.15.x, a regression has been introduced in ActiveMQ 5.16.0 and 5.16.1, causing the redelivery doesn't work anymore.

Actually, the message to be redelivered are deleted from the scheduler whereas they should be redelivered:


RedeliveryPlugin  175 | 40 - org.apache.activemq.activemq-osgi - 5.16.1 | redelivery #1 of: ID:mlipc2-4159-1611768583683-1:15:1:1:41 with delay: 1000, dest: queue://TEST2.msgin
ActiveMQMessageConsumer 1485 | 40 - org.apache.activemq.activemq-osgi - 5.16.1 | ID:mlipc2-4159-1611768583683-1:16:1:1 suppressing duplicate delivery on connection, poison acking: MessageDispatch {commandId = 0, responseRequired = false, consumerId = ID:mlipc2-4159-1611768583683-1:16:1:1, destination = queue://TEST2.msgin, message = ActiveMQTextMessage {commandId = 125, responseRequired = true, messageId = ID:mlipc2-4159-1611768583683-1:15:1:1:41, originalDestination = null, originalTransactionId = null, producerId = ID:mlipc2-4159-1611768583683-1:15:1:1, destination = queue://TEST2.msgin, transactionId = null, expiration = 0, timestamp = 1611768605501, arrival = 0, brokerInTime = 1611768607001, brokerOutTime = 1611768607012, correlationId = null, replyTo = null, persistent = true, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@5f105a66, marshalledProperties = org.apache.activemq.util.ByteSequence@5b2fd55c, dataStructure = null, redeliveryCounter = 1, size = 0, properties = {redeliveryDelay=1000, scheduledJobId=ID:mlipc2-4159-1611768583683-1:15:1:1:2}, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false, text = XXX}, redeliveryCounter = 1}

This has been fixed on ActiveMQ 5.16.2, and you can now use redelivery plugin without problem.

Apache Karaf features improvements

Several improvements have been done on the ActiveMQ Karaf features repository XML. I plan to complete update of the Karaf part for ActiveMQ 5.17.0, but 5.16.2 already brings good improvements.

First, the repository tag mentioning spring-legacy (providing Spring 4.x features required by ActiveMQ) is not "hard coded" anymore. The big advantage is to work with any Karaf versions, and avoid to load bunch of Spring features.

The only thing to remember is to add the spring-legacy repository before installing ActiveMQ features:


karaf@root()> feature:repo-add spring-legacy
karaf@root()> feature:repo-add activemq 5.16.2
karaf@root()> feature:install activemq...

Another improvement on ActiveMQ 5.16.2 is to avoid to install ActiveMQ Karaf shell commands by default. This can cause a refresh on other shell commands, and it should be optional for users. So, ActiveMQ 5.16.2 introduced a new activemq-shell feature if you really need the activemq:* shell commands:

karaf@root()> feature:install activemq-shell

Thinking about Apache ActiveMQ 5.16.3 and 5.17.0

Now, I can focus on ActiveMQ 5.16.3 and 5.17.0.

ActiveMQ 5.16.3 will be a maintenance release: so, not big changes, but more backward compatible improvements and fixes.

On the other hand, ActiveMQ 5.17.0 will bring important changes that I already started:

  • Upgrade to Spring 5, as Spring 4 is EoL. I'm evaluating removing Spring dependency in the future (to use more SPI like model), but it will be after 5.17.x anyway.
  • Upgrade to Log4j2, as we are still using Log4j1.
  • Introduce replicated kahadb PoC using Bookkeeper and other cloud friendly features.
  • JMS 2.x upgrade.
  • More modular and lightweight code organization.

For sure, don't expect ActiveMQ 5.17.0 very soon, but I'm moving forward smoothly (balancing my time with other Apache projects ;)).

Stay tuned !

Comments

Popular posts from this blog

Quarkus and "meta" extension

Getting started with Apache Karaf Minho

Apache Karaf Minho and OpenTelemetry