I wrote this code to automatically open and close my JMSConnection's in Clojure:

(defn with-jms
  ([provider-url context-factory factory-name fn args]
   (with-open [jndi-ctx (new InitialContext (populate-env provider-url context-factory))
               jms-conn (-> (.lookup jndi-ctx factory-name)
       (apply fn (-> (sequence args)
                     (conj jms-conn)
                     (conj jndi-ctx)))))
  ([fn args]
   (let [{provider-url    "provider-url"
          context-factory "context-factory"
          factory-name    "factory-name"} jms-properties]
     (with-jms provider-url context-factory factory-name fn args))))

Note how properties are used for convenience. Please also note that populate-env is a function that returns a HashTable populated with the necessary JMS properties.

I can then define JMS functions the following way:

(defn send-text-message! [jndi-ctx jms-conn topic content]
  (with-open [session (.createSession jms-conn false Session/AUTO_ACKNOWLEDGE)
              producer (.createProducer session (.lookup jndi-ctx topic))]
    (let [message (.createTextMessage session content)]
      (.send producer message))))

I can combine both functions in the following way :

(with-jms send-text-message! ["clojureTopic" "azerty"])

However I'm not 100% satisfied with it. These are the things that puzzle me:

  • In with-jms, the args in with-jms is an array, because overloading and multi-varied arguments is not supported in Clojure. Is there a better alternative?
  • In with-jms, the (apply fn (-> (sequence args) (conj jms-conn) (conj jndi-ctx))) part feels really clunky, is there a better way to write that?
  • When I call with-jms function, I must remember to exclude the jndi-ctx and the jms-conn from the argument lists even if it's in the called function signature. I don't like it, I find it confusing. I tried to write a wrapper that returns a partial function but it felt unnecessary and tedious to do for every JMS function. Maybe there's a better way to write with-jms?

Any help would be appreciated !


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.