Beginner question on Exception handling


#1

I am trying to make this snippet of code work but I am failing to do it. I want to catch any exception thrown by calling main from lein run port_number for example when port_number is already in use:

(ns clj-noob.core
  (:gen-class)
  (:require [ring.adapter.jetty :as jetty]))

(defn -main
  [port-number]
  (try
    (jetty/run-jetty
     (fn [request]
       (println request)
       {:status  200
        :body    "<h1>Hello, Clojure World</h1>  <p>Welcome to your first Clojure app.  This message is returned regardless of the request, sorry</p>"
        :headers {}})
     {:port (Integer. port-number)})
    (catch Exception e (.getMessage e))))

The Exception is not caught and the backtrace is printed on the console:

2018-10-21 13:39:26.670:INFO::main: Logging initialized @841ms
2018-10-21 13:39:26.680:INFO:oejs.Server:main: jetty-9.2.10.v20150310
2018-10-21 13:39:26.694:WARN:oejuc.AbstractLifeCycle:main: FAILED Se[email protected]{HTTP/1.1}{0.0.0.0:8080}: java.net.BindException: Address already in use
java.net.BindException: Address already in use
	at sun.nio.ch.Net.bind0(Native Method)
	at sun.nio.ch.Net.bind(Net.java:433)
	at sun.nio.ch.Net.bind(Net.java:425)
	at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
	at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
	at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:321)
	at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:80)
	at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:236)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.server.Server.doStart(Server.java:366)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at ring.adapter.jetty$run_jetty.invokeStatic(jetty.clj:127)
	at ring.adapter.jetty$run_jetty.invoke(jetty.clj:94)
	at clj_noob.core$_main.invokeStatic(core.clj:8)
	at clj_noob.core$_main.invoke(core.clj:5)
	at clojure.lang.Var.invoke(Var.java:384)
	at user$eval140.invokeStatic(form-init8591901165092636940.clj:1)
	at user$eval140.invoke(form-init8591901165092636940.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:7172)
	at clojure.lang.Compiler.eval(Compiler.java:7162)
	at clojure.lang.Compiler.load(Compiler.java:7631)
	at clojure.lang.Compiler.loadFile(Compiler.java:7569)
	at clojure.main$load_script.invokeStatic(main.clj:349)
	at clojure.main$init_opt.invokeStatic(main.clj:351)
	at clojure.main$init_opt.invoke(main.clj:351)
	at clojure.main$initialize.invokeStatic(main.clj:382)
	at clojure.main$null_opt.invokeStatic(main.clj:416)
	at clojure.main$null_opt.invoke(main.clj:413)
	at clojure.main$main.invokeStatic(main.clj:495)
	at clojure.main$main.doInvoke(main.clj:458)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:705)
	at clojure.main.main(main.java:37)
2018-10-21 13:39:26.694:WARN:oejuc.AbstractLifeCycle:main: FAILED [email protected]: java.net.BindException: Address already in use
java.net.BindException: Address already in use
	at sun.nio.ch.Net.bind0(Native Method)
	at sun.nio.ch.Net.bind(Net.java:433)
	at sun.nio.ch.Net.bind(Net.java:425)
	at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
	at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
	at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:321)
	at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:80)
	at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:236)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.server.Server.doStart(Server.java:366)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at ring.adapter.jetty$run_jetty.invokeStatic(jetty.clj:127)
	at ring.adapter.jetty$run_jetty.invoke(jetty.clj:94)
	at clj_noob.core$_main.invokeStatic(core.clj:8)
	at clj_noob.core$_main.invoke(core.clj:5)
	at clojure.lang.Var.invoke(Var.java:384)
	at user$eval140.invokeStatic(form-init8591901165092636940.clj:1)
	at user$eval140.invoke(form-init8591901165092636940.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:7172)
	at clojure.lang.Compiler.eval(Compiler.java:7162)
	at clojure.lang.Compiler.load(Compiler.java:7631)
	at clojure.lang.Compiler.loadFile(Compiler.java:7569)
	at clojure.main$load_script.invokeStatic(main.clj:349)
	at clojure.main$init_opt.invokeStatic(main.clj:351)
	at clojure.main$init_opt.invoke(main.clj:351)
	at clojure.main$initialize.invokeStatic(main.clj:382)
	at clojure.main$null_opt.invokeStatic(main.clj:416)
	at clojure.main$null_opt.invoke(main.clj:413)
	at clojure.main$main.invokeStatic(main.clj:495)
	at clojure.main$main.doInvoke(main.clj:458)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:705)
	at clojure.main.main(main.java:37)
2018-10-21 13:39:26.695:INFO:oejs.ServerConnector:main: Stopped [email protected]{HTTP/1.1}{0.0.0.0:8080}

What I am doing wrong here ?
Thanks !


#2

Binding exception was caught by internal Jetty handler and was logged to console. I think you should check Jetty docs to make it works for you (and remember to stop Jetty instances before start another one on same port). Also look at this article [https://8thlight.com/blog/mike-knepper/2015/05/19/handling-exceptions-with-middleware-in-clojure.html] to handle exceptions with middleware.