How do I start Hunchentoot? - lisp

How do I start Hunchentoot on a project? I looked over Edi Weitz's guide and everything went smoothly until after installation. The listed tutorials were either broken or skimmed over actual server usage.
I have my asdf file, installed dependencies with quicklisp, and set up a dispatch table. How do I get Hunchentoot to work with this stuff?

To update, I've improved upon Svante's answer:
(defun start-server ()
(stop-server)
(start (setf *acceptor*
(make-instance 'easy-acceptor
:port 4242))))
(defun stop-server ()
(when *acceptor*
(when started-p *acceptor*
(stop *acceptor*))))
Prior to starting the server, acceptor is nil. After the server has been started (even if it has subsequently been stopped) it is no longer nil. The started-p test checks to see if an initialized easy-acceptor is started. If you try to stop an already stopped acceptor, you receive an error.

You invoke start on an instance of an acceptor.
If you use the basic easy-handler mechanism that comes with hunchentoot, that would be an easy-acceptor.
You will want to have a mechanism in place to start and stop your server. That might look like this:
(defvar *acceptor* nil)
(defun start-server ()
(stop-server)
(start (setf *acceptor*
(make-instance 'easy-acceptor
:port 4242))))
(defun stop-server ()
(when *acceptor*
(stop *acceptor*)))

(start (defparameter hunchentoot-listener
(make-instance 'easy-acceptor
:port 4242
:document-root #p"/path/to/your/html/")))
will get you a running web server on port 4242 (http://localhost:4242/)

Related

Emacs+Slime inferior-lisp exited abnormally with code 5

I try to install slime in emacs. I follow many manuals and got one oucome.
"M-x slime" trow exeption "process inferior-lisp exited abnormally with code 5"
OS Windows 8.1
GNU Emacs 26.1 (build 1, x86_64-w64-mingw32) of
2018-05-30
SBCL 1.4.2
SLIME 2.22
My .emacs file text
(setq inferior-lisp-program "C:/SBCL/sbcl.exe")
(add-to-list 'load-path "C:/slime/")
(require 'slime)
Following the comment, I tried to understand where the installation falls
-(load #P"C:/slime/swank-loader")
-T
-(swank-loader::init :reload t)
-WARNING: redefining EMACS-INSPECT (#(SB-PCL:SYSTEM-CLASS COMMON-LISP:T)) in DEFMETHOD
NIL
-(swank:create-server :port 7777)
;;Swank started at port:7777
In Emacs
-M-x slime-connect
Host: localhost
Port: 7777
-Lisp connection closed unexpectedly: connection broken by remote peer
In other topics where i saw that error message, peoples run complex sourcecode with mistakes. The problem was solved by correcting errors. It seems like different situation or i don't understand something.
This is too long for a comment.
You need to find out at which layer the problem occurs. Try for example to run SBCL in a shell with the same command-line (e.g. C:/SBCL/sbcl.exe); if it works, in the REPL:
CL-USER> (load #P"C:/slime/swank-loader")
If that works, you can manually init the swank backend (the Common Lisp part of the Slime/Swank protocol).
CL-USER> (swank-loader::init :reload t)
Then, try to start a server (the port value is arbitrary):
CL-USER> (swank:create-server :port 7777)
If a server starts, you can try to run slime-connect from Emacs, using the localhost port and the same port.
Oleg, try to give ip address 127.0.0.1 instead of localhost when doing slime-connect. I have similar problem on OSX when connecting to a remote SLIME server.

Why won't can't I read from my usocket using usocket::socket-receive?

I'm learning common-lisp, and I'm trying to write a dumb chat program using a client and server tcp socket connection using the usocket library. Below is my function.
(defun receive-thread (socket)
(block receiver-nested-loop
(loop
(let ((ready-socket (usocket::wait-for-input socket)))
(let ((return-buffer (usocket::socket-receive ready-socket nil nil)))
(if (not (eq return-buffer :eof))
(handle-received-data return-buffer)
(return-from receiver-nested-loop)))))))
I'm doing simple test runs in 2 terminals, I am calling the (main) function manually (I know how to compile and script this).
In the first (replace x's with my ip address): sbcl --load chat.lisp -a xxx.xx.xxx.xx -s
In the second: sbcl --load chat.lisp -a xxx.xx.xxx.xx
When my program gets to the above function I get the following error:
debugger invoked on a SIMPLE-ERROR in thread
#<THREAD RUNNING {10069DF743}>:
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION USOCKET:SOCKET-RECEIVE (1)>
when called with arguments
(#<USOCKET:STREAM-SERVER-USOCKET {10069DF673}> NIL NIL).
Here is the pastebin for my complete code.
Can someone help me figure out what I've done wrong and what I need to do to fix it?
EDIT: Removed extra ':'s in the program and retested. The behavior and error remains the same. All the function calls are exported symbols, I just did it out of c++ instincts.
The error you posted hints that you're using usocket:socket-receive incorrectly (slightly cleaned up):
There is no applicable method for the generic function
USOCKET:SOCKET-RECEIVE
when called with arguments
USOCKET:STREAM-SERVER-USOCKET
Documentation for this function says that usocket:socket-receive will "receive data from a datagram socket". I suspect the socket you're trying to read is TCP socket and not a UDP socket.

Inspect state atom which gets updated by a ring handler

Consider the following scenario:
A minimal boot task starts up a http server:
(boot (serve :handler 'myapp.server/handler
:port 3000))
(This might be launched in several ways, here it's ok to just run it from a nrepl session, e.g. started by boot repl from the terminal)
The handler is represented by the function handler inside the namespace myapp.server. The corresponding file looks like this:
(ns myapp.server (:require ...))
(defonce server-state (atom {:nr 0}))
(defn handler [req]
(prn (swap! server-state update :nr inc))
{:body "Answer.\n"})
This works, every time the address localhost:3000 is visited the the atom is updated and the new version is printed to stdout inside the repl.
How can the atom been inspected at any time?
boot.user=> #myapp.server/server-state
yields an error. (...no such var...)
When trying the same thing from within an emacs cider nrepl connection, this previous attempt always shows up the initial value of the atom: {:n 0}
UPDATE
Here are the exact steps I do when using emacs/cider:
cd projectdir
start emacs
cider-jack-in
(boot (dev))
Ctrl+C+C (in order to get a prompt again.)
Then Testing with curl: getting responses + inside emacs updated atom is logged: {:n 1} .. {:n 2} ..
Then, in the repl: (require 'myapp.server), takes a while: nil.
finally: #myapp.server/state --> however: {:n 0}
Your (...no such var...) error probably happens because you haven't require the myapp.server namespace. Attempts to see updates happening to your atom in CIDER REPL fail probably because your ring app runs in another JVM process than your REPL so the REPL sees only initial value as updates from ring handler happen in another JVM or it is enclosed in a separated classloader as it might be isolated by boot POD.
You have two options:
start your ring app with REPL server enabled and connect to it from another process (for example by using Server Socket REPL and connecting to it using telnet)
start your REPL and then start your ring app from it and you have access to all your loaded namespaces.
With the first approach you probably need to use boot-clj's nrepl option. When you configure it to start nREPL server then you can connect to it using boot repl -c (optionally providing the same coordinates as to boot-http nrepl options) or directly from CIDER using cider-connect.

Connecting to DBus from emacs daemon

I recently tried to set up AucTeX SyncTeX with evince under GNU Emacs 24.4. From an ordinary emacs session it work oput of the box after activating TeX-source-correlate-mode, but under my standard Daemon session Dbus refuses to work properly. TeX-Evince-sync-view fails with a DBus 'no conncetion' error, so I tried M-: (dbus-init-bus :system) but that returns ((:signal :system "org.freedesktop.DBus.Local" "Disconnected") (nil "/org/freedesktop/DBus/Local" dbus-handle-bus-disconnect))
and M-: dbus-init-bus :session fails accordingly with 'no connection'.
Does anyone know how to get DBus running properly under Emacs in Daemon mode?
When you connect to D-Bus from Emacs, it must know where the respective dbus-daemon resides. Usually, it knows it via the environment variable $DBUS_SESSION_BUS_ADDRESS. So set this variable in your daemonized Emacs before you call (dbus-init-bus :session) or alike

No logging for a Clojure app deployed as a WAR to Jetty

I built a WAR file and deploy to Jetty 9 with these WAR-making and deployment steps, which is an adaptation from Pedestal's suggestions. This process has worked for me in the past, but at present, Jetty will not start the application.
I also cannot find any useful logs. This is my main problem. I have looked in these places:
/var/log/jetty/current tells me only this:
2014-03-29_16:23:24.058:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext#181d4997{/,file:/tmp/jetty-0.0.0.0-8080-myapp.war-_-myapp.domain.com-5203978721479585979.dir/webapp/,AVAILABLE,myapp.domain.com}{/opt/myapp/myapp.war}
2014-03-29_16:23:24.14610 2014-03-29 16:23:24.126:INFO:oejs.ServerConnector:main: Started ServerConnector#5cb1d518{HTTP/1.1}{0.0.0.0:8080}
/opt/jetty/logs - contains no files at all
/opt/myapp - contains myapp.war but no logs
I also tried adding -DDEBUG=true -Dorg.eclipse.jetty.LEVEL=DEBUG to my Jetty JVM options at start-up, but the extra logging in /var/log/jetty/current didn't tell me what went wrong with the WAR file launch.
Although logging works in development (e.g. with lein run-dev), I would not be surprised if I have made some kind of mistake with my logging configuration. I'm using the standard logback.xml provided by the Pedestal service template.
With regards to the underlying application error, I have some guesses there too. It is most likely due to recent changes in the application dependencies (I added Datomic) or connecting to Datomic at start-up.
Here is my my project.clj:
(defproject myapp-service "0.1.0-SNAPSHOT"
:description "A web app"
:url "http://myapp.domain.com"
:dependencies
[[org.clojure/clojure "1.6.0"]
[org.clojure/tools.reader "0.8.3"]
[com.datomic/datomic-pro "0.9.4699"
:exclusions [org.slf4j/slf4j-api org.slf4j/slf4j-nop commons-codec]]
[io.pedestal/pedestal.service "0.2.2"
:exclusions [com.fasterxml.jackson.core/jackson-core]]
[io.pedestal/pedestal.service-tools "0.2.2"
:exclusions [com.fasterxml.jackson.core/jackson-core]]
[enlive/enlive "1.1.5"]
[validata "0.1.5"]]
:repositories
{"my.datomic.com"
{:url "https://my.datomic.com/repo"
:username "email#domain.com"
:password "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}}
:profiles
{:dev
{:source-paths ["dev"]
:dependencies
[[io.pedestal/pedestal.jetty "0.2.2"]]}}
:min-lein-version "2.0.0"
:resource-paths ["config", "resources"]
:aliases
{"run-dev" ["trampoline" "run" "-m" "myapp-service.server/run-dev"]}
:repl-options
{:init-ns user
:init
(try
(use 'io.pedestal.service-tools.dev)
(require 'myapp-service.service)
; HACK: Allow referencing non clojure.core symbols in :init
(eval '(init myapp-service.service/service
#'myapp-service.service/routes))
(catch Throwable t
(println "ERROR: There was a problem loading"
"io.pedestal.service-tools.dev")
(clojure.stacktrace/print-stack-trace t)
(println)))
:welcome (println
"Welcome to pedestal-service!"
"Run (tools-help) to see a list of useful functions.")}
:main ^{:skip-aot true} myapp-service.server)
So, to restate my main question, how do I get logging to work? Everything else will follow from that.
Embarrassingly, my issue was DNS. Logging is fine.