вторник, 17 июня 2014 г.

How to make jar with dependencies using clojure language

I like clojure but I don't like uberjars. I prefer to make my programs in a structure where I have main program jar file and lib folder with all dependencies jars.
To make jar with dependencies using clojure language we need
1. install libdir and lein-exec plugins
2. In a project.clj add :manifest and libdir plugin config like this

  :main ^:skip-aot myprog.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all}}

  :manifest { "Class-Path" "lib/clojure-1.6.0.jar"}

  ;;call 'lein libdir' in order to copy all dependencies into lib folder
  :plugins [[lein-libdir "0.1.1"]]
  :libdir-path "lib")

3. go to root project folder and run my script from command line


rm a.txt
lein libdir
ls lib/ >>a.txt
lein exec -e '(def file-list (slurp "a.txt")) (def clean-file-list (clojure.string/split file-list #"\n")) (def add-lib-list (map #(str "lib/" %1 " ") clean-file-list)) (println (reduce str add-lib-list))'

rm a.txt

This script will print necessary value for :manifest in a project.clj

4. copy produced string to :manifest in a section "Class-Path" in a project.clj

5. Then run lein uberjar.

6. Go target/uberjar/ folder where you can find not standalone jar of your program. Then copy lib folder from the root of your project (this folder produced on step 3 when 'lein libdir' plugin is called) and now you can run: java -jar yourprogram.jar

Also, in a such way you can build standalone jar library for other java programmers, but in this case you need to remove lib prefix in a manifest section. so all dependencies should be in a same folder.

четверг, 12 июня 2014 г.

call clojure code from java

Since clojure 1.6 there is no more special dances inside clojure code: special declarations or wrappers or something else. it is possible call clojure code from jar file like this. Clojure code (jar file) and clojure-1.6.jar should be in a class-path.

import clojure.java.api.Clojure;
import clojure.lang.IFn;

        IFn require = Clojure.var("clojure.core", "require");

        IFn myf0 = Clojure.var("my-clj-project.core", "my-clojure-func0");

or  myf0.invoke(param1, param2);

среда, 11 июня 2014 г.

How to break JCE crypto policy limit when using bouncycastle

    //this code allows to break limit if client jdk/jre has no unlimited policy files for JCE.
    //it should be run once. So this static section is always execute during the class loading process.
//this code is useful when working with Bouncycastle library.
    static {
        try {
            Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
            field.set(null, java.lang.Boolean.FALSE);
        } catch (Exception ex) {

or clojure variant of this function

(defn break-jce-policy-limit
  "This function breaks JCE crypto limits. Should be run once, primarily at the begining of the program
  to avoid JCE policy limit if JDK/JRE runtime has no installed files for break crypto limit. Returns nil."
  (safe (let [field (-> (Class/forName "javax.crypto.JceSecurity")
                      (.getDeclaredField "isRestricted"))]
          (.setAccessible field true)
          (.set field nil java.lang.Boolean/FALSE))))

(defmacro safe [bindings? & forms]
  "This macro is used to execute any function inside try-catch block."
  (let [bindings (if (and (even? (count bindings?)) (vector? bindings?))
                   bindings? nil)
        forms (if bindings forms (cons bindings? forms))
        except `(catch Exception e# e#
                  (println (.getMessage e#) e#))]
    (if bindings
      `(let ~bindings (try ~@forms ~except))
      `(try ~@forms ~except))))