Lein compile project with protocols

Igor Artamonov

I have a project with following ns:

  • processor.bus <- general protocol for bus operations
  • processor.core <- main class to run
  • processor.pubsub <- concrete bus methods

in processor.pubsub I have following:

(ns processor.pubsub
  (:gen-class))

(defrecord PubsubBus [client])

; + other stuff related to this implementation

In processor.bus I have:

(ns tiptop.processor.bus
  (:gen-class)
  (:import [processor.pubsub PubsubBus]))

(defprotocol SendToBus
  (send-line! [self json]))

(extend-type PubsubBus
  SendToBus
  ....) 

The problem that Lein doesn't compile namespaces in right order. I get following error:

$ lein compile
Compiling user
Compiling processor.auth
Compiling processor.bus
java.lang.ClassNotFoundException: processor.pubsub.PubsubBus, compiling:(bus.clj:1:1)
Exception in thread "main" java.lang.ClassNotFoundException: processor.pubsub.PubsubBus, compiling:(bus.clj:1:1)

Notice it tries to compile my ns in alphabetical order (auth -> bus -> pubsub), instead if dependency order.

Of course I could precompile pubsub.clj before, like:

$ lein compile processor.pubsub
$ lein compile processor.bus
$ lein compile

But it doesn't seems quite right for me. What if I'll have more such dependent namespaces?

How I can tell Lein in which order it should compile my namespaces? Or maybe i'm missing something to configure in project.clj? I have :aot :all if it matters

Alex

Leiningen does not do anything to determine namespace dependencies - it simply compiles the namespaces that you tell it to. It is the Clojure compiler that handles namespace dependencies via the require (and obsolete use) built-ins.

In this case, you need to :require the namespace that defines the generated class before you can import it. Otherwise, you're relying on the imported class being present on the classpath as a side effect of some other operation (loading the namespace that defines it in the REPL, a previous lein compile command, etc). Adding an explicit :require in the namespace definition ensures the class is defined before it's imported:

(ns processor.bus
  (:gen-class)
  (:require [processor.pubsub])
  (:import [processor.pubsub PubsubBus]))

A couple of other notes:

  • I doubt :gen-class is doing what you think it's doing in these namespace declarations. It does not cause class files to get written for the protocol and records defined in these namespaces; that's what the :aot key is for in the Leiningen project.clj. The :gen-class flag as it's used here will cause classes named processor.bus and processor.pubsub to be generated.
  • It's unusual to see protocol implementation details for concrete record types specified via extend-type in the same namespace where the protocol is defined. The typical use case for extend-type is to extend your protocol to work with types that are beyond your control, like those built in to Clojure or defined in third-party libraries. When the protocol and record are defined in the same project, it's more common to see the protocol implementation defined inline as part of the defrecord body.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Lein Figwheel Compile Error

From Dev

Using lein project with /lib doesn't work

From Dev

Compile clojure source into class (AOT) from command line (not using lein)

From Dev

Compile clojure source into class (AOT) from command line (not using lein)

From Dev

Can I lookup things within a Lein Project in the REPL?

From Dev

How to load and use native c code in a lein project?

From Dev

ClassNotFoundException trying to run "lein run server-headless" for any project

From Dev

Compile a Cython project and clean

From Dev

Compile options for alsa project

From Dev

Compile Groovy project with -indy

From Dev

Not able to compile grails project

From Dev

Compile Groovy project with -indy

From Dev

Compile and run Angular Project?

From Dev

Build a project is the same as "compile"?

From Dev

Maven compile replies 'No sources to compile' for scala project

From Dev

Maven compile replies 'No sources to compile' for scala project

From Dev

Compile entire project from another project

From Dev

Compile MVC project to a single DLL?

From Dev

Compile android project with a higher sdk

From Dev

Compile a compiler as an external project and use it?

From Dev

Trying to compile a project with Scalatra and failing

From Dev

Unable to compile my android project

From Dev

Compile Library project with AndroidAnnotations and Fragments

From Dev

how to compile opencl project with kernels

From Dev

compile xcode project file to send

From Dev

Compile android project with a higher sdk

From Dev

Add /MT compile flag to project

From Dev

Unable to Compile a Qt project in qtcreator

From Dev

Compile a compiler as an external project and use it?

Related Related

HotTag

Archive