pulsar icon indicating copy to clipboard operation
pulsar copied to clipboard

Adding pulsar dep breaks refactor-nrepl plugin

Open jjcomer opened this issue 9 years ago • 17 comments

When I add pulsar as a dependency (with quasar), the refactor-nrepl plugin is prevented from loading. If I remove pulsar, the plugin starts working again. The cider-nrepl plugin does not have this issue. Not sure where this defect lies, if it is in the plugin or in plusar.

jjcomer avatar Aug 20 '15 13:08 jjcomer

I don't know much about refactor-nrepl but I tried adding the Leiningen plugin to a basically empty project with no deps (specifically no Quasar/Pulsar and no agents) and when I run lein repl I get the following:

Error loading refactor-nrepl.middleware: java.io.FileNotFoundException: Could not locate cider/nrepl/middleware/util/misc__init.class or cider/nrepl/middleware/util/misc.clj on classpath: , compiling:(refactor_nrepl/middleware.clj:1:1)
Exception in thread "main" java.lang.RuntimeException: Unable to resolve var: refactor-nrepl.middleware/wrap-refactor in this context, compiling:(/tmp/form-init5440298671210986450.clj:1:1477)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6651)
    at clojure.lang.Compiler.analyze(Compiler.java:6445)
    at clojure.lang.Compiler.analyze(Compiler.java:6406)
    at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6646)
    at clojure.lang.Compiler.analyze(Compiler.java:6445)
    at clojure.lang.Compiler.analyze(Compiler.java:6406)
    at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6646)
    at clojure.lang.Compiler.analyze(Compiler.java:6445)
    at clojure.lang.Compiler.access$100(Compiler.java:38)
    at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6050)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6644)
    at clojure.lang.Compiler.analyze(Compiler.java:6445)
    at clojure.lang.Compiler.analyze(Compiler.java:6406)
    at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782)
    at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5217)
    at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3846)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6642)
    at clojure.lang.Compiler.analyze(Compiler.java:6445)
    at clojure.lang.Compiler.eval(Compiler.java:6700)
    at clojure.lang.Compiler.eval(Compiler.java:6693)
    at clojure.lang.Compiler.eval(Compiler.java:6693)
    at clojure.lang.Compiler.load(Compiler.java:7130)
    at clojure.lang.Compiler.loadFile(Compiler.java:7086)
    at clojure.main$load_script.invoke(main.clj:274)
    at clojure.main$init_opt.invoke(main.clj:279)
    at clojure.main$initialize.invoke(main.clj:307)
    at clojure.main$null_opt.invoke(main.clj:342)
    at clojure.main$main.doInvoke(main.clj:420)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at clojure.lang.Var.invoke(Var.java:383)
    at clojure.lang.AFn.applyToHelper(AFn.java:156)
    at clojure.lang.Var.applyTo(Var.java:700)
    at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: Unable to resolve var: refactor-nrepl.middleware/wrap-refactor in this context
    at clojure.lang.Util.runtimeException(Util.java:221)
    at clojure.lang.Compiler$TheVarExpr$Parser.parse(Compiler.java:659)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6644)
    ... 34 more
REPL server launch timed out.

This is the project file (project generated with lein new <name>):

(defproject basic "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.6.0"]]
  :plugins [[refactor-nrepl "1.1.0"]])

Is that the issue you're running into? Else what's the trace/log, if any? How do you know the plugin is prevented from loading? If you can share a testable reproduction of the issue it can greatly help.

circlespainter avatar Aug 21 '15 12:08 circlespainter

This works with lein repl:

(defproject dep-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]]
  :plugins [[refactor-nrepl "1.1.0"]])

This one breaks with the above error you quote.

(defproject dep-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [co.paralleluniverse/pulsar "0.7.2"]]
  :java-agents [[co.paralleluniverse/quasar-core "0.7.2"]]
  :plugins [[refactor-nrepl "1.1.0"]])

And to be thorough :wink: this one works too:

(defproject dep-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [co.paralleluniverse/pulsar "0.7.2"]]
  :java-agents [[co.paralleluniverse/quasar-core "0.7.2"]])

jjcomer avatar Aug 21 '15 12:08 jjcomer

Also interesting is that both of these work:

(defproject dep-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]]
  :java-agents [[co.paralleluniverse/quasar-core "0.7.2"]]
  :plugins [[refactor-nrepl "1.1.0"]])
(defproject dep-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [co.paralleluniverse/pulsar "0.7.2"]]
  :plugins [[refactor-nrepl "1.1.0"]])

jjcomer avatar Aug 21 '15 12:08 jjcomer

Here (Linux Mint 17.2 Rafaela, Oracle JDK 1.8.0_60-b27 64-bit on MBP late 2008) this too breaks with the above error:

(defproject dep-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]]
  :plugins [[refactor-nrepl "1.1.0"]])

circlespainter avatar Aug 21 '15 12:08 circlespainter

I'm running Ubuntu 15.04 -- Leiningen 2.5.2 on Java 1.8.0_60 Java HotSpot(TM) 64-Bit Server VM

Also tried wiping out the my user profile. Turns out you need cider-nrepl too.

Here is the base then:

(defproject dep-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]]
  :plugins [[refactor-nrepl "1.1.0"]
            [cider/cider-nrepl "0.9.1"]])

jjcomer avatar Aug 21 '15 14:08 jjcomer

Adding :bootclasspath true (which tells Leiningen to add the agent JAR to the boot class path as well) seems to solve the issue, although it's not completely clear why to me; I just don't know enough about those plugins' architecture (or leiningen's plugins classloading architecture for that matter).

This relates to classloading hierarchies anyway, for example quasar-core needs be added to the boot class path as well when instrumenting JDK parts; this is because it adds reference to some Quasar runtime classes during instrumentation (which must be loadable by the JDK classloader afterwards).

Does this work for you?

circlespainter avatar Aug 23 '15 08:08 circlespainter

@circlespainter Adding :bootclasspath true makes the refactor-nrepl error go away, but then the pulsar code stops working.

I started with https://github.com/yogthos/pulsar-example and edited its project.clj to look like:

(defproject pulsar-example "0.1.0-SNAPSHOT"
  :description "a sample project using Pulsar"
  :url "https://github.com/yogthos/pulsar-example"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [co.paralleluniverse/pulsar "0.7.3"]
                 [co.paralleluniverse/quasar-core "0.7.3"]]

  :plugins [[refactor-nrepl "1.1.0"]
            [cider/cider-nrepl "0.9.1"]]

  :bootclasspath true

  :manifest {"Premain-Class" "co.paralleluniverse.fibers.instrument.JavaAgent"
             "Agent-Class" "co.paralleluniverse.fibers.instrument.JavaAgent"
             "Can-Retransform-Classes" "true"
             "Can-Redefine-Classes" "true"}

  :java-agents [[co.paralleluniverse/quasar-core "0.7.3"]]

  :main pulsar-example.core
  :uberjar-name "pulsar-example.jar"
  :aot [pulsar-example.core])

The REPL loaded just fine, but when I tried to run (-main), it threw a NullPointerException.

1. Unhandled java.lang.NullPointerException
   (No message)

              ActorLoader.java:  368  co.paralleluniverse.actors.ActorLoader/loadCurrentClass
              ActorLoader.java:  392  co.paralleluniverse.actors.ActorLoader/getCurrentClassFor
              ActorLoader.java:  379  co.paralleluniverse.actors.ActorLoader/getReplacementFor0
              ActorLoader.java:  117  co.paralleluniverse.actors.ActorLoader/getReplacementFor
                    Actor.java:  135  co.paralleluniverse.actors.Actor/checkReplacement
                    Actor.java:  235  co.paralleluniverse.actors.Actor/spawn
                    Actor.java:  203  co.paralleluniverse.actors.Actor/spawn
                      core.clj:   29  pulsar-example.core/-main
                          REPL:    1  pulsar-example.core/eval15500

beppu avatar Sep 16 '15 02:09 beppu

A Workaround

Normally, I have the refactor-nrepl and cider-nrepl plugins setup in my ~/.lein/profiles.clj.

To remove refactor-nrepl, I create a project-specific profiles.clj in the root of the project that overrides :plugins:

{:user {:plugins ^:replace [[lein-pprint "1.1.1"]
                            [cider/cider-nrepl "0.9.1"]]}}

Notice that it doesn't include refactor-nrepl. I can live without that plugin, and at least I have a working REPL with pulsar again.

beppu avatar Sep 17 '15 05:09 beppu

@beppu Thanks for posting a workaround. I'll be looking further into this issue.

circlespainter avatar Sep 28 '15 12:09 circlespainter

Same issue for me with pulsar 0.7.3. @beppu 's work-around works. (I too specify refactor-nrepl in ~/.lein/profiles.clj`.)

stig avatar Dec 06 '15 00:12 stig

@circlespainter the problem you encountered in the second post of this thread is caused by your not specifying a cider-nrepl version in your profiles.clj. We assume that dependency is :provided, because our plugin works on all versions of that middleware and we didn't want to pollute the classpath unnecessarily by specifying some specific version (and risk overriding the user's preference) when we don't have to.

expez avatar Dec 06 '15 20:12 expez

Here are a few other threads discussing this same issue:

https://github.com/puniverse/pulsar/issues/20 https://github.com/clojure-emacs/refactor-nrepl/issues/107

expez avatar Dec 06 '15 20:12 expez

@expez Thanks, it doesn't look like the instrumentation errors in https://github.com/clojure-emacs/refactor-nrepl/issues/107 are the source of the issue because when not using auto-instrumentation I can see no errors in the full instrumentation logs (they can be obtained by adding :options "vdc" to the agent entry).

Some tricky interaction with mranderson is possible but it sounds strange that it only happens with refactor-nrepl and not with cider-nrepl.

This definitely requires some more investigation.

circlespainter avatar Jan 31 '16 08:01 circlespainter

@circlespainter Thanks for your investigation! I would really love to have this solved, since cider-nrepl + refactor-nrepl is my main programming environment.

malchmih avatar Feb 01 '16 08:02 malchmih

does someone has a solution to this, im falling in the same error? also i wasnt able to remove refactor-nrepl as suggested because it is being called by emacs and i dont know how to prevent it from calling automatically, even though it isnt listed in my project.clj file. Any help is appreciated...

greboide avatar May 17 '17 06:05 greboide

@greboide to get rid of refactor-nrepl do (setq cljr-inject-dependencies-at-jack-in nil) in your .emacs

clj-refactor is injecting its own middleware. Without it quite a few refactorings won't work anymore.

expez avatar May 17 '17 07:05 expez

nice, thank you @expez im such a noobie with clojure, i dont think im going to refactor just now, anyway it works like a charm without it!

greboide avatar May 18 '17 16:05 greboide