The ClojureWerkz Blog

News and updates about ClojureWerkz projects

Cassaforte 2.0.0-beta3 Is Released

TL;DR

Cassaforte is a Clojure client for Apache Cassandra. It is built around CQL 3 and focuses on ease of use. You will likely find that using Cassandra from Clojure has never been so easy.

2.0.0 is a major API revision release that introduces breaking public API changes.

Changes between 2.0.0-beta2 and 2.0.0-beta3

Cassandra 2.1 Compatibility

Cassaforte 2.0 is compatible with Cassandra 2.1.

Prepared Statement Cache Removed

Prepared statement cache was affecting client correctness in some cases and was removed.

Clojure 1.7.0-alpha2+ Compatibility

Cassaforte is now compatible with Clojure 1.7.0-alpha2 and later versions.

News and Updates

New releases and updates are announced on Twitter. Cassaforte also has a mailing list, feel free to ask questions and report issues there.

Cassaforte is a ClojureWerkz Project

Cassaforte 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
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • EEP, a Clojure library for stream (event) processing
  • Neocons, a Clojure client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

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

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

About the Author

Michael on behalf of the ClojureWerkz Team.

Meltdown 1.1.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.1.0-beta1 is a development mileston that updates Reactor to the most recent point release.

Changes between 1.0.0 and 1.1.0

Reactor Update

Reactor is updated to 1.1.x.

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.

About the Author

Michael on behalf of the ClojureWerkz Team

Metrics-clojure 2.2.0 Is Released

TL;DR

metrics-clojure is a Clojure fa├žade around Coda Hale’s Metrics library, originally developed by Steve Losh.

metrics-clojure is not a ClojureWerkz project but we help maintain it and consider it to be a very valuable library.

Changes Between 2.1.x and 2.2.0

Graphite Extension

metrics.reporters.graphite is a new sub-project that contains a Graphite reporter.

Ring Extension Now Respects User-provided Registry

The Ring extension now respects user-provided registries instead of always using the default one.

Contributed by David Smith.

Bugfixes

  • Fixed metrics.core/default-registry to have a valid reflection hint (no longer causes compile error when used in interop.) Fix planned on 2.1.x as well. Contributed by Tim McCormack.

Full Change Log

metrics-clojure change log is available on GitHub.

About the Author

Michael on behalf of the metrics-clojure Team.

Langohr 3.0.0-rc2 Is Released

TL;DR

Langohr is a small Clojure RabbitMQ client.

3.0 will be a major release that introduces moderate internal changes in the library and some breaking public API refinements.

Changes between Langohr 2.11.x and 3.0.0-rc2

Options as Maps

Functions that take options now require a proper Clojure map instead of pseudo keyword arguments:

1
2
3
4
5
6
7
8
9
10
11
12
# in Langohr 2.x

(lq/declare ch q :durable true)
(lhcons/subscribe ch q (fn [_ _ _])
                        :consumer-tag ctag :handle-cancel-ok (fn [_]))
(lb/publish ch "" q "a message" :mandatory true)

# in Langohr 3.x
(lq/declare ch q {:durable true})
(lhcons/subscribe ch q (fn [_ _ _])
                        {:consumer-tag ctag :handle-cancel-ok (fn [_])})
(lb/publish ch "" q "a message" {:mandatory true})

JDK 8 Compatibility

Langohr test suite now passes on JDK 8 (previously there was 1 failure in recovery test).

GH issue: #54.

Connection Recovery Performed by Java Client

Langohr no longer implements automatic connection recovery of its own. The feature is still there and there should be no behaviour changes but the functionality has now been pushed “upstream” in the Java client, so Langohr now relies on it to do all the work.

There is one public API change: com.novemberain.langohr.Recoverable is gone, langohr.core/on-recovery now uses com.rabbitmq.client.Recoverable instead in its signature.

GH issue: #58.

RabbitMQ Java Client Upgrade

RabbitMQ Java client dependency has been updated to 3.3.5.

Custom Exception Handlers

langohr.core/exception-handler is a function that customizes default exception handler RabbitMQ Java client uses:

1
2
3
4
5
6
(require '[langohr.core :as rmq])

(let [(rmq/exception-handler :handle-consumer-exception-fn (fn [ch ex consumer
                                                               consumer-tag method-name]
                                                             ))]
  )

Valid keys are:

  • :handle-connection-exception-fn
  • :handle-return-listener-exception-fn
  • :handle-flow-listener-exception-fn
  • :handle-confirm-listener-exception-fn
  • :handle-blocked-listener-exception-fn
  • :handle-consumer-exception-fn
  • :handle-connection-recovery-exception-fn
  • :handle-channel-recovery-exception-fn
  • :handle-topology-recovery-exception-fn

GH issue: #47.

langohr.core/version is Removed

langohr.core/version was removed.

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.

About The Author

Michael on behalf of the ClojureWerkz Team

Elastisch 2.1.0-beta5 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.

2.1.0-beta5 is a preview release of Elastisch 2.1.

Changes between Elastisch 2.1.0-beta4 and 2.1.0-beta5

ElasticSearch Native Client Upgrade

Elastisch now depends on ElasticSearch native client version 1.3.x.

Single-Bucket Aggregation Fix in the Native Client

Child aggregations in single-bucket aggregations (i.e. “global”) are no longer silently dropped.

Contributed by Yannick Scherer (StyleFruits).

Full Change Log

Elastisch change log is available on GitHub.

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
  • 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.

About the Author

Michael on behalf of the ClojureWerkz Team

Validateur 2.3.1 Is Released

TL;DR

Validateur is a functional validations library inspired by Ruby’s ActiveModel. Validateur 2.3 is a minor feature release.

Changes Between 2.2.0 and 2.3.0

unnest

unnest is a helper function useful for building UIs that validate on the fly. Here’s a basic example. Let’s write some code to render a UI off of a nested map and build up live validation for that map off of component validators. Here are the components:

1
2
3
4
5
6
7
8
(def profile-validator
  (vr/validation-set
   (vr/presence-of #{:first-name :last-name})))

(def secret-validator
  (vr/validation-set
   (vr/length-of :password :within (range 5 15))
   (vr/length-of :phone :is 10)))

And then the composed, user account validator:

1
2
3
4
(def account-validator
  (vr/compose-sets
   (vr/nested :secrets secret-validator)
   (vr/nested :profile profile-validator)))

Next are the “rendering” functions. Imagine that these are input components responsible for validating their input and displaying errors when present. Our “render” phase will just print.

1
2
3
4
5
6
7
8
9
10
11
12
13
(defn render-profile [profile errors]
  (prn "Profile: " profile)
  (prn "Profile Errors: " errors))

(defn render-secrets [secrets errors]
  (prn "Secrets: " secrets)
  (prn "Secret Errors: " errors))

(defn submit-button
  "Renders a submit button that can only submit when no errors are
  present."
  [errors]
  (prn "All Errors: " errors))

The render-account function renders all subcomponents, performs global validation and routes the errors and data where each needs to go:

1
2
3
4
5
6
7
8
9
10
11
12
13
(defn render-account
  "This function accepts an account object, validates the entire thing
  using the subvalidators defined above, then uses unnested to pull
  out specific errors for each component.

  The entire validation error map is passed into submit-button,
  which might only allow a server POST on click of the full error map
  is empty."
  [{:keys [secrets profile] :as account}]
  (let [errors (account-validator account)]
    (render-profile profile (vr/unnest :profile errors))
    (render-secrets secrets (vr/unnest :secrets errors))
    (submit-button errors)))

Let’s see this function in action. Calling render-account with an invalid map triggers a render that shows off a bunch of errors:

1
2
3
4
5
6
7
8
9
10
11
(render-account
   {:secrets {:password "face"
              :phone "703555555512323"}
    :profile {:first-name "Queequeg"}})


"Profile: " {:first-name "Queequeg"}
"Errors: " {[:last-name] #{"can't be blank"}}
"Secrets: " {:password "face", :phone "703555555512323"}
"Errors: " {[:phone] #{"must be 10 characters long"}, [:password] #{"must be from 5 to 14 characters long"}}
"All Errors: " {[:profile :last-name] #{"can't be blank"}, [:secrets :phone] #{"must be 10 characters long"}, [:secrets :password] #{"must be from 5 to 14 characters long"}}

Calling render-account with a valid map prints only the data:

1
2
3
4
5
6
7
8
9
10
11
(render-account
 {:secrets {:password "faceknuckle"
            :phone "7035555555"}
  :profile {:first-name "Queequeg"
            :last-name "Kokovoko"}})

"Profile: " {:last-name "Kokovoko", :first-name "Queequeg"}
"Errors: " {}
"Secrets: " {:password "faceknuckle", :phone "7035555555"}
"Errors: " {}
"All Errors: " {}

nest

nest is a helper function that makes it easy to validate dynamic data that’s not part of the actual map you pass into the validator. For example, say you wanted to validate all user accounts, then build up a map of userid –> validation errors:

1
2
3
4
5
6
7
8
(for [account (get-all-accounts)]
  (vr/nest (:id account)
           (account-validator account)))

{[100 :profile :first-name] "can't be blank"
 [200 :profile :last-name] "can't be blank"
 ;; etc
 }

Full Change Log

Validateur change log is available on GitHub.

Validateur is a ClojureWerkz Project

Validateur 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
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • Cassaforte, a Clojure Cassandra client built around CQL
  • Neocons, a client for the Neo4J REST API
  • Welle, a Riak client with batteries included
  • Quartzite, a powerful scheduling library

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

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

About The Author

Michael on behalf of the ClojureWerkz Team

Mailer 1.2.0 Is Released

TL;DR

ClojureWerkz Mailer is an ActionMailer-inspired mailer library for Clojure.

1.2.0 is a minor feature release.

Changes Between 1.1.0 and 1.2.0

Improved Template Rendering Exceptions

Template rendering exceptions now have a better error message.p

Contributed by Lei.

Mailer is a ClojureWerkz Project

Mailer 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 minimalistic Clojure client for ElasticSearch
  • Cassaforte, a Clojure client for Cassandra built around CQL
  • Monger, a Clojure MongoDB client for a more civilized age
  • Welle, a Riak client with batteries included
  • Neocons, a Clojure client for the Neo4J REST API

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

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

About the Author

Michael on behalf of the ClojureWerkz Team.

Validateur 2.2.0 Is Released

TL;DR

Validateur is a functional validations library inspired by Ruby’s ActiveModel. Validateur 2.2 is a minor feature release.

Changes Between 2.1.0 and 2.2.0

nested

nested is a new validator runner for nested attributes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(require '[validateur.validation :refer :all])

(let [v (vr/nested :user (vr/validation-set
                            (vr/presence-of :name)
                            (vr/presence-of :age)))
        extra-nested (vr/nested [:user :profile]
                                (vr/validation-set
                                 (vr/presence-of :age)
                                 (vr/presence-of [:birthday :year])))]
  (v {})
  ;= {[:user :age] #{"can't be blank"}
      [:user :name] #{"can't be blank"}}
  (v {:user {:name "name"}})
  ;= {[:user :age] #{"can't be blank"}}
  (extra-nested {:user {:profile {:age 10
                                  :birthday {:year 2004}}}})
  ;= {}
  (extra-nested {:user {:profile {:age 10}}})
  ;= {[:user :profile :birthday :year] #{"can't be blank"}}

Contributed by Sam Ritchie.

validate-by

validate-by is a new validator function. It returns a function that, when given a map, will validate that the + value of the attribute in that map is one of the given:

1
2
3
4
5
6
(require '[validateur.validation :refer :all])

(validation-set
   (presence-of :name)
   (presence-of :age)
   (validate-by [:user :name] not-empty :message \"Username can't be empty!\"))

Contributed by Sam Ritchie.

Full Change Log

Validateur change log is available on GitHub.

Validateur is a ClojureWerkz Project

Validateur 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
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • Cassaforte, a Clojure Cassandra client built around CQL
  • Neocons, a client for the Neo4J REST API
  • Welle, a Riak client with batteries included
  • Quartzite, a powerful scheduling library

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

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

About The Author

Michael on behalf of the ClojureWerkz Team

Mailer 1.1.0 Is Released

TL;DR

ClojureWerkz Mailer is an ActionMailer-inspired mailer library for Clojure.

1.1.0 is a minor feature release.

Changes Between 1.0.0 and 1.1.0

Support for Alternative Email Bodies

build-email and deliver-email now take extra set of template, data, content-type for alternative email body. This is useful for supplying alternative plain-text body in addition to main HTML body of the message.

1
2
3
(build-email {:from "Joe The Robot", :to ["ops@megacorp.internal" "oncall@megacorp.internal"] :subject "Hello!"}
             "templates/html_hello.mustache" {:name "Joe"} :text/html
             "templates/hello.mustache" {:name "Joe"} :text/plain)

Contributed by Lei.

Mailer is a ClojureWerkz Project

Mailer 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 minimalistic Clojure client for ElasticSearch
  • Cassaforte, a Clojure client for Cassandra built around CQL
  • Monger, a Clojure MongoDB client for a more civilized age
  • Welle, a Riak client with batteries included
  • Neocons, a Clojure client for the Neo4J REST API

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

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

About the Author

Michael on behalf of the ClojureWerkz Team.

Quartzite 1.3.0 Is Released

Quartzite is a Clojure DSL on top of the Quartz scheduler.

1.3.0 is a minor release that contains minor improvements and upgrades dependencies.

Changes Between Quartzite 1.2.0 and 1.3.0

Clojure 1.6 by Default

The library now depends on Clojure 1.6.

clj-time upgraded to 0.8.0

clj-time dependency has been upgraded to version 0.8.0.

Changes between Quartzite 1.1.0 and 1.2.0

Clojure 1.3 is No Longer Supported

Quartzite requires Clojure 1.4+ as of this version.

clj-time upgraded to 0.6.0

clj-time dependency has been upgraded to version 0.6.0.

New Functions

  • clojurewerkz.quartzite.scheduler/get-currently-executing-jobs returns a set of currently executing jobs.
  • clojurewerkz.quartzite.scheduler/currently-executing-job? returns true there is a running job for a given key.

Change Log

Quartzite change log is available on GitHub.

Quartzite is a ClojureWerkz Project

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

  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • Monger, a Clojure MongoDB driver for a more civilized age
  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Welle, a Riak client with batteries included
  • Neocons, a client for the Neo4J REST API

and several others. If you like Quartzite, 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