The ClojureWerkz Blog

News and updates about ClojureWerkz projects

Langohr 1.6.0-beta1 Is Released

TL;DR

Langohr is a Clojure RabbitMQ client that embraces AMQP 0.9.1 Model.

1.6.0-beta1 is a development milestone release that includes improvements to automatic connection recovery.

Changes between Langohr 1.5.0 and 1.6.0

Automatic Recovery Improvements

Connections will only be recovered if shutdown was not application-initiated.

Contributed by Steffen Dienst.

Support Update

Langohr now depends on ClojureWerkz Support 0.20.0.

langohr.conversion/BytePayload and langohr.conversion/to-bytes are replaced by clojurewerkz.support.bytes/ByteSource and clojurewerkz.support.bytes/to-byte-array, respectively.

Change Log

Langohr change log is available on GitHub.

Langohr is a ClojureWerkz Project

Langohr is part of the group of libraries known as ClojureWerkz, together with

  • Elastisch, a minimalistic well documented Clojure client for ElasticSearch
  • Cassaforte, a Clojure Cassandra client built around CQL 3.0
  • Monger, a Clojure MongoDB client for a more civilized age
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Langohr, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

Michael on behalf of the ClojureWerkz Team

Elastisch 1.3.0-beta4 Is Released

TL;DR

Elastisch is a battle tested, small but feature rich and well documented Clojure client for ElasticSearch. It supports virtually every Elastic Search feature and has solid documentation.

1.3.0-beta4 is a development milestone release that is compatible with 1.2.0 and includes one bug fix.

Changes between Elastisch 1.3.0-beta3 and 1.3.0-beta4

clj-http Update

clj-http dependency has been upgraded to version 0.7.7.

Date Histogram Fix

Date histogram in the native client now includes :total field.

Contributed by Jim Dunn.

Change log

Elastisch change log is available on GitHub.

Thank You, Contributors

Kudos to Jim Dunn for contributing to this release.

Elastisch is a ClojureWerkz Project

Elastisch is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Meltdown, a Clojure interface to Reactor
  • Quartzite, a powerful scheduling library

and several others. If you like Elastisch, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

Michael on behalf of the ClojureWerkz Team

Introducing Machine Head

Why Messaging Matters for Emerging Languages

Over the last 6-7 years we have been observing how companies adopt emerging technologies. Younger languages such as Clojure may enjoy completely green field projects every now and then, but most of the time, they have to integrate into existing systems.

Back when ClojureWerkz “founders” started adopting Clojure, the very first project we had to develop was Langohr. Langohr is a RabbitMQ client that made it possible for us to build services in Clojure that interoperate with other applications (in Ruby and C). That worked very well and messaging keeps being one of our primary integration strategies.

Today we are happy to announce another project in the same space: Machine Head.

What is Machine Head

Machine Head is a minimalistic Clojure MQTT (v3.1) client built on top of Eclipse Paho.

MQTT is an efficient messaging protocol that was designed for low power devices like sensors. It is quite useful as a general purpose protocol, despite being small in scope.

Machine Head is a project for developers who want to integrate Clojure-based services into a system that involves telemetry devices and would prefer to keep the same protocol across the system. So it’s not a replacement for Langohr but a complimentary library. Indeed, RabbitMQ 3.x supports MQTT so you can use both with it!

Documentation and Examples

To get started with Machine Head, please refer to our Getting Started guide. The rest of the documentation is work in progress.

To give you a taste of what using Machine Head is like, here’s a Hello, World example:

1
2
3
4
5
6
7
8
9
10
11
12
(ns clojurewerkz.machine-head.examples.hello-world
  (:gen-class)
  (:require [clojurewerkz.machine-head.client :as mh]))

(defn -main
  [& args]
  (let [id   (mh/generate-id)
        conn (mh/connect "tcp://127.0.0.1:1883" id)]
    (mh/subscribe conn ["hello"] (fn [^String topic meta ^bytes payload]
                                   (println (String. payload "UTF-8"))
                                   (mh/disconnect conn)))
    (mh/publish conn "hello" "Hello, world")))

Supported Clojure Versions

Machine Head targets Clojure 1.5+, tested against 3 Clojure versions x 2 JDKs on travis-ci.org, and is released under the Eclipse Public License.

Community

To subscribe for announcements of releases, important changes and so on, please follow @ClojureWerkz on Twitter.

License

The source is available on GitHub. We also use GitHub to track issues.

The ClojureWerkz Team

Introducing Propertied

What is Propertied

Propertied is a tiny Clojure library that makes working with Java property lists from Clojure a bit nicer.

It is very small in scope: convert java.util.Properties to and from an immutable map, load and store them to and from .properties files.

Supported Clojure Versions

Propertied targets Clojure 1.4+, tested against 3 Clojure versions x 2 JDKs on travis-ci.org, and is released under the Eclipse Public License.

Documentation and Examples

Propertied makes it easy to convert property lists (java.util.Properties) into Clojure maps and vice versa. Thus working with property lists is generally as straightforward as working with maps.

clojurewerkz.propertied.properties/load-from is a polymorphic function that instantiates a property list from an input (e.g. a map).

clojurewerkz.propertied.properties/properties->map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(require '[clojurewerkz.propertied.properties :as p])

(p/load-from {"a key" "a value"})
;= {"a key" "a value"}
(class (p/load-from {"a key" "a value"}))
;= java.util.Properties
(let [pl (p/load-from {"a key" "a value"})]
  (p/properties->map pl))
;= {"a key" "a value"}

;; loading from files and InputStreams
(require '[clojure.java.io :as io])

(p/load-from (io/resource "resource/on/classpath.properties"))
(p/load-from (io/file "resource/on/classpath.properties"))

;; storing to property files (.properties)
(p/store-to {"name" "Michael" "age" "28"} "/tmp/michael.properties")
(p/store-to {"name" "Michael" "age" "28"} (io/file "/tmp/michael.properties"))
(p/store-to {"name" "Michael" "age" "28"} (java.io.File/createTempFile "michael" ".properties"))

Learn more in the documentation.

Community

To subscribe for announcements of releases, important changes and so on, please follow @ClojureWerkz on Twitter.

License

The source is available on GitHub. We also use GitHub to track issues.

The ClojureWerkz Team

Meltdown 1.0.0-beta2 Is Released

TL;DR

Meltdown is a Clojure interface to Reactor, an asynchronous programming, event passing and stream processing toolkit for the JVM.

1.0.0-beta2 is a development milestone release that updates Reactor to 1.0.0.RC1.

Changes between 1.0.0-beta1 and 1.0.0-beta2

Reactor Update

Reactor is updated to 1.0.0.RC1.

Change log

Meltodwn change log is available on GitHub.

Meltdown is a ClojureWerkz Project

Meltdown is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Elastisch, a Clojure client for ElasticSearch
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Meltdown, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

Michael on behalf of the ClojureWerkz Team

Monger 1.7.0-beta1 Is Released

TL;DR

Monger is an idiomatic Clojure MongoDB driver for a more civilized age. It has batteries included, offers powerful expressive query DSL, strives to support every MongoDB 2.0+ feature and has sane defaults. It also has solid documentation.

1.7.0-beta1 is a completely backwards-compatible (besides dropped Clojure 1.3 support) development milestone that introduces a few minor features and updated dependencies.

Changes between 1.6.0 and 1.7.0-beta1

Fune Tuning Cursor Options

monger.query DSL now provides a way to fine tune database cursor options:

1
2
3
4
5
6
7
(with-collection "products"
  ...
  (options {:notimeout true, :slaveok false}) ;; where keyword matches Bytes/QUERYOPTION_*
  (options [:notimeout :slaveok])
  (options com.mongodb.Bytes/QUERYOPTION_NOTIMEOUT) ;; support Java constants
  (options :notimeout)
  ...

monger.cursor is a new namespace that provides the plumbing for cursor fine tuning but should not be widely used directly.

Joda Time Integration Improvements: LocalDate

LocalDate instance serialization is now supported by Monger Joda Time integration.

Contributed by Timo Sulg.

Clojure 1.3 Is No Longer Supported

Monger now officially supports Clojure 1.4+.

Cheshire Upgrade

Cheshire dependency has been upgraded to 5.2.0

ClojureWerkz Support Upgrade

ClojureWerkz Support dependency has been updated to 0.19.0.

Validateur 1.5.0

Validateur dependency has been upgraded to 1.5.0.

Change Log

Monger change log is available on GitHub.

Thank You, Contributors

Timo Sulg contributed key features in this release.

Monger is a ClojureWerkz Project

Monger is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Cassaforte, a Clojure Cassandra client built around CQL
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • Welle, a Riak client with batteries included
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Monger, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

@michaelklishin on behalf of the ClojureWerkz Team

Elastisch 1.3.0-beta3 Is Released

TL;DR

Elastisch is a battle tested, small but feature rich and well documented Clojure client for ElasticSearch. It supports virtually every Elastic Search feature and has solid documentation.

1.3.0-beta3 is a development milestone release that is compatible with 1.2.0 and comes with one usability improvement and updated ElasticSearch Java client.

Changes between Elastisch 1.3.0-beta2 and 1.3.0-beta3

Fields in Search Hit Results in Native Client

Native client now returns the same value in :fields and :_fields keys in search hits. This makes it both backwards compatible with earlier versions and the format ElasticSearch HTTP API uses.

ElasticSearch Native Client Upgrade

Elastisch now depends on ElasticSearch native client version 0.90.5.

Change log

Elastisch change log is available on GitHub.

Thank You, Contributors

Kudos to konradkonrad for contributing to this release.

Elastisch is a ClojureWerkz Project

Elastisch is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Meltdown, a Clojure interface to Reactor
  • Quartzite, a powerful scheduling library

and several others. If you like Elastisch, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

Michael on behalf of the ClojureWerkz Team

EEP 1.0.0-alpha5 Is Released

EEP (Embeded Event Processing) is a Clojure stream processing library.

1.0.0-alpha5 is a development milestone that introduces several minor API improvements and bug fixes.

Changes between 1.0.0-alpha4 and 1.0.0-alpha5

Fixed a problem with repeated emitter evaluation

build-topology had a bug that caused emitter given in the form of (create) to be re-evaluated each time the topology was updated. The bug does not affect codebases that use a single emitter instance bound to an existing var.

Fixed a problem with add-handler not returining an instance of emitter

Usually an emitter is stored in a var, but if you use a threading macro such as -> to build topologies, add-handler failed because it returned a caching registry. Thew new version returns the emitter, allowing for threading macros to work.

Optional downstreams argument for properly visualising splitters.

Because splitters only receives a function that’s responsible for the routing, it’s impossible for EEP to know where the events are routed after split. You can define a splitter with an array of all possible splits to make data flow visualisation possible.

For exmaple, following splitter will split events to even and odd ones. Along with splitter function, pass an vector of [:even :odd] so that visualiser would catch it.

1
(defsplitter *emitter* :entrypoint (fn [i] (if (even? i) :even :odd)) [:even :odd])

Changes between 1.0.0-alpha3 and 1.0.0-alpha4

Meltdown is updated to 1.0.0-aplha3

Meltown alpha3 is a release with minor API additions.

Fixed problem with RingBuffer dispatcher overflow

RingBuffer operates in it’s own pool, adding notifications blocks RingBuffer’s yielding, therefore notify function block forever.

EEP now has realistic throughput tests that verify that the issue is gone.

Added more options to emitter constructor

It is now possible to pass backing Dispatcher for reactor that’s handling routing for the Emitter and an environment.

Change log

EEP change log is available on GitHub.

EEP is a ClojureWerkz Project

EEP is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Elastisch, a small feature complete Clojure client for ElasticSearch
  • Cassaforte, a Clojure Cassandra client
  • Monger, a Clojure MongoDB client for a more civilized age
  • Titanium, a Clojure graph library
  • Meltdown, a fast message passing library built on top of Reactor
  • Welle, a Riak client with batteries included
  • Quartzite, a powerful scheduling library

and several others. If you like Elastisch, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

Michael on behalf of the ClojureWerkz Team

Meltdown 1.0.0-beta1 Is Released

TL;DR

Meltdown is a Clojure interface to Reactor, an asynchronous programming, event passing and stream processing toolkit for the JVM.

1.0.0-beta1 is a development milestone release that introduces one feature and updates Reactor to 1.0.0.M3.

Changes between 1.0.0-alpha3 and 1.0.0-beta1

Reactor Update

Reactor is updated to 1.0.0.M3.

Added dispatcher option to reactor and stream composition

When creating reactor, it’s now possible to plug in a custom dispatcher or configure an underlying dispatcher in a way that’s most suitable for your application, for example:

1
2
3
4
5
6
7
8
9
10
(ns my-app.core
  (:import [reactor.event.dispatch RingBufferDispatcher]
           [com.lmax.disruptor.dsl ProducerType]
           [com.lmax.disruptor YieldingWaitStrategy]))

;; Creates a RingBuffer Dispatcher, with a custom queue size of 4096
(def reactor (mr/create :dispatcher (RingBufferDispatcher. "dispatcher-name"
                                                            4096
                                                            ProducerType/MULTI
                                                            (YieldingWaitStrategy.))))

Change log

Meltodwn change log is available on GitHub.

Meltdown is a ClojureWerkz Project

Meltdown is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Elastisch, a Clojure client for ElasticSearch
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Elastisch, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

Michael on behalf of the ClojureWerkz Team

How to Write a Useful Change Log for Your Open Source Project

TL;DR

A useful project change log answers three questions:

  • Whether it is critical to update
  • Whether the release is backwards compatible
  • What has changed and why

A change log that covers these three points will help your users adopt new versions faster, even in some of the most conservative corporate environments. It will also make the ops people respect your project more.

Before We Start

Back in April we described some of the things we think make an open source project awesome.

That blog post got a lot of positive responses. Today we will dig a little deeper in one aspect of maintaining a project: writing a good change log.

Before we start, let’s remind a rule of thumb you can use with anything related to open source:

Don’t make your users mad

also known as

Don’t make your users want to break the computer

Bro, Do You Event Change log?

Besides documentation, which often takes a fairly substential amount of effort to write well and edit, a good change log is (in our opinion) the second most important thing that earns you credibility in your users’ eyes.

Unfortunately, the majority of open source projects on GitHub do not have a change log at all.

How To Write a Good Change Log

Before we talk about how to maintain a good change log, let’s define “good”. Good for a change log means informative. What kind of information a user is looking for when she is looking to upgrade? This will vary from person to person, but it likely includes a few things:

  • Is this release critical? Should I upgrade immediately or can it wait?
  • Is this release backwards compatible? Should I expect things to just work?
  • What has changed? Why? How can I use the new stuff?

All of these are very important for ops people, because when stuff breaks, they get woken up late at night. But a good change log is not written with just developers or just ops engineers in mind, it caters to both.

What Ops Care About

Like we’ve mentioned earlier, if an upgrade cases an outage, some people may be woken up at night. If that happens more than once thanks to your project, you can be damn sure that they will push for one of two things:

  • That your project is not upgraded for as long as possible
  • That your project is avoided altogether

As a maintainer, these are some of the worst things that can happen. So mess with ops people at your own risk. It won’t take hours to make them confident about upgrading, though. All you need to do is to make it clear if the release has any breaking changes.

It’s OK for your project to have breaking changes every once in a while. Just make it very clear in the announcement and change log when it happens.

Then mention if it is a critical upgrade or not. Using semantic versioning will help with this (major versions are rarely critical but point releases may fix critical bugs or security issues).

In some cases, a bug that you fix affects a lot of people. That should be well reflected, too. In other cases it affects a tiny minority, people who run a certain OpenBSD version on a rarely used hardware architecture, or a specific patch release of a runtime. In such cases, mentioning that the issue only affects such and such environments is a good idea as it will make everybody else upgrade quicker.

A common case of major breaking changes that primarily concern ops is when you drop support for a particular runtime version. For example, we’ve started phasing our support for Clojure 1.3 for our projects last month. Not mentioning such changes is basically stabbing your users in the back.

Example 1

Langohr 1.5 change log explicitly states that Clojure 1.3 is no longer supported:

Example 2

For Cassaforte 1.0.0-rc4 we decided we really need to move some code around between namespaces. It sucked to break the API at such a late stage but it was still in pre-1.0 days so we decided to do it. We knew Cassaforte already had a few users, so we mentioned the breaking changes in bold in the first line of the change log for that release:

Example 3

We don’t always mention whether everyone should upgrade in change logs for ClojureWerkz projects but I (@michaelklishin) try to do so for my other projects. We also mention this in release announcements.

In any case, if you know what group of users may be affected, mentioning that will earn you bonus points.

Summary

As you can see, it does not take much effort to make it very clear that there are breaking changes in a release. In fact, it often takes a single line of text. You can write that in a fraction of the time it takes you to skim Hacker News front page. No excuses.

What Developers Care About

Developers need a little more information from change logs. Sure, it’s just as important for them to know if there are breaking changes. But developers are more concerned with what new features were introduced.

It’s not sufficient, however, to just mention that there is a new feature X available in the release. You need to make it easy to understand how to use it. This means that documentation needs to be reasonably up-to-date and that you need to provide some examples in the change log itself.

Below are some example from Monger, Langohr and other projects of ours.

Example 1

Example 2

Example 3

How Not To Write a Change Log

Every once in a while you find a project that has ChangeLog.md in the repo that basically says “see git log for change log”.

Unless you write amazingly detailed commit messages and very carefully merge topic branches, that is not a change log. That is a “screw you, figure it out, I don’t owe you anything” thrown to your users. Don’t be that guy.

Final Thoughts

As you can see, it does not take a lot of effort to go from a useless change log to something that will help your users and, in turn, your project adoption.

Michael.