Welcome! Please see the About page for a little more info on how this works.

0 votes
in Meta by

Hi,

i have two Leiningen project that compiles well, and worked well before sharing some functions in a common included file.
Both project runs on a tomcat server

First project create a .jar file used as a library for java code compiled from java source.
it has been created with:
lein new eu.oca.jclojure
and compile this way:
lein uberjar

The other project is a full clojure web application running also on tomcat.
it has been created with:

lein new compojure sidonie-admin

and compile with:
lein ring uberwar

the common file is included in source clojure code like this:

(load-file "src/sidonie_admin2/sidonie-common.clj") in the second project and in the first like this (and both compile without errors)
(load-file "../sidonie-admin2/src/sidonie_admin2/sidonie-common.clj")

The error occurs at runtime :

the problem come of the file having common definitions that is not included in the war file and probably not in the jar file and i have this error when running one project:
java.io.FileNotFoundException: ../sidonie-admin2/src/sidonie_admin2/sidonie-common.clj

and this error with other project:
Caused by: java.io.FileNotFoundException: src/sidonie_admin2/sidonie-common.clj (Aucun fichier ou dossier de ce type)

those are same type of error complaining about missing source file in JVM byte code !
a bit surprising ,i admit in case of error print stack trace needs some info to give line number of error.

so the question is simple, how can i share the common file between two projects and have no error?

best regards,

Damien

here is some output of server log:

08-Oct-2019 12:40:51.275 SEVERE [http-nio-127.0.0.1-8080-exec-8] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [eu.oca.ApplicationConfig] in context with path [/Sidonie] threw exception [org.glassfish.jersey.server.ContainerException: java.lang.ExceptionInInitializerError] with root cause
java.io.FileNotFoundException: ../sidonie-admin2/src/sidonie_admin2/sidonie-common.clj (Aucun fichier ou dossier de ce type)

at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at clojure.lang.Compiler.loadFile(Compiler.java:7314)
at clojure.lang.RT$3.invoke(RT.java:320)
at eu.oca.jclojure__init.load(Unknown Source)
at eu.oca.jclojure__init.<clinit>(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at clojure.lang.RT.classForName(RT.java:2168)
at clojure.lang.RT.classForNam

...

un(NioEndpoint.java:1500)

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

and also:

08-Oct-2019 12:21:42.761 SEVERE [http-nio-127.0.0.1-8080-exec-11] org.apache.catalina.core.StandardContext.listenerStart Exception lors de l'envoi de l'évènement contexte initialisé (context initialized) à l'instance de classe d'écoute (listener) sidonie_admin2.listener
Syntax error compiling at (sidonie_admin2/handler.clj:32:1).

at clojure.lang.Compiler.load(Compiler.java:7647)
at clojure.lang.RT.loadResourceScript(RT.java:381)
at clojure.lang.RT.loadResourceScript(RT.java:372)
at clojure.lang.RT.load(RT.java:463)
at clojure.lang.RT.load(RT.java:428)
at clojure.core$load$fn__6824.invoke(core.clj:6126)
at clojure.core$load.invokeStatic(core.clj:6125)
at clojure.core$load.doInvo

...

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

Caused by: java.io.FileNotFoundException: src/sidonie_admin2/sidonie-common.clj (Aucun fichier ou dossier de ce type)

at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInp

3 Answers

+3 votes
by

The best approach is probably going to be turning the shared code into its own project and producing an artifact from that (a regular, non-uber JAR) but that means you'll need to publish the artifact somewhere -- or just make the build process for each original project also build and "install" the shared project locally.

Or you could have both original projects use Leiningen's "checkouts" feature to have them depend on the common code project via Git.

As Alex says in his answer: don't use load-file for this. Make the common code into something genuinely shared that you can just :require in via its namespace. That means getting the shared code into a format that is on the classpath for each project (via checkouts or an additional build step to package up the common code as a JAR).

+1 vote
by

Why are you using load-file? When the clj file is inside a jar or war file, you cannot load it as a file (and using load-file is very unusual in Clojure). The way you typically load things is by requireing them into a namespace.

by
He's using load-file because he's trying to share sourcecode between two projects.
0 votes
by

thanks for the response, but i can not do it this way. In fact it's not a library or something reusable that can be set in a lib or even a name space i think, because i can put all in the war file and not have separated jar library use with NetBeans for a public part of web site and after i developed a password protected part of site that use compojure. So in fact i could revamp all the code in one single .war compojure file. But it is faster to stay like that...

so i found this solution, ah ah this is basically a hack, a UNIX hack i admit it, to share the common file i made a symbolic link:

ln -s ../../../../sidonie-admin2/src/sidonie_admin2/sidonie-common.clj symbolic-link-sidonie-common.clj

and i changed a bit the way to load file instead of load-file i use load:

(load "symbolic-link-sidonie-common")

works also with hard link, but my Dropbox account does not support hard link,also this solution should works under windows as it supports also links.

so i can edit a simple files that is shared on many projects, and i can edit it from any directory .

Under emacs had to had (setq backup-by-copying-when-linked t) in .emacs to avoid the mv (move) feature of emacs .~ backup files that put the mess with links.

i admit it is not the perfect solution but the question also was not perfect ;-)

Damien

...