Clojure: Casting to a Java class...or not!
I have a bit of Java code for working out the final destination of a URL assuming that there might be one redirect which looks like this:
private String resolveUrl(String url) {
try {
HttpURLConnection con = (HttpURLConnection) (new URL(url).openConnection());
con.setInstanceFollowRedirects(false);
con.connect();
int responseCode = con.getResponseCode();
if (String.valueOf(responseCode).startsWith("3")) {
return con.getHeaderField("Location");
}
} catch (IOException e) {
return url;
}
return url;
}
I need to cast to HttpURLConnection on the first line so that I can make the call to setInstanceFollowRedirects which isn’t available on URLConnection.
I wanted to write some similar code in Clojure and my first thought was that I needed to work out how to do the cast, which I didn’t know how to do.
I then remembered that Clojure is actually dynamically typed so there isn’t any need - as long as the object has the method that we want to call on it everything will be fine.
In this case we end up with the following code:
(defn resolve-url [url]
(let [con (.. (new URL url) openConnection)]
(doall
(.setInstanceFollowRedirects con false)
(.connect con))
(if (.startsWith (str (.getResponseCode con)) "3")
(.getHeaderField con "Location")
url)))
Which can be simplified to this:
(defn resolve-url [url]
(let [con (doto (.. (new URL url) openConnection)
(.setInstanceFollowRedirects false)
(.connect))]
(if (.startsWith (str (.getResponseCode con)) "3")
(.getHeaderField con "Location")
url)))
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.