Description
Environment
Attachments
- clj-1671-13.patch10 Sep 2015, 12:26 AM
- clj-1671-12.patch05 Sep 2015, 07:42 AM
- clj-1671-11.patch26 Aug 2015, 06:37 AM
- clj-1671-10.patch26 Aug 2015, 12:51 AM
- 26 Aug 2015, 12:14 AM
- 20 Aug 2015, 06:27 AM
- 14 Aug 2015, 04:15 PM
- 09 Jul 2015, 12:17 AM
- 03 Jul 2015, 04:39 AM
- 14 Mar 2015, 02:29 AM
- 13 Mar 2015, 03:06 AM
- 12 Mar 2015, 02:31 AM
Activity
Alex Miller August 20, 2015 at 6:27 AM
Oh, and I got rid of the use of getLoopbackAddress() so this works in jdk 1.6.
Alex Miller August 15, 2015 at 12:43 AM
Oh sorry, I thought you were just confirming what was already there - the current patch does execute a require for the namespace containing the accept function.
Laurent PETIT August 15, 2015 at 12:08 AM
Sure, I know this is WIP, and that's why I find it valuable to add my 2 cents now, rather that when things are almost wrapped up.
So it will be triggered not by the fact that clojure.main is invoked, but during the initialization of the clojure runtime ?
Then it seems indeed difficult to ask to wait for clojure.main to have finished starting.
My first remark still stands, though:
the fully qualified var symbol String passed as value of `:accept` parameter should not require that its namespace be already loaded, or this will really limit to choice of vars that can be passed on. Some dynamic `require` call and var `resolve` should be taking place here.
Alex Miller August 14, 2015 at 11:11 PM
Hey Laurent,
Keep in mind this is a work in progress still. The idea here is that you can pass these system properties when running ANY Clojure program. The Clojure runtime will scan system properties and start socket servers as needed (that hook is not yet installed).
So you can do clojure.main if you like but if you're passing the server system properties the socket server will be launched. I have not determined yet exactly where that RT loading will happen but I would expect it to be prior to the -i or -e being evaluated.
Laurent PETIT August 14, 2015 at 7:09 PM
Just to check, I'd like to understand if we share the same detail view of how the `:accept` key will work.
Its default value is `clojure.repl/repl`.
I expect to be able to specify a value like `my.not.yet.loaded.namespace/my-repl-fn` and that the server code will try to require `my.not.yet.loaded.namespace` from the java classpath.
Also, when will the resolution of `:accept` take place? Before or after all the -e and -i expressions / files have been evaluated? That is, will it be possible to load `my.not.yet.loaded.namespace` via a -i option or in the list of files to load, instead of having to tweak the classpath? (Some tools / IDEs abstracting away the notion of classpath, program arguments, jvm parameters make it difficult if possible at all to tweak the classpath, but really easy to add JVM parameters / program arguments before launching.
Programs often want to provide REPLs to users in contexts when a) network communication is desired, b) capturing stdio is difficult, or c) when more than one REPL session is desired. In addition, tools that want to support REPLs and simultaneous conversations with the host are difficult with a single stdio REPL as currently provided by Clojure.
Tooling and users often need to enable a REPL on a program without changing the program, e.g. without asking author or program to include code to start a REPL host of some sort. Thus a solution must be externally and declaratively configured (no user code changes). A REPL is just a special case of a socket service. Rather than provide a socket server REPL, provide a built-in socket server that composes with the existing repl function.
For design background, see: http://dev.clojure.org/display/design/Socket+Server+REPL
Start a socket server by supplying an extra system property (classpath and clojure.main here, but this would generally be starting your own app instead - we won't use the repl it starts):
java -cp target/classes -Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" clojure.main
where options are:
address = host or address, defaults to loopback
port = port, required
accept = namespaced function to invoke on socket accept, required
args = sequential collection of args to pass to accept
bind-err = defaults to true, binds err to out stream
server-daemon = defaults to true, socket server thread doesn't block exit
client-daemon = defaults to true, socket client threads don't block exit
Run a repl client using telnet:
$ telnet 127.0.0.1 5555 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. user=> (println "hello") hello nil user=> clojure.core.server/*session* {:server "repl", :client "1"} user=> (ns foo) nil foo=> (+ 1 1) 2 foo=>
Patch: clj-1671-13.patch