Note: now that Immutant 2.1.0 is out, we've published another Datomic post covering using it with 2.1.0 specifically.

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.