import clojure.lang.LockingTransaction;
import clojure.lang.Ref;
import clojure.lang.AFn;
import java.util.concurrent.Callable;

class stm {
    static String hello = "hello";
    static Ref a;
    static Ref b;

    static {
        try {
            a = new Ref(hello);
            b = new Ref(hello.length());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static void prn() {
        System.out.println("a = " + a.deref() + ", b = " 
                           + b.deref());
    }

    static class StmSetter implements Callable {
        String input;
        
        StmSetter(String input) {
            this.input = input;
        }

        public Object call() throws Exception {
            a.set(input);
            b.set(input.length());
 
            return null;
        }
    }

    static void run(String val) {
        try {
            LockingTransaction.runInTransaction(
                    new StmSetter(val));
        } catch (Exception e) {
            System.out.println(e.getClass().getName());
        }
    }

    public static void main(String[] args) {
        try {
            prn();
            run("foo");
            prn();
            run(null);
            prn();
            run("world");
            prn();
        } catch (Exception e) {
            e.printStackTrace();
        }    
    }
}
