Using Datomic With Immutant

Immutant 2.x is just a set of libraries, usable from a standard Clojure application. The Datomic peer client is also a library, so in theory we can use Immutant and Datomic together in the same application. But in pratice, it's not that simple.

The sticking point is HornetQ - Datomic uses HornetQ to connect peers to the transactor and depends on HornetQ 2.3.x, while Immutant depends on 2.4.x. We should be able to resolve this with the proper dependency exclusions - the API that Datomic uses in 2.3.x is available in 2.4.x, but there are two issues that prevent that from working with the current stable release of Immutant (2.0.2):

  1. Immutant 2.0.x uses the JMS 2.0 API, which didn't appear in HornetQ until 2.4.0, so 2.4.x is required.
  2. The Datomic transactor is running HornetQ 2.3.x, and a 2.4.x client can't connect to a 2.3.x server, so 2.3.x is required.

Hence our pickle.

But, all is not lost - with Immutant 2.0.x, you have two (non-awesome) options for using Datomic, and if you are willing to use recent Immutant incremental builds (and are willing to upgrade to Immutant 2.1.0 when it is released in a few weeks), you have a third, more palatable option.

Option 1 - No Immutant Messaging

The first option for using Datomic with Immutant 2.0.x is to not use Immutant messaging. This requires either depending individually on the Immutant libraries you are using:

  :dependencies [[com.datomic/datomic-pro "0.9.5206"]
                 [org.immutant/web "2.0.2"]
                 [org.immutant/scheduling "2.0.2"]
                 ...]

or using the catch-all artifact, and excluding messaging:

  :dependencies [[com.datomic/datomic-pro "0.9.5206"]
                 [org.immutant/immutant "2.0.2"
                  :exclusions [org.immutant/messaging]]
                 ...]

But this means you can't use any of the Immutant messaging features, which isn't great.

Option 2 - In WildFly Only

An Immutant application deployed to a WildFly application server doesn't directly use any on the HornetQ APIs, and instead uses the JMS API to communicate with the HornetQ provided by WildFly. That HornetQ is ClassLoader-isolated, which means your application can bring in its own version of HornetQ (in this case, 2.3.x via Datomic), which can be used without issue.

But this means you have to do all of your development against an application running inside WildFly, which isn't a great development experience. With our "dev" war, you can still have a REPL-driven process, but it is definitely more painful than out-of-container development.

Option 3 - Use Recent Incrementals, i.e. 2.1.0

For the soon-to-be-released Immutant 2.1.0, we're working on supporting Red Hat JBoss Enterprise Application Platform (which is a mouthful, so we'll just call it EAP). EAP is the commercialized version of Red Hat's open source JBoss Application Server (now known as WildFly), and the current version (6.4.0) is based off an older WildFly that uses HornetQ 2.3.x. We'll cover what EAP support really means in a future blog post - what matters today is that changes we've made in Immutant to support EAP allow you to use Immutant messaging with Datomic both in and out of WildFly (and soon EAP).

The only issues with this option is you have to use a recent incremental build of Immutant until we release 2.1.0, and do a few dependency exclusions/inclusions to make Immutant messaging and Datomic play nicely. Luckily, we've figured that out for you! The bare minimum to get things working is:

:dependencies [[org.immutant/immutant "2.x.incremental.602"]
               ;; Datomic transitively brings in HornetQ 2.3.17.Final, which
               ;; overrides the HornetQ 2.4.5.Final from org.immutant/messaging
               [com.datomic/datomic-pro "0.9.5206"]
               ;; org.immutant/messaging requires this, but Datomic doesn't
               ;; bring it in, so we have to depend on it explicitly
               [org.hornetq/hornetq-jms-server "2.3.17.Final"
                :exclusions [org.jboss.jbossts.jts/jbossjts-jacorb]]]

Now that you have it working, you'll probably notice that Leiningen's pedantic report is chock full of warnings. Both Datomic and Immutant have large dependency trees, so conflicts are inevitable. If you want to get rid of those warnings, we've figured that out for you as well:

:dependencies [[org.immutant/immutant "2.x.incremental.602"
                :exclusions [org.hornetq/hornetq-server
                             org.hornetq/hornetq-jms-server
                             org.hornetq/hornetq-journal
                             org.hornetq/hornetq-commons]]
               [com.datomic/datomic-pro "0.9.5206"
                :exclusions [org.slf4j/slf4j-nop
                             joda-time
                             commons-codec
                             org.jboss.logging/jboss-logging]]
               [org.hornetq/hornetq-jms-server "2.3.17.Final"
                :exclusions [org.jboss.spec.javax.transaction/jboss-transaction-api_1.1_spec
                             org.jboss.logging/jboss-logging
                             org.jboss/jboss-transaction-spi
                             org.jgroups/jgroups
                             org.jboss.jbossts.jts/jbossjts-jacorb]]]

Note again that this option currently requires you to run a recent incremental build (#602 or newer), which requires relying on our incremental repo:

:repositories [["Immutant incremental builds" "http://downloads.immutant.org/incremental/"]]

Get In Touch

If you have any questions, issues, or other feedback about Datomic with Immutant, you can always find us on #immutant on freenode or our mailing lists.

Immutant 2.0.2 Patch Release

This patch release resolves issues with Websocket on-close handlers not being fired when close frames aren't actually sent.

What is Immutant?

Immutant is an integrated suite of Clojure libraries backed by Undertow for web, HornetQ for messaging, Infinispan for caching, Quartz for scheduling, and Narayana for transactions. Applications built with Immutant can optionally be deployed to a WildFly cluster for enhanced features. Its fundamental goal is to reduce the inherent incidental complexity in real world applications.

Get In Touch

If you have any questions, issues, or other feedback about Immutant, you can always find us on #immutant on freenode or our mailing lists.

Issues resolved in 2.0.2

  • [IMMUTANT-563] - on-close handler for async channels doesn't fire if server is stopped
  • [IMMUTANT-564] - Websocket on-close handlers not being called when Safari client goes away

Using ActiveMQ Artemis With Immutant

Artemis is a "new" JMS2-compatible message broker based on a merging of the ActiveMQ and HornetQ codebases, and represents the future of both projects.

Immutant is built on an abstraction layer called WunderBoss in order to share much of the implementation with our sibling project, TorqueBox. An additional advantage of this layer is it allows us (in theory) to easily switch out the underlying messaging implementation while keeping the same Clojure API. With the release of Artemis 1.0.0, we've now taken the opportunity to test that theory.

wunderboss-artemis

With only a couple of changes to WunderBoss that allow us to share the bulk of the existing JMS2 implementation between the HornetQ and Artemis adapters and make it easier to exclude the HornetQ dependencies, we're now able to provide wunderboss-artemis. It allows you to use Artemis instead of HornetQ as the message broker in an embedded application (it doesn't yet support Artemis if you are deploying to WildFly).

If you want to give it a try, you just need to depend on a recent incremental build (#585 or newer) and make a few adjustments to your :dependencies:

:dependencies [[org.immutant/messaging "2.x.incremental.585"
                :exclusions [org.projectodd.wunderboss/wunderboss-messaging-hornetq]]
               [org.projectodd.wunderboss/wunderboss-artemis "0.1.0"]]

If you then use messaging and see something like the following in your log output, you're all set!

14:12:44.471 INFO  [org.apache.activemq.artemis.core.server] (main) AMQ221020: Started Acceptor at localhost:5445 for protocols [CORE]
14:12:44.471 INFO  [org.apache.activemq.artemis.core.server] (main) AMQ221007: Server is now live
14:12:44.471 INFO  [org.apache.activemq.artemis.core.server] (main) AMQ221001: Apache ActiveMQ Artemis Message Broker version 1.0.0 [nodeID=2107a7c3-0a1c-11e5-955d-71ef037c4451]

Artemis is brand new - once it matures a bit, we may provide an immutant-artemis lib that would bring in wunderboss-artemis and provide an Artemis management namespace similar to the immutant.messaging.hornetq we currently provide.

As always, if you have any issues or feedback, feel free to get in touch.

An Immutant Plugin For Boot

Boot is an interesting new build tool for Clojure from Alan Dipert and Micha Niskin (if you're not familiar with it, Alan & Micha gave a great intro at Clojure/West).

To support the (probably enormous) set of Immutant 2.x users that use Boot and deploy to WildFly, we've ported the functionality of our lein-immutant plugin to Boot, and have released the cleverly-named boot-immutant.

boot-immutant provides two tasks: immutant-war and immutant-test, which are analogous to the immutant war and immutant test tasks from lein-immutant, respectively.

We consider the current release (0.3.0) beta quality. If you're in the set of users that would find this plugin useful, give it a try and let us know if you run in to any issues, either through the usual channels or by filing an issue.

Immutant 2.0.1 Patch Release

Despite our best efforts, the 2.0.0 release wasn't perfect. This release fixes the imperfections we're currently aware of.

What is Immutant?

Immutant is an integrated suite of Clojure libraries backed by Undertow for web, HornetQ for messaging, Infinispan for caching, Quartz for scheduling, and Narayana for transactions. Applications built with Immutant can optionally be deployed to a WildFly cluster for enhanced features. Its fundamental goal is to reduce the inherent incidental complexity in real world applications.

What's changed in this release?

Mainly the following:

  • Subscribing to remote topics now actually works
  • When running inside WildFly, if your :main doesn't return, we abort the deployment instead of letting it hang the deployer. See the WildFly guide for details.

See below for a full list of changes.

Get In Touch

If you have any questions, issues, or other feedback about Immutant, you can always find us on #immutant on freenode or our mailing lists.

Issues resolved in 2.0.1

  • [IMMUTANT-558] - Clarify that the :main fn must return for deployment to succeed in WildFly
  • [IMMUTANT-559] - Time out the :main calls that block
  • [IMMUTANT-560] - Subscribing to pre-existing topic on remote context throws NPE
  • [IMMUTANT-561] - Concurrent websocket requests can fail under load in-container on slow hardware