Skip to content

qiuxiafei/thrift-clj

 
 

Repository files navigation

thrift-clj

Build Status

Using Thrift from Clojure as if it was Clojure.

Usage

thrift-clj is available via Clojars.

Leiningen

[thrift-clj "0.1.0"]

Note: Tested with the Thrift 0.9.0 compiler. Since this depends massively on the generated code, make sure to use that version (or any other one that was tested with this library).

Automatic Thrift Compilation

I recommend lein-thriftc for automatic compilation of Thrift IDL files to Java class files.

Example

A working example demonstrating Service and Client implementation should always be available as thrift-clj-example. A small peek follows.

Accessing Types

Thrift

namespace java org.example

struct Person {
  1: optional string firstName,
  2: string lastName,
  3: byte age
}

Compile to Java using Thrift and add to Leiningen's classpath. (see :java-source-paths)

Clojure

(require '[thrift-clj.core :as thrift])
(thrift/import 
  (:types [org.example Person]))
  
(def clj-p (Person. "Some" "One" 99)) 
;; => #ns_1071852349.Person{:firstName "Some", :lastName "One", :age 99}

(def thr-p (thrift/->thrift clj-p))   
;; => #<Person Person(firstName:Some, lastName:One, age:99)>

(class clj-p) ;; => ns_1071852349.Person
(class thr-p) ;; => org.example.Person

Implementing a Service

Thrift

namespace java org.example

// ... Person struct from above ...

service PersonIndex {
    bool storePerson(1:i32 id, 2:Person p),
    Person getPerson(1:i32 id)
}

Clojure

(require '[thrift-clj.core :as thrift])
(thrift/import 
  (:types [org.example Person])
  (:services org.example.PersonIndex))

(defonce person-db (atom {}))
(thrift/defservice person-index-service
  PersonIndex
  (storePerson [id p]
    (boolean
      (when-not (@person-db id)
        (info "Storing Person:" p)
        (swap! person-db assoc id p)
        true)))
  (getPerson [id]
    (info "Retrieving Person for ID:" id)
    (@person-db id))) 
    
(thrift/serve-and-block!
  (thrift/multi-threaded-server
    person-index-service 7007
    :bind "localhost"
    :protocol :compact))

Running a Client

(require '[thrift-clj.core :as thrift])
(thrift/import 
  (:types [org.example Person])
  (:clients org.example.PersonIndex))
  
(with-open [c (thrift/connect! PersonIndex ["localhost" 7007])]
  (PersonIndex/storePerson c 1 (Person. "Some" "One" 99))
  (PersonIndex/getPerson c 1))

Roadmap

  • Have a look at Lists/Sets/Enums/...
  • wrappers around Protocols (to encode/decode values directly to/from byte arrays)
  • more protocols/servers/clients
  • asynchronous client/server
  • union?
  • exceptions
  • tests & documentation
  • ...

Related Work/Inspiration

License

Copyright © 2013 Yannick Scherer

Distributed under the Eclipse Public License, the same as Clojure.

About

Thrift and Clojure!

Resources

Stars

Watchers

Forks

Packages

No packages published