Pregunta

Entonces, actualmente tengo este código:

(ns contact-form.core
  (:gen-class))

(def foo "Hello World!")

(defn some-func [a-symbol]
  (println (str a-symbol "'s value is: " (eval a-symbol))))

(defn -main [& args]
  (some-func 'foo))

Después de hacer C-c C-k en Emacs, obtengo el siguiente resultado:

contact-form.core> (-main)
foo's value is: Hello World!
nil

Pero cuando hago lein uberjar y ejecuto el archivo jar resultante, aparece un error:

Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:0)
    at clojure.lang.Compiler.analyze(Compiler.java:6235)
    at clojure.lang.Compiler.analyze(Compiler.java:6177)
    at clojure.lang.Compiler.eval(Compiler.java:6469)
    at clojure.lang.Compiler.eval(Compiler.java:6431)
    at clojure.core$eval.invoke(core.clj:2795)
    at contact_form.core$some_func.invoke(core.clj:7)
    at contact_form.core$_main.doInvoke(core.clj:10)
    at clojure.lang.RestFn.invoke(RestFn.java:397)
    at clojure.lang.AFn.applyToHelper(AFn.java:159)
    at clojure.lang.RestFn.applyTo(RestFn.java:132)
    at contact_form.core.main(Unknown Source)
Caused by: java.lang.RuntimeException: Unable to resolve symbol: foo in this context
    at clojure.lang.Util.runtimeException(Util.java:156)
    at clojure.lang.Compiler.resolveIn(Compiler.java:6720)
    at clojure.lang.Compiler.resolve(Compiler.java:6664)
    at clojure.lang.Compiler.analyzeSymbol(Compiler.java:6625)
    at clojure.lang.Compiler.analyze(Compiler.java:6198)
    ... 10 more

Entonces tengo dos preguntas:

  1. ¿Por qué el uberjar no funciona exactamente igual que el REPL?
  2. ¿Qué puedo hacer para solucionar este problema?
¿Fue útil?

Solución

1. ¿Por qué uberjar funciona de manera diferente a REPL?

Una causa del error "NO_SOURCE_PATH" es que no se encuentra actualmente en el espacio de nombres que definió 'foo.

Para ilustrar: si evalúo su código en mi REPL y lo ejecuto, me coloca en el espacio de nombres contact-form.core como cabría esperar porque el REPL evalúa (ns contact-form.core), pero si cambio al espacio de nombres user y llamo -main puedo producir el mismo error:

contact-form.core=> (-main)
foo's value is: Hello World!
nil
contact-form.core=> (ns user)
nil
user=> (contact-form.core/-main)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:120) 
user=> 

Por lo tanto, al especificar su punto de entrada a main para la ejecución autónoma de uberjar (fuera del REPL), es equivalente a llamar a (contact-form.core/-main) desde el espacio de nombres predeterminado en su jar, que es clojure.core, porque (ns contact-form.core) no ha sido evaluado. Resultado: main se puede ejecutar con una ruta completamente calificada (con espacio de nombres) a la función, pero ninguno de los símbolos de contact-form.core está disponible en el espacio de nombres predeterminado actual.

2. La solución

La solución sería cambiar explícitamente primero a su espacio de nombres:

(defn -main [& args]
  (use 'contact-form.core)
  (some-func 'foo))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top