Re: [ccw] ClassCastException trying to start a REPL

27 views
Skip to first unread message

Chas Emerick

unread,
Oct 8, 2012, 12:48:15 PM10/8/12
to clojured...@googlegroups.com
This is being caused by a recent change in nREPL.  CCW had been relying upon undocumented implementation details of the value returned by start-server (my bad, I wrote both bits of code :-P).  The latest nREPL builds do not return an Agent anymore:


It does return a record (map) that implements IDeref, so other codebases (especially Clojure ones) that simply deref'ed the value returned by start-server will be unaffected by the change.  Unfortunately, I over-specialized the cast in CCW.

Anyway, if you grab a SNAPSHOT build of nREPL (see https://github.com/laurentpetit/ccw/pull/15 for some notes on this change), then all should be well.

- Chas

On Oct 8, 2012, at 12:23 PM, Dave Hartnoll wrote:

Following on from the problems I've been having with the Namespace Browser (see recent posts in -users or my filed issue 455) I decided to have a go at compiling CCW myself to see if I can help locate the issue (and with a secondary motive to learn a little more about Clojure/Java integration).

I've managed to build a working development environment thanks to the HowToBuild instructions in the wiki, and I've successfully started an EclipseApplication with all plugins from the workspace. Everything seems as it should, and I started by creating a simple Clojure project as per the simple steps in my issue above. However, when I try to start a REPL, I get a stacktrace (listed in full below). I've tried to follow the root cause but I'm having difficulty understanding what might be wrong.

The exception is:

java.lang.ClassCastException: clojure.tools.nrepl.server.proxy$clojure.lang.Agent$Closeable$b14108b6 cannot be cast to java.util.Map
at ccw.CCWPlugin.startREPLServer(CCWPlugin.java:97)

The relevant lines from CCWPlugin.java:

90:  Var startServer = BundleUtils.requireAndGetVar(getBundle().getSymbolicName(), "clojure.tools.nrepl.server/start-server");
  ...
97:  ackREPLServer = (ServerSocket)((Map)startServer.invoke(Keyword.intern("handler"), handler)).get(Keyword.intern("server-socket"));

The relevant lines from start-server in clojure.tools.nrepl.server:

  [& {:keys [port bind transport-fn handler ack-port greeting-fn] :or {port 0}}]
  (let [bind-addr (if bind (InetSocketAddress. bind port) (InetSocketAddress. port))
        ss (ServerSocket. port 0 (.getAddress bind-addr))
        smap {:ss ss
              :transport (or transport-fn t/bencode)
              :greeting greeting-fn
              :handler (or handler (default-handler))}
        server (proxy [clojure.lang.Agent java.io.Closeable] [smap]
                 (close [] (stop-server this)))]
    (send-off server accept-connection)
    (when ack-port
      (ack/send-ack (.getLocalPort ss) ack-port))
    server))

From my reading of this code, the return value is a Map which is also proxied to be a clojure.lang.Agent and a java.io.Closeable. I'm not sure why there is a ClassCastException, and I presume there normally isn't as CCW clearly works. I hate to fall at an early hurdle like this but I'm stumped and would appreciate an pointers.

Dave.

Here's the full stack trace:

!ENTRY ccw.core 4 0 2012-10-08 16:45:39.581
!MESSAGE Could not start plugin-hosted REPL server
!STACK 0
java.lang.ClassCastException: clojure.tools.nrepl.server.proxy$clojure.lang.Agent$Closeable$b14108b6 cannot be cast to java.util.Map
at ccw.CCWPlugin.startREPLServer(CCWPlugin.java:97)
at ccw.CCWPlugin.getREPLServerPort(CCWPlugin.java:108)
at ccw.launching.ClojureLaunchDelegate.getProgramArguments(ClojureLaunchDelegate.java:226)
at org.eclipse.jdt.launching.JavaLaunchDelegate.launch(JavaLaunchDelegate.java:63)
at ccw.launching.ClojureLaunchDelegate.launch(ClojureLaunchDelegate.java:192)
at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:855)
at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:704)
at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:697)
at ccw.launching.ClojureLaunchShortcut.launchProject(ClojureLaunchShortcut.java:127)
at ccw.launching.ClojureLaunchShortcut.launchProject(ClojureLaunchShortcut.java:108)
at ccw.editors.clojure.LoadFileAction$1.run(LoadFileAction.java:96)
at java.lang.Thread.run(Thread.java:722)






--
You received this message because you are subscribed to the Google Groups "counterclockwise" group.
To view this discussion on the web visit https://groups.google.com/d/msg/clojuredev-devel/-/GskM0dn7MTkJ.
To post to this group, send email to clojured...@googlegroups.com.
To unsubscribe from this group, send email to clojuredev-dev...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/clojuredev-devel?hl=en.

Dave Hartnoll

unread,
Oct 9, 2012, 7:36:28 AM10/9/12
to clojured...@googlegroups.com
Thanks for the quick reply. Grabbing the latest nREPL snapshot does indeed solve the ClassCastException issue. However, I now have a new Exception and I don't really want to spend time on it if it may be a result of not having the latest of everything again.

In the pasted console log below, the thing that seems odd to be is the port numbers. The server is started on port 64105 but then later port 64106 that is apparently closed and causing an Exception. The REPL of the running application says it is using 64106 and appears to work, so I'm not sure what's going on there. Also, opening a REPL to to ports 64105 or 64106 from either the development Eclipse or the running application all seem to work (it seems there are two ports open).

Maybe I'm out of my depth here (it always feels like that when looking at other software for the first time), or maybe this is something that needs to be solved to get to the bottom of the Namespace Browser issue. Maybe this is something I can ignore for now as it's due to the software being in an intermediate state of development. Once again, I'd appreciate a pointer so I don't spend too much time going down the wrong path.

Dave.

PS. I'm not seeing my own post in this group - does my membership/post need to be approved?

Here is the console output:

!SESSION 2012-10-09 10:43:03.383 -----------------------------------------------
eclipse.buildId=I20120608-1400
java.version=1.7.0_06
java.vendor=Oracle Corporation
BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=en_GB
Framework arguments:  -product org.eclipse.sdk.ide --launcher.XXMaxPermSize 1g
Command-line arguments:  -product org.eclipse.sdk.ide -data C:\workspaces\Counterclockwise/../runtime-Counterclockwise -dev file:C:/workspaces/Counterclockwise/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os win32 -ws win32 -arch x86_64 -consoleLog --launcher.XXMaxPermSize 1g

!ENTRY org.eclipse.core.resources 2 10035 2012-10-09 10:43:07.213
!MESSAGE The workspace exited with unsaved changes in the previous session; refreshing workspace to recover changes.
Warning: *optimize* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *optimize* or change the name.
Warning: *brackets-tags* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *brackets-tags* or change the name.
Warning: *commands* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *commands* or change the name.
Warning: *strict-commands* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *strict-commands* or change the name.
Warning: *configuration-based-commands* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *configuration-based-commands* or change the name.
Warning: *default-repl-port* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *default-repl-port* or change the name.
Warning: *ID* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *ID* or change the name.
Warning: *TARGET_ID* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *TARGET_ID* or change the name.
Leiningen Plugin start()
ccw.leiningen.util load starts
ccw.leiningen.util load starts
util namespace loaded
ccw.leiningen.classpath-container load starts
util namespace loaded
ccw.leiningen.classpath-container load starts
classpath-container namespace loaded
classpath-container namespace loaded

!ENTRY ccw.core 1 0 2012-10-09 10:43:42.300
!MESSAGE Started ccw nREPL server: nrepl://localhost:64105

!ENTRY ccw.core 1 0 2012-10-09 10:43:42.305
!MESSAGE Starting REPL with program args: -i "/C:/Users/dhartnoll/git/ccw/ccw.core/bin/ccw/debug/serverrepl.clj" -e "(require 'clojure.tools.nrepl.server)(do (clojure.tools.nrepl.server/start-server :ack-port 64105) nil)"  

!ENTRY ccw.core 1 0 2012-10-09 10:43:43.201
!MESSAGE Adding to project's classpath to support nREPL: [C:\eclipse_targets\ccw_third_party\tools.nrepl-0.2.0-20121004.224629-45.jar]
ERROR: Unhandled REPL handler exception processing message {:id 469273ac-b4c3-4124-b2df-8f1b47296757, :op ack, :port 64106}
java.net.SocketException: Socket closed
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:116)
at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at clojure.tools.nrepl.transport$bencode$fn__3384.invoke(transport.clj:103)
at clojure.tools.nrepl.transport.FnTransport.send(transport.clj:28)
at clojure.tools.nrepl.ack$handle_ack$fn__6363.invoke(ack.clj:42)
at clojure.tools.nrepl.server$handle_STAR_.invoke(server.clj:18)
at clojure.tools.nrepl.server$handle$fn__6432.invoke(server.clj:27)
at clojure.core$binding_conveyor_fn$fn__3713.invoke(core.clj:1817)
at clojure.lang.AFn.call(AFn.java:18)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)

!ENTRY ccw.core 1 0 2012-10-09 10:43:47.475
!MESSAGE Cannot handle REPL response: :ops{:ops {:clone {}, :close {}, :describe {}, :eval {}, :interrupt {}, :load-file {}, :ls-sessions {}, :stdin {}}, :session "edb7031a-8d27-436a-b3b2-412332888219", :status ["done"], :versions {:clojure {:incremental 0, :major 1, :minor 3}, :nrepl {:incremental "0", :major "0", :minor "2", :qualifier "SNAPSHOT"}}}

!ENTRY ccw.core 1 0 2012-10-09 10:43:47.478
!MESSAGE Cannot handle REPL response: :versions{:ops {:clone {}, :close {}, :describe {}, :eval {}, :interrupt {}, :load-file {}, :ls-sessions {}, :stdin {}}, :session "edb7031a-8d27-436a-b3b2-412332888219", :status ["done"], :versions {:clojure {:incremental 0, :major 1, :minor 3}, :nrepl {:incremental "0", :major "0", :minor "2", :qualifier "SNAPSHOT"}}}

Chas Emerick

unread,
Oct 9, 2012, 8:35:47 AM10/9/12
to counterclockwise
The "Socket closed" exception is expected.  That's what CCW's own nREPL server sees when the new project-specific nREPL server closes its connection to the former after ack-ing its port back.  I have a way to keep it from happening from within nREPL, but it's not been pushed up to github or deployed into a SNAPSHOT yet.  In any case, it's benign.

- Chas

To view this discussion on the web visit https://groups.google.com/d/msg/clojuredev-devel/-/9HSG_O0TgcEJ.

Dave Hartnoll

unread,
Oct 9, 2012, 9:08:47 AM10/9/12
to clojured...@googlegroups.com
OK, thanks. That's sort of what I wanted to hear (I can ignore it). There's just enough extra info to keep me intrigued though :-)

Dave.

Laurent PETIT

unread,
Oct 9, 2012, 9:26:35 AM10/9/12
to clojured...@googlegroups.com
Hello Dave,

Please also note that the way repls are started is subject to change as soon as we add lein's :nrepl support.

2012/10/9 Dave Hartnoll <dave.h...@gmail.com>
--
You received this message because you are subscribed to the Google Groups "counterclockwise" group.
To view this discussion on the web visit https://groups.google.com/d/msg/clojuredev-devel/-/l_dpe-Ys6BcJ.
Reply all
Reply to author
Forward
0 new messages