Immutant 2 (The Deuce) Alpha Released

We're as excited as this little girl to announce our first alpha release of The Deuce, Immutant 2.0.0-alpha1.

This represents a significant milestone for us, as we've completely removed the app server from Immutant. It's just jars now. We've put a lot of thought into the API and performed enough integration testing to feel confident putting an alpha out at this time.

Big, special thanks to all our early adopters who provided invaluable feedback on our incremental releases these past few months.

What is Immutant?

Immutant is an integrated suite of Clojure libraries backed by Undertow for web, HornetQ for messaging, Infinispan for caching, and Quartz for scheduling. 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.

A few highlights of The Deuce compared to the previous 1.x series:

  • It uses the Undertow web server -- it's much faster, with WebSocket support
  • The source is licensed under the Apache Software License rather than LPGL
  • It's completely functional "embedded" in your app, i.e. no app server required
  • It may be deployed to latest WildFly for extra clustering features

How to try it

If you're already familiar with Immutant 1.x, you should take a look at our migration guide. It's our attempt at keeping track of what we changed in the Clojure namespaces.

The tutorials are another good source of information, along with the apidoc.

For a working example, check out our Feature Demo application!

Get It

There is no longer any "installation" step as there was in 1.x. Simply add the relevant dependency to your project as shown on Clojars.

What's next?

For the first release, we focused on the API and on usage outside of a container. For the next alpha, we plan on focusing on making in-container behavior more robust. Take a look at our current issues if you want to follow along.

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.

Immutant 1.1.4 Released

We're as happy as a kid at a basketball game to announce Immutant 1.1.4 - "OneFourMoreTheRoad".

This is strictly a bug fix release and, unless any new bugs are reported against it, possibly our last 1.x release. We are now focusing our efforts on The Deuce. We will make every reasonable effort to fix any bugs reported against 1.x, but we will only be adding features to 2.x. As always, view our road map here.

What is Immutant?

Immutant is an application server for Clojure. It's an integrated platform built on JBoss AS7 that aims to reduce the inherent incidental complexity in real world applications.

What's in this release?

The notable changes in this release are:

  • META-INF/ and WEB-INF/ directories on your resource path are now honored.
  • We've restored the needed bits to allow remote jmx connections.
  • Recent cider-nrepl snapshots require tools.nrepl to be on the classpath at the time the project.clj is resolved, so it's now available.
  • We no longer force tools.logging to use log4j. Note: If you were relying on that behavior, see IMMUTANT-464.

Get It

The simplest way to install or upgrade to 1.1.4 is via our Leiningen plugin:

$ lein immutant install 1.1.4

See our install page for more details. Once you have it installed, take a look at our tutorials.

What's next?

As we said above, we'll be focusing on Immutant 2, with a tentative alpha release in the next few weeks.

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 1.1.4

  • [IMMUTANT-452] - Remote jmx not supported by default distribution
  • [IMMUTANT-453] - Immutant ignores logback config
  • [IMMUTANT-455] - META-INF and WEB-INF in a resource dir should be honored
  • [IMMUTANT-457] - Yet more com.sun packages need to be exposed in the sun.jdk module. This time, it's sound packages.
  • [IMMUTANT-459] - Recent cider-nrepl snapshots cause deployment to fail because it can't find tools.nrepl
  • [IMMUTANT-464] - Don't force tools.logging to use a particular provider

lein-immutant Plugin 1.2.2 Released

We just released version 1.2.2 of our Leiningen plugin. This release contains the following changes:

  • Active profiles are now honored for the immutant test task.
  • The immutant run and immutant server tasks no longer give spurious profile warnings under lein 2.4.2.

For the full list of changes, see the milestone.

Get it

If you're already using lein-immutant you probably already know how to do this, but just in case - to install it, add it to the :plugins list in your :user profile in ~/.lein/profiles.clj:

{:user {:plugins [[lein-immutant "1.2.2"]]}}

Get in touch

If you have any questions, issues, or other feedback, you can always find us on #immutant on freenode or you can file an issue on lein-immutant.

Immutant 1.1.3 Released

We're as happy as a kid with a banana to announce Immutant 1.1.3 - "Already?".

This is strictly a bug fix release and, unless any new bugs are reported against it, possibly our last 1.x release. We are now focusing our efforts on The Deuce. We will make every reasonable effort to fix any bugs reported against 1.x, but we will only be adding features to 2.x. As always, view our road map here.

What is Immutant?

Immutant is an application server for Clojure. It's an integrated platform built on JBoss AS7 that aims to reduce the inherent incidental complexity in real world applications.

What's in this release?

There are only three changes in this release:

  • Files in directories that are created after deployment under `resources/' are now visible on the classpath.
  • The helper classes needed for cider-nrepl to load are now exposed by the appropriate classloader.
  • Applications that depend on org.clojure/tools.logging and any Immutant namespace will now work properly when used outside of the container.

Get It

The simplest way to install or upgrade to 1.1.3 is via our Leiningen plugin:

$ lein immutant install 1.1.3

See our install page for more details. Once you have it installed, take a look at our tutorials.

What's next?

As we said above, we'll be focusing on Immutant 2, with a tentative release season beginning this summer.

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 1.1.3

  • [IMMUTANT-446] - newly-generated cljs files don't get served without a server restart
  • [IMMUTANT-447] - Fix classpath issues with cider-nrepl middleware
  • [IMMUTANT-449] - immutant.logging fails outside of the container if tools.logging is loaded

Messaging with The Deuce

[mailboxes]

In this installment of our series on getting started with Immutant 2, we'll take a detailed look at the API of our library for messaging, and show a few examples of usage.

If you're coming from Immutant 1.x, you may notice that the artifact has been renamed (org.immutant/immutant-messaging is now org.immutant/messaging), and the API has changed a bit. We'll point out the notable API changes as we go.

The API

The messaging API is backed by HornetQ, which is an implementation of JMS. JMS provides two primary destination types: queues and topics. Queues represent point-to-point destinations, and topics publish/subscribe.

To use a destination, we need to get a reference to one via the queue or topic functions, depending on the type required. This will create the destination if it does not already exist. This is a bit different than the 1.x API, which provided a single start function for this, and determined the type of destination based on conventions around the provided name. In 2.x, we've removed those naming conventions.

Once we have a reference to a destination, we can operate on it with the following functions:

  • publish - sends a message to the destination
  • receive - receives a single message from the destination
  • listen - registers a function to be called each time a message arrives at the destination

If the destination is a queue, we can do synchronous messaging (request-response):

  • respond - registers a function that receives each request, and the returned value will be sent back to the requester
  • request - sends a message to the responder

Finally, to deregister listeners, responders, and destinations, we provide a single stop function. This is another difference from 1.x - the unlisten and stop functions have been collapsed to stop.

Some Examples

The following code fragments were tested against 2.x.incremental.133. You should follow the instructions in the getting started post to set up a project using Immutant 2.x, and add [org.immutant/messaging "2.x.incremental.133"] and [cheshire "5.3.1"] to the project dependencies (we'll be encoding some messages as JSON in our examples below, so we'll go ahead and add cheshire while we're at it). Then, fire up a REPL, and require the immutant.messaging namespace to follow along:

(require '[immutant.messaging :refer :all])

First, let's create a queue:

(queue "my-queue")

That will create the queue in the HornetQ broker for us. We'll need a reference to that queue to operate on it. Let's go ahead and store that reference in a var:

(def q (queue "my-queue"))

We can call queue any number of times - if the queue already exists, we're just grabbing a reference to it.

Now, let's register a listener on our queue. Let's just print every message we get:

(def listener (listen q println))

We can publish to that queue, and see that the listener gets called:

(publish q {:hi :there})

You'll notice that we're publishing a map there - we can publish pretty much any data structure as a message. By default, that message will be encoded using edn. We also support other encodings, namely: :clojure, :fressian, :json, and :text. We can choose a different encoding by passing an :encoding option to publish:

(publish q {:hi :there} :encoding :json)

Out of the box, we provide full support for the :clojure, :edn, and :text encodings. If you want to use :fressian or :json, you'll need to add org.clojure/data.fressian or cheshire to your dependencies to enable them, respectively.

We passed our options to publish as keyword arguments, but they can also be passed as a map:

(publish q {:hi :there} {:encoding :json})

This holds true for any of the messaging functions that take options.

We're also passing the destination reference to publish instead of the destination name. That's a departure from 1.x, where you could just pass the destination name. Since we no longer have conventions about how queues and topics should be named, we can no longer determine the type of the destination from the name alone.

We can deregister the listener by either passing it to stop or calling .close on it:

(stop listener)
;; identical to
(.close listener)

Now let's take a look at synchronous messaging. Let's create a new queue for this (you'll want to use a dedicated queue for each responder) and register a responder that just increments the request:

(def sync-q (queue "sync"))

(def responder (respond sync-q inc))

Then, we make a request, which returns a Future that we can dereference:

@(request sync-q 1)

The responder is just a fancy listener, and can be deregistered the same way as a listener.

That's not all...

That was just a brief introduction to the messaging API. There are features we've yet to cover (durable topic subscriptions, connection/session sharing, transactional sessions, remote connections), but it's getting late, so we'll save those for another time.

Try it out!

As always, we'd love to incorporate your feedback. Find us via our community page and join the fun!

Thanks to John Lillis for the image, used under CC BY-NC-ND