By Developers, For Developers

Historical errata for Web Development with Clojure, Second Edition

PDF PgPaper PgTypeDescriptionFixed onComments
93TYPO

Prismatic schema is now at the plumatic github account with the plumatic name

2016-02-02
10ERROR

The displayed test code is what was there by default, not updated to reflect the guestbook application.

2016-02-06
8SUGGEST

“We’d like to be able to save
messages in our database, so we’ll create a function called save-message!.
Note that the function ends with ! to indicate that it mutates data. The second
function will be used to retrieve currently stored messages and we’ll call it
get-messages.”

There is no detail about where(which file) to create these functions. So, it will cause problem on page 9,
“;;check if we have any existing data
(get-messages)
;;output: ()”

2016-02-06I've updated the wording, I guess the part that's not clear is that the functions are generated automatically given the query names in the SQL file.
2TYPO

“source file namedcore.clj” missing a space, should be “source file named core.clj”

2016-02-06
3TYPO

Although copy/paste shows it correctly as “its name is myapp.core”, in the PDF (and epub) it looks like there is a missing space between “is” and “myapp.core”.

2016-02-06
5ERROR

The web page screen capture says “lein ragtime migrate” but the command is shown on page 7 as “lein run migrate”.

2016-03-14
8SUGGEST

“as seen in the sample queries” should be “as shown in the sample queries”.

2016-02-06
9TYPO

“points to the value of the :databse-url environment variable”

“:databse-url” should be “:database-url”

2016-02-06
12SUGGEST

“dynamic content that will be injected in our template”

“in” should be “into”

2016-02-06
13SUGGEST

“create a li item”

change “a” to “an” (because most people will pronounce li as ell eye)

2016-03-16
13TYPO

“we’ll add references the guestbook.db.core”

missing “to” after “references”

2016-02-06
13ERROR

“We’ll create another div that will contain a field to hold any error messages
that might be populated by the server …”

Did I miss it? I didn’t see that div and field for the error messages in the snippet or final home.html (on page 14).

2016-03-14
71SUGGEST

“errors-component” and modification to “send-message!” code is not displayed until 2 pages down, which feels disjointed

2016-03-16
13SUGGEST

“We’ll then iterate the messages and create a li item for each message inside a ul tag.”

This falls wrong upon my ear. The messages are not actually iterated. The messages are shown just once. The usual idiom for this type of situation is “iterate over”, as shown below:

“We’ll then iterate over the messages and create a li item for each message inside a ul tag.”

The same problem occurs on page 49 (“if we pass in a collection we can iterate it”), page 225 (“When you need to iterate a collection”), and page 228 (“since we have to iterate our
sequence each time”).

2016-03-05
18SUGGEST

“The result of the validate function is a vector where the first parameter”

“parameter” should be “element”

2016-02-06
19SUGGEST

“Flash session variables have lifecycle of a single request”

“have lifecycle of” should be “have a lifespan of”

2016-02-06
23ERROR

“that the user can assemble in a way that best fits their particular application”

“their” should be “his”

If this offends the gender police, “their” could be replaced with “his or her”.

Alternatively, the pronoun could be eliminated:

“that can be assembled in a way that best fits a particular application”

or “user” could be made plural:

“that the users can assemble … fits their …”

2016-02-06
24TYPO

“Ring adapters for the Java HTTP Servlet application programming interface
(API), 3 allow applications to be deployed on any servlet container, such as
Jetty or Tomcat.”

The first comma (after “(API)”) should be omitted.

“to run Clojure applications as standalone using …”

“as standalone” should be “standalone”

2016-02-06
29ERROR

“This is necessary to ensure that when the Var object containing the
current handler function is returned.”

This is not a complete sentence. Perhaps “when” should be omitted? As it is, the meaning is not clear.

2016-02-06
79TYPO

“Finally, we’ll create the add-message! function”
but the function name in the code is “handle-message!”

2016-02-06
20TYPO

In the chapter ‘Creating Tests’, the text says ‘The current tests are defined with the generated users table in mind. Since we’ve changed our table structure, we’ll replace it with the following test instead’ but the code is actually the generated code not the code that should be used instead.

2016-02-06
85TYPO

The cljs code for “ws/connect!” is not in the book.

2016-02-06
89TYPO

“Finally, we’ll have to update the routes to use the ring-ajax-get-or-ws-handshake
and the ring-ajax-post functions…”

the code for this is not shown.

2016-02-06
12ERROR

The example test, which the text states is a replacement for the one generated by the template, is exactly a copy of the test generated by the template. It refers to the original user table, which we removed in the preceding pages.

2016-03-05
49ERROR

The DB test example is the same of the generated with the table users, and not the correct tests with the table GuestBook.

2016-02-13
238SUGGEST

The fourth paragraph describes the backtick. I had to read the explanation for the backtick, “This is the opposite of unquoting…” several times. Eventually, I agreed that the description was accurate, but it seems such a different way of explaining syntax quote compared to other explanations.

2016-03-17I couldn't think of a succinct way to reword this, hopefully won't cause too much confusion :)
10-11ERROR

Test case in book is still the default generated test-users code. When trying to adapt based on the current structure, I ran into a couple of issues: The auto increment makes it difficult to test the return value; the java.uitl.Date. stored does not have the same value after passing through the H2 database.

2016-03-09
73ERROR

On the “guestbook-validation/resources/templates/home.html” code, the post action is incorrect. The correct is `“

2016-02-09
39TYPO

“The core namespaces that will be present in a Luminus applications are as follows:”

should likely be

“The core namespaces that will be present in a Luminus application are as follows:”

though something like

“A Luminus application is typically comprised of the following core namespaces:”

may work better.

2016-02-13
40ERROR

The second fragment of “guestbook/src/guestbook/core.clj” at the bottom of the page simply shows “start-app” all over again - the “stop-app” function should be listed here.

2016-02-13
41ERROR

The code fragment listed under “guestbook/src/guestbook/handler.clj” is actually now part of the “luminus.logger” namespace.

“github.com/luminus-framework/luminus-log4j/blob/master/src/luminus/logger.clj”

The matching code in the handler.clj is simply “(logger/init env)”.

2016-02-13
36TYPO

I think this is a typo:

(GET “/:foo” {{value “name”} :params}
(str “The value of name is ” value))

It instead should be

(GET “/:foo” {{value :name} :params}
(str “The value of name is ” value))

2016-02-13
42TYPO

“that” instead of “tha” in the following sentence:

“It also adds the ring-defaults middleware tha we dis-
cussed earlier along with wrap-webjars for serving static assets from the WebJars
repository.”

2016-02-13
53TYPO

“For example, should we try to run the following code then we’ll
get an exception informing us that uppercases is not a valid tag.
(selmer/render ”{{content|safea}}" {})"

presumably this should be something like

“For example, should we try to run the following code then we’ll
get an exception informing us that the tag contains an invalid filter safea.”

2016-02-13
53TYPO

“If you’ll recall from the last chapter, middleware function accept a handler
function as a parameter and returns a function that accepts the request map.”

should be

“If you’ll recall from the last chapter, middleware functions accept a handler
function as a parameter and return a function that accepts the request map.”

or

“If you’ll recall from the last chapter, a middleware function accepts a handler
function as a parameter and returns a function that accepts the request map.”

2016-02-13
10ERROR

I believe that using the following terminology is discouraged for new code:
(use ’guestbook.db.core)
in favor of
(require [’guestbook.db.core :refer :all])

Particularly in a book for relative newcomers to clojure, it would probably be better to use the require form.
The system doesn’t allow links, so if you google ‘clojure libs and namespaces’, the top link has more info.

2016-03-09
126TYPO

As we are continuing the repl session from before the db is the conn variable thus before running the (read-employees) query you need to run
(conman/bind-connection db “sql/queries.sql”)
not
(conman/bind-connection conn “sql/queries.sql”)

2016-02-13
16ERROR

The following code leads to an exception:

(defn save-message! [{:keys [params]}]
(db/save-message!
(assoc params :timestamp (java.util.Date.)))
(response/redirect “/”))

The exception is:
java.lang.RuntimeException: No such var: response/redirect, compiling:(guestbookp/routes/home.clj:16:3)

the namespace declarations seems to be ok:
(ns guestbookp.routes.home
(:require [guestbookp.layout :as layout]
[compojure.core :refer [defroutes GET POST]]
[guestbookp.db.core :as db]
[ring.util.http-response :as response]
))

If we replace “response/redirect” with “response/found”, it compiles ok

2016-02-13
144ERROR

Can’t run the register! function in the repl due to the wrong number of args being supplied as it seems the destructuring done in the args needs a session.

2016-02-13
58ERROR

The code snippets for running the render and render-file functions in the REPL should be prefixed with “selmer/”, as they are on the previous page.

2016-02-13
60TYPO

The sentence “First, we’ll define our base template called base.html and place it in the resources folder along side the home.html template we already have” refers to home.html, but the template we already have is called hello.html.

2016-02-13
62ERROR

There seems to be a mismatch between the sentence:

“For example, should we try to run the following code then we’ll get an exception informing us that uppercases is not a valid tag”

and the code snippet:

“(selmer/render ”{{content|safea}}" {})"

2016-02-13
63ERROR

In order to use the “wrap-error-page” function from selmer.middleware, we must first :require selmer.middleware. There is no mention of that in the text.

2016-03-09
75ERROR

On page 75 the bottom code snippet refers to the “/add-message” route. However, as far as I can tell, the route which was created in chapter one is actually called “/message”. This problem reoccurs in the following pages as well.

2016-03-09
148TYPO

The components namespace is imported as “c”
[picture-gallery.components.common :as c])

but the modal is used in the code block below as just “modal” not “c/modal”

2016-02-13
150TYPO

component is defined as “registration-form” but called in page function as
“r/registration-form-example” it should be called as “r/registration-form”

2016-02-13
151TYPO

Registration is misspelled in picture of modal.

2016-03-17
150 TYPO

the require statement [picture-gallery.components.registration :as r] conflicts with the already existing [reagent.core :as r] and anyways is used later on page 156 as “reg/” in reg/registration-button

2016-02-13
77ERROR

In the final code snippet on page 77, the save-message! function is updated to return JSON, rather than redirecting. However, the error messages shown on page 76 and earlier on page 77 are already in JSON format, as though that change had already been made.

2016-03-16
16TYPO

The title (address) of the code fragment is incorrect:
guestbook-validation/src/guestbook/routes/home.clj
should be
guestbook/src/guestbook/routes/home.clj

2016-03-14
10SUGGEST

Creating Tests

If you want to demo the testing facility, you may want to do it before you set up guestbook.

I finally got the guestbook test to work, but it would only test successfully after I deleted the test database manually to reset the auto-increment counter back to 1 or maybe 0. Couldn’t find a way to reset the test database on a quick look through luminus documentation.

If you do want to adapt the test to the guestbook messages example, would you cover the reason why an extra argument was required for db/getmessages to make the test run. I ended up using (db/get-messages {} {:connection t-conn}).

2016-03-09This is mostly a problem with the H2 implementation that doesn't rollback the sequence increment when the transaction is rolled back. I updated the tests to avoid the issue.
141TYPO

“We’ve already looked at handling input validation using the Buddy
library when we worked on the guestbook application in Chapter 2…”

chapter 2 covered Bouncer, not Buddy

2016-02-13
149TYPO

The code for the modal component was already displayed earlier and the code for text-input and password-input is missing

2016-02-13
64TYPO

“syntactic sugar” rather than “syntax sugar”

“Reagent also provides syntax sugar for collapsing nested tags into a single
tag.”

should be

“Reagent also provides syntactic sugar for collapsing nested tags into a single
tag.”

2016-02-13
68TYPO

Not sure whether this relates to my particular project setup or whether the luminus project template has been (recently) updated. So just in case - instead of the indicated 403 “Forbidden” error status I am getting “POST localhost:3000/add-message 404 (Not Found)”.

2016-03-09It sounds like you don't have a route with the URI /add-message in your app. The 404 error indicates that the server couldn't find the specified route.
9TYPO

“The function name is specified using the –name: comment”

In B1, the above had two hyphens preceding “name”, which I believe is correct (as that is how it is shown in the queries.sql file below that paragraph).

In B2, the two hyphens have become an en dash or em dash.

2016-03-14
14TYPO

“create a li item”

change “a” to “an” (because most people will pronounce li as ell eye)—Frank Sergeant

2016-03-05
20TYPO

“Flash session variables have lifespan of a single request”

“have lifespan” should be “have a lifespan”

2016-03-05
35TYPO

“We already saw some examples of routing using Compojure when we built
our first application in the Chapter 1, Getting Your Feet Wet, on page 1, now
let’s take a closer look at the functionality it provides.”

“in the Chapter 1” should be “in Chapter 1”

2016-03-05
41TYPO

“using Selmer HTML templating engine.”

“using” should be “using the”

2016-03-05
42TYPO

“the compiled bytecode is emitted in the
resulting jar archive”

“in” should be “into”

2016-03-05
42TYPO

“the mode that
application runs in”

“that application” should be “that the application”

2016-03-05
43TYPO

“The profiles in the project.clj are responsible”

“in the project.clj” should be “in project.clj”

2016-03-13
44SUGGEST

“There are two functions that control the lifecycle of the application, these are
the start-app and the stop-app functions respectively.”

I don’t think “respectively” is needed or that it adds anything.

The sentence could be changed around a bit, such as

“The two functions that control the lifecycle of the application are
start-app and stop-app.”

2016-03-05
45TYPO

“is managed by the mount library. 2 .”

(The 2 is a superscript.) There are too many periods. The period after the superscript should be removed.

2016-03-05
45SUGGEST

“Had we
wrapped these routes directly with (middleware/wrap-csrf home-routes) then the wrap-
csrf would end up being applied to any routes defined below home-routes as it’s
now part of the common middleware chain.”

I didn’t understand this. Perhaps an example would help?

2016-03-13
47SUGGEST

“The routes package
in our application is reserved for the namespaces that describe these
workflows.”

I think this is the first use of the term “package” in the book. If this has a technical meaning in Clojure, perhaps it should be defined here? Is this Java terminology (“package” equivalent to “namespace”?) that has crept in accidentally?

2016-03-14The wording of namespace to house namespaces seemed a bit awkward, and I thought the word package would get the meaning across. However, I'll just reword this to keep it consistent if it's causing confusion.
47TYPO

“This ensures that we’re not hardcoding our connection in the application
or checking into the code repository.”

“checking into” should be “checking it into”

2016-03-05
48TYPO

“The application will read the environment variable when it starts up and use
it as to connect to the database.”

“use it as to” should be “use it to”

2016-03-05
49SUGGEST

“Alternatively, we may wish to front multiple applications using a server such
as Apache or Nginx.”

I’m concerned about the use of the word “front”.

I think I understand what you mean but I it sounds awkward to me. Perhaps it could be reworded?

2016-03-17Thanks for the suggestion, unfortunately I couldn't really think of anything else that would be better. Hopefully it won't be terribly confusing, I was under the impression that this was fairly common terminology.
49TYPO

“This allows running multiple applications without having to setup
subdomains for each one.”

“setup” should be “set up” (since it is used as a verb)

2016-03-05
49SUGGEST

“Similarly to the tag above it, a filter is added …”

This sounds awkward. How about this:

“Next, a filter is added …”

2016-03-05
51SUGGEST

“In this book we’ll primarily focus on using Selmer for server side templates.
Later on we’ll also see how to write single-page applications where most of
the templating is done on the client. 9 This approach nicely separates your
application’s client and server components. It also facilitates using other
clients with the server, such as native mobile applications.”

(The 9 is a superscript.)

I am concerned about the words “This” and “It” that start the second and third sentences. What exactly do they refer to? It could be confusing as to whether you mean using Selmer or using the single-page approach. I assume you mean both, but some more explanation about what the approach is and how it achieves the separation would have made this paragraph clearer to me.

2016-03-09
52SUGGEST

“The map contains any variables that we’d like to render in
our template and provides a context for it. In our case we’re populating the
name tag using the :name key in the context map.”

I found this confusing. Wouldn’t the first sentence still convey the complete meaning (and be less confusing) it is were just

“The map contains any variables that we’d like to render in our template.”

I guess the map is also called a context map. Any reason it should be referred to as a context map instead of simply a map?

2016-03-09
52SUGGEST

“if we pass in a collection we can iterate it using the for tag”

“iterate it” should be “iterate over it”

2016-03-09
229SUGGEST

“When you need to iterate a collection,”

“iterate a” should be “iterate over a”

2016-02-24
232SUGGEST

“since we have to iterate our
sequence each time”

“iterate our” should be “iterate over our”

2016-02-24
33TYPO

Last example for server response codes should be status 500 (currently status 100)

2016-03-05
11SUGGEST

Please describe how to connect the repl
with “lein repl :connect 7000” in another window.

At least I had to google on how to do it :-)

2016-03-09
154SUGGEST

“load-interceptors!” is called but this function is not introduced until a couple pages later

2016-03-17
154TYPO

reg/registration-form-example does not match the defined function, reg/registration-form

2016-03-06
86SUGGEST

“Finally, we’ll need to write a function to initialize the websocket. The function
will call the js/WebSocket with the supplied url to create the channel. Once the
channel is created it sets the onmessage callback to the supplied handler
function and puts the channel in the ws-chan atom.”

This paragraph basically describes the “connect!” function in “src/cljs/guestbook/ws.cljs”.

May be an idea to list the code here as well - ultimately the lack of the “connect!” listing lead to the “ws/connect! function” forum topic.

2016-03-14
170TYPO

no code showing that reagent.session needs to required in picture-gallery.ajax

2016-03-06
173TYPO

for the REPL test on page 175 to work,
need to require
[clojure.java.io :as io]
and include File in the java.io import

2016-03-06
8SUGGEST

Under the “Managing Database Migrations”,

This should generate a new migration, instead of replacing the contents of the add-users-table.up.sql migration, since we’re not actually adding a users table.

Related, we should also deal with the corresponding down migration. Right now, the down migration is left dropping the wrong table.

2016-03-04
15TYPO

The text

“We’ll create another div that will contain a field to hold any error messages
that might be populated by the server and a form for submitting new messages.”

shouldn’t be on this page, the div in question is only introduced on PDF page 21.

2016-03-05
176TYPO

need to require this in the services namespace:

[compojure.api.upload :refer [wrap-multipart-params TempFileUpload]]

2016-02-25
181TYPO

need to require the gallery namespace in services.clj:
[picture-gallery.routes.services.gallery :as gallery]

2016-02-25
163157TYPO

Under heading “Register the User” it says “We’ll navigate back to the picture-gallery.components.registration namespace” but the namespace in the example is “picture-gallery.registration”.

2016-03-06
165159TYPO

error atom is missing from let statement in registration-form (is present on previous page).

2016-03-06
195TYPO

Missing component code for selecting images to delete

2016-02-24
90ERROR

project.clj update on page 89-90 indicates:

[com.taoensso/timbre “4.1.5-SNAPSHOT”]
[com.taoensso/sente “1.7.0”]
[com.taoensso/tower “3.0.2”]

then I experienced:
“Exception in thread ”main" java.lang.ExceptionInInitializerError
\tat clojure.main.(main.java:20)
Caused by: java.lang.IllegalAccessError: have? does not exist, compiling:(taoensso/sente.clj:1:1)"

after checking updated source code download updated to:

[com.taoensso/timbre “4.2.1”]
[com.taoensso/sente “1.8.0-beta1”]
[com.taoensso/tower “3.0.2”]

and the problem went away.

2016-03-14
~8ERROR

Loc 332: Managing Database Migrations: How to restart application?

The default luminous page on port 3000 says to restart the application. There’s no indication of how to do that.

Generally there’s no instruction on what to do if you’ve made an error in your code (restart server? just edit file and server will reload?)

2016-03-09
13ERROR

The db namespace was omitted from save-message! on PDF p13 and p17

(defroutes home-routes
(GET “/” [] (home-page))
(POST “/message” request (save-message! request))
(GET “/about” [] (about-page)))

should be:

(defroutes home-routes
(GET “/” [] (home-page))
(POST “/message” request (db/save-message! request))
(GET “/about” [] (about-page)))

2016-03-09This is actually correct, the route calls the save-message! function in the same namespace, that function in turn calls the db/save-message! function.
98TYPO

“like” or “such as” instead of just “such”

“We can see that routes are declared using the compojure-api helpers such compojure.api.sweet/GET as opposed to compojure.core/GET that we used previously.”

should probably be:

“We can see that routes are declared using the compojure-api helpers like compojure.api.sweet/GET as opposed to compojure.core/GET that we used previously.”

2016-03-14
100TYPO

“Note” instead of “Noe”

“Noe that if your application is running then you’ll need to restart it in order
for the library to become available.”

should be

“Note that if your application is running then you’ll need to restart it in order
for the library to become available.”

2016-03-14
103SUGGEST

“At this point we can safely remove the existing sample endpoints from the namespace.”

What isn’t mentioned (based on “Figure 5 - Cat API” on p.104 and the source code download) is that the “context” context was removed entirely and that the “thingie” tag of the “/api” context was changed to “thecatpi”; the “Thingie” schema was also removed and the service-routes configuration map altered. Some less determined readers may find these types of discontinuities somewhat disruptive. Then again maybe users and disciples of clojure already have the necessary above average level of determination. :)

You may want to consider re-taging the “/api” to “thecatapi” instead of “thecatpi” - unless the allusion to feline urine is deliberate.

2016-03-17
106TYPO

Images in “Figure 6 - Default Page” on p.106 and “Figure 7 - Default Page” on p.107 identical.

“Figure 6 - Default Page” on p.106 can probably be elided without any loss of information.

2016-03-17The second image shows the navbar that's not present in the first image.
107TYPO

“the” instead of “th”

“For example, let’s change th content of the home-page function as follows.”

should be

“For example, let’s change the content of the home-page function as follows.”

2016-03-14
104TYPO

Most recent service version is about cats/kittens, not pugs/puppies so:

“localhost:3000/swagger-ui/index.html#!/tumbler/get_api_pugs”

should be

“localhost:3000/swagger-ui/index.html#!/thecatapi/get_api_cat_links”

2016-03-14
109TYPO

“cats” or “kittens” instead of “puppies” in the code listing at the bottom of the page:

“TODO: show some puppies…”

should be

“TODO: show some kittens…”

2016-03-14
110SUGGEST

“When we check the browser, it should now display the new content without having to refresh the page.”

Well, the content changes - but the navigation bar doesn’t immediately go away - for that I have to reload the browser; at least with Chromium 48.0.2564.109 (64-bit).

2016-03-17
112SUGGEST

Given that there are no “«” and “»” keys on most keyboards it may be an idea to use “»” and “«” for the angle quotes/guillemots in the “pager” code listing

(:require …
[goog.string :as gs])


[:span (gs/unescapeEntities “«”)]

[:span (gs/unescapeEntities “»”)]

2016-03-17
66SUGGEST

“Reagent is a ClojureScript UI component library built on top of the popular Facebook React library.”

It may be an idea to include some links in a footnote that shed some light on how React (and therefore Reagent) “actually works”. The typical “Hello World tutorial” or “see React Documentation” links like the one’s referenced in the Om Next tutorial

“facebook.github.io/react/docs/component-specs.html”

get quickly lost in the minutiae of React components without ever explicitly explaining the “collaboration” these components are created for. My recent top pick, the one that made “it click” for me, is “React Components, Elements, and Instances” by Dan Abramov

“facebook.github.io/react/blog/2015/12/18/react-components-elements-and-instances.html”

As a bonus after reading this blog entry people should be more appreciative of Hiccup’s syntax (at least in comparison to React Element JavaScript objects). :)

2016-03-09Thanks for the suggestion, added a footnote with the React components link. I think that for the scope of the book, the reader doesn't really need to dive into React, as I introduce all the concepts necessary to use Reagent. However, I agree that a bit of a background is helpful.
120SUGGEST

“sql/with-db-transaction [t-conn db]”

It could be helpful for clojure neophytes to mention in a footnote that here the vector should be read like a let binding. It took me to p.124 to realize what was going on here.

PS: On p.124 you may want add a :canucks or :hosers function entry to the with-db-transaction body inside find-users-transaction for derogatory balance. :)

2016-03-17
125SUGGEST

“Now let’s update our migrations files found in the migrations folder.”

The following may make it easier for some readers:

“Now let’s update our migration files found in resources/migrations.”

2016-03-14
129SUGGEST

Had to perform mount BEFORE changing the namespace in the REPL; i.e.:

user=> (in-ns ’reporting-example.db.core)
#object[clojure.lang.Namespace 0x2a3a5241 “reporting-example.db.core”]
reporting-example.db.core=> (mount.core/start #’reporting-example.db.core/*db*)

CompilerException java.lang.RuntimeException: Unable to resolve var: reporting-example.db.core/*db* in this context, compiling:(/tmp/form-init6535933350333489482.clj:1:1)

While reversed:

user=> (mount.core/start #’reporting-example.db.core/*db*)
[2016-02-19 21:03:59,149][INFO][com.zaxxer.hikari.HikariDataSource] HikariPool-0 - is starting.
{:started [“#’reporting-example.db.core/*db*”]}
user=> (in-ns ’reporting-example.db.core)
#object[clojure.lang.Namespace 0x2a3a5241 “reporting-example.db.core”]

2016-03-14
133SUGGEST

The “employee-template-paragraph” listing on p.133 is identical to the listing on p.132.

The repetition seems unnecessary if no change is required.

2016-03-17
136SUGGEST

“reporting-example/src/clj/reporting_example/routes/home.clj”
(defroutes home-routes
(GET “/” [] (home))
(GET “/about” [] (about))
(GET “/:report-type” [report-type] (generate-report report-type)))

Note the functions that are generated by default are “home-page” and “about-page”. As there are no instructions regarding “about-page” referencing “about” will result in an error. It is probably best to stick with “home-page” and “about-page” in “home-routes” and use “home-page” instead of “home” on p.135:

“reporting-example/src/clj/reporting_example/routes/home.clj”
(defn home []
(layout/render “home.html”))

2016-03-14
13SUGGEST

I was wrong about the db namespace and save-message!
I see we create a function by that name to call the one in the db namespace.
There is a problem in that the book shows the route:
(POST “/message” request (save-message! request))
before we make a save-message! function, causing an error as soon as we save the rile home.clj
Perhaps it would be best to create this route after making the save-message! function or show it commented out until save-message! is created.

2016-03-09
13SUGGEST

I got a bit confused by the Clojure code here, which contains the route for saving a message (which we won’t write until a couple of pages later) and doesn’t show the render function (which is referred to in the paragraph below the code excerpt). Maybe what should be shown is:

guestbook/src/clj/guestbook/routes/home.clj
(defn home-page []
(layout/render
“home.html” {:docs (-> “docs/docs.md” io/resource slurp)}))

(defroutes home-routes
(GET “/” [] (home-page))
(GET “/about” [] (about-page)))

2016-03-09I ended up including a wrong code sample there, hence the confusion.
38ERROR

The browsers output of
(GET “/some-route” request (interpose “, ” (keys request)))
is

[“ssl-client-cert”,“, ”,“protocol”,“, ”,“remote-addr”,“, ”,“params”,“, ”,“route-params”,“, ”,“headers”,“, ”,“server-port”,“, ”,“content-length”,“, ”,“compojure/route”,“, ”,“content-type”,“, ”,“character-encoding”,“, ”,“uri”,“, ”,“server-name”,“, ”,“query-string”,“, ”,“body”,“, ”,“scheme”,“, ”,“request-method”]

rather than the following quoted in the book:

:ssl-client-cert, :remote-addr, :scheme, :query-params, :session, :form-params,
:multipart-params, :request-method, :query-string, :route-params, :content-type,
:cookies, :uri, :server-name, :params, :headers, :content-length, :server-port,
:character-encoding, :body, :flash

Maybe there’s some middleware that hasn’t been introduced yet?

2016-03-14
38ERROR

Here’s a fix for the GET form in Accessing Request Parameters
(GET “/foo” request (apply str (interpose “, ” (keys request))))

2016-03-14
14SUGGEST

“First, we’ll add references to the guestbook.db.core and the ring.util.response namespaces.”

There was already a reference to ring.util.response in the template file, so I didn’t have to add it. On the other hand I did have to remove [clojure.java.io :as io] from the list of requirements for my file to match what’s in the book.

2016-03-05
11TYPO

“Since the queries are parametarized any variables we pass in will be sanitized to prevent SQL injection.”
“parametarized” should be: “parameterized”

2016-03-05
144TYPO

Function name is missing an exclamation mark; it should be

“(defn register! [{:keys [session]} user]”

not just

“(defn register [{:keys [session]} user]”

The missing exclamation mark makes an appearance by p.147.

2016-03-14
146ERROR

“picture-gallery.routes.services.auth/handle-registration-error” expects it’s parameter “e” to support “getNextException” - this method is only supported by java.sql.SQLException.

“picture-gallery.routes.services.auth/register!” will invoke “handle-registration-error” for ANY exception - i.e. “handle-registration-error” will fail when it is invoked with an exception that isn’t (derived from) a SQLException.

2016-03-17
83ERROR

(swap! channels #(remove #{channel} %)) replaces the original set referenced by channels with a seq.

To maintain the channels atom as a set change to:
(swap channels #(clojure.set/difference channels #{channel}))

2016-03-09good catch, and you could just do the following: (swap! channels clojure.set/difference #{channel})
83ERROR

Correction of earlier p83 eratum:
The fix is:
(swap! channels (clojure.set/difference channels #{channel}))

2016-03-09
83ERROR

Sorry, one more time:
(swap! channels clojure.set/difference #{channel})

2016-03-09
75SUGGEST

The component referred to in “We also create a new component called errors-component. The component accepts the errors and the field id.” only shows up two pages later (77), after the section on “Reimplementing the List”.
It should be part of the code listing on page 74.

2016-03-16
75SUGGEST

“We pass the errors to the send-message! function. The function will now either clear the errors on success, or set the errors from the response.”

The send-message! function is not redefined until page 77, and there it includes the changes to accommodate a third argument for messages. This whole section (Pages 74-77) needs a review, its a bit scattered.

2016-03-16
157TYPO

“Next, we’ll reference the ajax.core and the picture-gallery.validation namespaces.”

-> [reagent.session :as session]

has to be added as well (and should be shown as such in the “picture-gallery.components.registration” code listing that follows).

2016-03-06
86SUGGEST

The cljs ws/connect! function is missing in the code listings.

It should appear after:
“Finally, we’ll need to write a function to initialize the websocket. The function will call the
js/WebSocket with the supplied url to create the channel. Once the channel is created it sets the onmessage callback to the supplied handler function and puts the channel in the ws-chan atom.”

2016-03-14
160TYPO

“We should now see a register button in the navbar as seen in the following figure.”

To get an un-obscured view of the page as depicted in figure 17 we need to revert in “picture-gallery.core” from :

(defn page []
[:div
;; registration modal test
[reg/registration-form]
[(pages (session/get :page))]])

back to:

(defn page []
[(pages (session/get :page))])

2016-03-06
88TYPO

ws/start-router! should be ws/connect!. (The code listing accurately uses ws/connect!, only the text needs to be changed).

“The home function will now initialize all the atoms and then pass these to the response-handler that will in turn be passed to the ws/start-router! function and used to handle responses.”

2016-03-14
5TYPO

Actually in the excerpt of Chapter 5 on websockets, h__ps://media.pragprog.com/titles/dswdcloj2/websockets.pdf

At the bottom of the page, the section above the code snippet
The line
“Finally, we’ll create the add-message! function that will be called when the client
sends a message to the server.”
should be
“Finally, we’ll create the handle-message! function that will be called when the client
sends a message to the server.”
according to the code-snippet that follows.

2016-03-09
130TYPO

It seems the “comment form” component’s textarea is missing the “:value” key, and is malformed.

It reads:

:on-change #(swap! fields assoc :message (-> % .-target .-value))}
(:message @fields)]]

But it should read

:on-change #(swap! fields assoc :message (-> % .-target .-value))
:value (:message @fields)}]]

I’m also pretty sure the “:div.form-group” is closed too early (after the “name” input), instead of at the bottom after the “submit” input.

2016-03-14
90ERROR

In addition/completion of Peer Reynders erratum.

Placing the following in the project.clj dependencies causes a dependency conflict (see Peers erratum).

[com.taoensso/timbre “4.1.5-SNAPSHOT”]
[com.taoensso/sente “1.7.0”]
[com.taoensso/tower “3.0.2”]

Replacing this with newer versions of timbre and sente (as provided as solution by Peer) does not seem to resolve the issue.

Following advise from the author of timbre/sente/tower I’ve placed the latest version of encore (the conflicting dependency) above timbre, sente and tower. This solves the issue.

[com.taoensso/encore “2.36.1”]
[com.taoensso/timbre “4.2.1”]
[com.taoensso/sente “1.7.0”]
[com.taoensso/tower “3.0.2”]

2016-03-14
94ERROR

The state and handshake handlers have gotten exchanged in the code listing:

“(event-msg-handler
{:message message-handler
:state handshake-handler
:handshake state-handler})”

should be:

“(event-msg-handler
{:message message-handler
:state state-handler
:handshake handshake-handler})”

2016-03-14
94SUGGEST

“All that’s left is to modify the guestbook.core namespace to reflect the changes
in the guestbook.ws namespace. We’ll start by updating the namespace declara-
tion.”

The namespace declaration is identical to the previous one (Pg 87) It doesn’t need to be updated.

2016-03-14
164ERROR

With the adoption of HugSQL the “authenticate” function doesn’t need

(first (db/get-user {:id id}))

but only

(db/get-user {:id id})

See forum for details.

2016-03-06
175SUGGEST

The REPL test will also not work because compilation will fail due to the missing the function stubs for “image->byte-array” and “scale-image”. On p.174 it is mentioned

“A good way to figure out what helper functions we’ll need is to stub them out in our top level function”

but it will likely improve flow if the stubs are supplied explicitly in one of the listings before the REPL test.

(defn scale-image [file thumb-size]
)

(defn image->byte-array [image]
)

FYI: at first I thought that the code wasn’t working - due to the static scaling “scaled.jpg” looked off (i.e. nothing like a thumbnail) - until I realized that I was seeing the scaled upper left hand corner of the image. Adding a crude scaling calculation made the test result a bit more compelling.

user=> (require ’[clojure.java.io :as io])
nil
user=> (in-ns ’picture-gallery.routes.services.upload)
#object[clojure.lang.Namespace 0x642e2c87 “picture-gallery.routes.services.upload”]
picture-gallery.routes.services.upload
=> (ImageIO/write
#_=> (let [org-image (ImageIO/read (io/input-stream “image.jpg”))
#_=> scale-factor (/ thumb-size
#_=> (max (.getWidth org-image) (.getHeight org-image)))]
#_=> (scale org-image scale-factor thumb-size thumb-size))
#_=> “jpeg”
#_=> (File. “scaled.jpg”))
true
picture-gallery.routes.services.upload=>

2016-03-17
177SUGGEST

I realize that the reader is supposed to be “paying attention” but it could be helpful to have a footnote around

“We can now test uploading some files and check the database to confirm that the entries were indeed created there.”

with an instruction to navigate to “localhost:3000/swagger-ui-private/index.html#/default”. It is all to easy to use the browser history to navigate to “good ol’” “localhost:3000/swagger-ui/index.html#/default” and wonder where that darn “/upload” is hiding … (and given that it is supposed to be “private” somebody might give up just a little bit to easily).

2016-03-03
252SUGGEST

We read that “there are three main aspects to consider when picking a document-based database. These are consistency, availability and partition tolerance, as defined by the CAP theorem”.

This seems ill-expressed.

Unless one is building a “web-scale” application for 10’000 simultaneous clients, having to think about CAP tradeoffs is unlikely to be a immediate concern as “CAP theorem” applies to replicated services only, and even then only in certain cases.

When thinking about using a document-based database, other concerns should be more relevant, in particular, what kind of features does the document-based database support that you need and that are not covered by current RDBMS database (which may have all the features that you need to store, search and retrieve documents via appropriate SQL-callable functions)? Which features of the RDBMS do you want to give up in return (for example,. if you have to give up transactions, it’s probably not worth it unless you are sure to not regret it later).

The use case may well be that you just need a very simple “store-and-retrieve operation” and you are aiming for simplicity, so a “document-based” may be the way to go. Or you want performance, but even then you better mesaure what you are getting.

This excerpt from “Overcoming CAP with Consistent Soft-State Replication” (Kenneth P. Birman, Daniel a. Freedman, Qi Huang, Patrick Dowell, IEEE Computer, February 2012, pp 50-57) explains the context of CAP pretty well:

"The CAP theorem explores tradeoffs between consistency, availability and partition tolerance, and concludes that a replicated service can just have two of these three properties. To prove CAP, researchers construct a scenario in which a replicated service is forced to respond to conflicting requests during a wide-area network outage, as might occur if two different datacenters hosted replicas of some single service, and received updates at a time when the network link between them was down. The replicas respond without discovering the conflict, resulting in inconsistency that might confuse an end user.

However, there are important situations in which cloud computing developers depend upon data or service replication, and for which this particular proof does not seem to apply. Here, we consider such a case: a scalable service running in the first tier of a single datacenter. Today’s datacenters employ redundant networks that almost never experience partitioning failures: the “P” in CAP does not occur. Nonetheless, many cloud computing application developers believe in a generalized CAP “folk theorem,” holding that scalability and elasticity are incompatible with strong forms of consistency.

Our work explores a new consistency model for data replication in first-tier cloud services. The model combines agreement on update ordering with a form of durability that we call amnesia freedom. Our experiments confirm that this approach scales and performs surprisingly well.

….

Obviously, not all applications need the strongest forms of consistency, and perhaps this is the real insight. Today’s cloud systems are inconsistent by design because this design point has been relatively easy to implement, scales easily, and works well for the applications that earn the most revenue in today’s cloud. The kinds of applications that need stronger assurance properties simply have not yet wielded enough market power to shift the balance. The good news, however, is that if cloud vendors ever tackle high-assurance cloud computing, CAP will not represent a fundamental barrier to progress."

2016-03-17While cloud services may address the problem, I think it's still worth noting that there are trade-offs to be aware of. I did reword the paragraph to note that you should consider the features offered by the database as well.
103ERROR

Changes to the get-links function are not shown in the book:
After defining the parse-links function, the get-links function needs to be changed to also call parse-links. This is missing.

2016-03-14
105ERROR

The link to “/tumbler/get_api_pugs” is incorrect, it should instead be to “/thecatapi/get_api_cat_links”

2016-03-14
105SUGGEST

The section on “Compiling ClojureScript with Figwheel” should come earlier, on page 104.
Page 104 shows a screenshot of the swagger-ui page, which wouldn’t work without running figwheel first.

The first image in this section is the wrong one, it should be a screenshot asking you to run figwheel to compile cljs, instead of the “Welcome to swagger-service” screenshot.

2016-03-17Swagger UI doesn't actually reply on ClojureScript. It's a separate set of routes that's completely independent from the UI routes.
102SUGGEST

the text forgets to mention to added our newly composed helper `parse-links` to the `get-links` function as follows:

```
(defn get-links [link-count]
(-> “http: //thecatapi.com/api/images/get?format=xml&results_per_page=”
(str link-count)
client/get
:body
parse-xml
parse-links))
```

2016-03-14
132ERROR

At the bottom of the page the :header data {:color [0 150 150]} has the incorrect keyword. According to the code, to set a background color (the green in the example on the following page) the keyword is :backdrop-color i.e.:
:header [{:backdrop-color [0 150 150]} “Name” “Occupation” “Place” “Country”]}]

2016-03-14
64SUGGEST

The project name (as given in the path to the file above the code on this page) has changed from ‘guestbook’ to ‘guestbook-cljs’. Not sure if it’s intended to be an entirely new project: it’s not mentioned in the text.

2016-03-09That's done intentionally. I provide sample projects for different sections to make it easier to see what the final version should look like.
3SUGGEST

Leiningen has some limitations with regard to web development. A look at boot-clj would be helpful.

2016-03-14While boot does have some advantages, I simply haven't used it enough myself to dive into it. Since Luminus uses Leiningen as well, it's out of scope for this book.
43TYPO

(response/internal-server-error “failed to complete request”)
;=> {:status 100, :headers {}, :body “failed to complete request”}

Correct:
;=> {:status 500

2016-03-13
2SUGGEST

Invoking sudo in command ‘sudo mv lein ~/bin’ seems quite unnecessary since the lein script is copied to user’s own bin directory.

2016-03-14
76SUGGEST

I’ve been able to follow along with the code in this chapter so far but the ^{:key timestamp} on this page is the first time I’ve felt like I was falling into cargo cult programming. If it’s possible to add even a brief explanation of what this annotation is doing, that would be great.

2016-03-14
57ERROR

In (defn renderer []) …

wrap-error-page is an undefined symbol

2016-03-14
60TYPO

[selmer.parser :as selmer]
+
[selmer.parser :as parser]


(selmer/render “Hello {{name}}” {:name “World”})
+
(parser/render “Hello {{name}}” {:name “World”})

2016-03-17
198TYPO

picture-gallery-f/src/cljs/picture_gallery/components/registration.cljs

Presumably the Hiccup paragraph keyword was meant to be lowercase, not uppercase (though it may not matter). So

(defn delete-account-modal []
(fn []
[c/modal
[:h2.alert.alert-danger “Delete Account!”]
[:p “Are you sure you wish to delete the account and associated gallery?”] ; <<— this one
[:div

instead of

(defn delete-account-modal []
(fn []
[c/modal
[:h2.alert.alert-danger “Delete Account!”]
[:P “Are you sure you wish to delete the account and associated gallery?”] ; <<— this one
[:div

2016-03-17
24ERROR

This line:
(POST “/message” request (save-message! request))

should be:
(POST “/message” request (db/save-message! request))

2016-03-17
119TYPO

Several instances of clojure.java.jdbc being referred to as clojure.data.jdbc.

2 on page 119, 1 on 120, 1 on 121

2016-03-21Thanks, looks like this snuck in from the first edition, so much has changed. :)
5SUGGEST

Upon creating a new luminus app, lein run does not give us
[2016-02-29][INFO][guestbook.core] #’guestbook.db.core/*db* started

No where in the template is the guestbook.db.core used to form any db connection. I had to manual (start) it in repl.

I can’t find anywhere in the text where it tell me where and how I should add to the code to automatically form the db connections. Thanks.

2016-03-21The database connection is managed by the [mount](https://github.com/tolitius/mount) library. When the `mount.core/start` function is run, then all the resources are initialized automatically. \n \nHowever, the resource has to be referenced somewhere in order to be started. Once you start using the database in the later section, then it will be started for you automatically. \n \nSince the REPL test session happens before the resource is used, it does need to be started manually by running `(mount/start #'guestbook.db.core/*db*)`. I've updated the example in the chapter to reflect that.
131ERROR

(jdbc/insert!
@db
…)

->

(jdbc/insert!
db
…)

2016-03-23
181TYPO

set set this variable -> set this variable

2016-03-25
9787SUGGEST

Don’t understand this line of code:
(swap! channels clojure.set/difference #{channel})

2016-03-25The code removes the channel from the set of currently open channels. The `swap!` function passes the value `channels` atom as the first parameter to the `clojure.set/difference` function followed by `#{channel}`. It then replaces the current value with the one returned by the `difference` function. \n \nThe value of `channels` is a set of all open channels, and the difference between it and a set containing `channel` will be all the other channels.
87ERROR

The disconnect! function has the lines

(swap! channels #(remove #{channel} %))
(swap! channels clojure.set/difference #{channel}))

Shouldn’t it be one or the other?

2016-03-27Yeah, it should be the second one. Using `remove` will return a seq instead of a set.
89TYPO

The cleaned-up code for the guestbook.routes.home namespace still has all the functions that have been moved to guestbook.routes.ws.

2016-03-27
1SUGGEST

I tried running some bits of the book using openjdk-9, and it seems like there have been changes made that result in reporting-example, at least, to fail in non-obvious ways. I’m not sure what can be done about this, but since it impeded my progress with the book, I wanted to mention it. Perhaps a note about compatible versions of the jvm could be added, or should be added to luminus itself?

2016-05-19JDK 1.8 should be listed as one of the requirements and as JDK 9 gets closer to the release I'll be updating the Luminus template to work with it.
65SUGGEST

This is my first attempt at using ClojureScript, and although I was able to follow along with the examples in the book (for the most part!) I struggled a bit with debugging typos, writing code straight into files rather than trying it out in the REPL, etc. Having now gone through the Quick Start in the ClojureScript GitHub wiki (spam filter isn’t letting me link to it directly) I feel a lot more comfortable with it — maybe worth adding a reference to that in a footnote here or in the primer at the end of the book?

2016-04-02
178ERROR

The page number is probably incorrect, I’m using the epub version of the book,and this is in chapter 8.

My problem is that binding db in the repl is failing. Here is what I’m running into:

user=> (in-ns ’picture-gallery.db.core)

user=> (in-ns ’picture-gallery.db.core)
#object[clojure.lang.Namespace 0x19dfd41 “picture-gallery.db.core”]
picture-gallery.db.core=> db
#object[mount.core.DerefableState 0x52691944 {:status :failed, :val #error {
:cause “mount.core.DerefableState cannot be cast to clojure.lang.IFn”
:via
[{:type java.lang.RuntimeException
:message “could not start [#’picture-gallery.db.core/*db*] due to”
:at [mount.core$up$fn__100 invoke “core.cljc” 92]}
{:type java.lang.ClassCastException
:message “mount.core.DerefableState cannot be cast to clojure.lang.IFn”
:at [picture_gallery.db.core$eval7339$fn__7340 invoke “core.clj” 32]}]
:trace
[[picture_gallery.db.core$eval7339$fn__7340 invoke “core.clj” 32]
[mount.core$record_BANG_ invokeStatic “core.cljc” 86]
[mount.core$record_BANG_ invoke “core.cljc” 85]
[mount.core$up$fn__100 invoke “core.cljc” 93]
[mount.core$up invokeStatic “core.cljc” 92]
[mount.core$up invoke “core.cljc” 90]
[mount.core.DerefableState deref “core.cljc” 115]
[clojure.core$deref invokeStatic “core.clj” 2228]
[clojure.core$deref_as_map$fn__6164 invoke “core_print.clj” 392]
[clojure.core$deref_as_map invokeStatic “core_print.clj” 392]
[clojure.core$fn__6170 invokeStatic “core_print.clj” 410]
[clojure.core$fn__6170 invoke “core_print.clj” 410]
[clojure.lang.MultiFn invoke “MultiFn.java” 233]
[clojure.tools.nrepl.middleware.pr_values$pr_values$fn$reify__20636 send “pr_values.clj” 35]
[cider.nrepl.middleware.track_state$make_transport$reify__36833 send “track_state.clj” 184]
[clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn_20670$fn_20683 invoke “interruptible_eval.clj” 113]
[clojure.main$repl$read_eval_print__7408 invoke “main.clj” 241]
[clojure.main$repl$fn__7417 invoke “main.clj” 258]
[clojure.main$repl invokeStatic “main.clj” 258]
[clojure.main$repl doInvoke “main.clj” 174]
[clojure.lang.RestFn invoke “RestFn.java” 1523]
[clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__20670 invoke “interruptible_eval.clj” 87]
[clojure.lang.AFn applyToHelper “AFn.java” 152]
[clojure.lang.AFn applyTo “AFn.java” 144]
[clojure.core$apply invokeStatic “core.clj” 646]
[clojure.core$with_bindings_STAR_ invokeStatic “core.clj” 1881]
[clojure.core$with_bindings_STAR_ doInvoke “core.clj” 1881]
[clojure.lang.RestFn invoke “RestFn.java” 425]
[clojure.tools.nrepl.middleware.interruptible_eval$evaluate invokeStatic “interruptible_eval.clj” 85]
[clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke “interruptible_eval.clj” 55]
[clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn_20715$fn_20718 invoke “interruptible_eval.clj” 222]
[clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__20710 invoke “interruptible_eval.clj” 190]
[clojure.lang.AFn run “AFn.java” 22]
[java.util.concurrent.ThreadPoolExecutor runWorker “ThreadPoolExecutor.java” 1142]
[java.util.concurrent.ThreadPoolExecutor$Worker run “ThreadPoolExecutor.java” 617]
[java.lang.Thread run “Thread.java” 745]]}}]
picture-gallery.db.core=> (conman/bind-connection db “sql/queries.sql”)
{:snips nil, :fns ([:delete-user! {:meta {:doc “”}, :fn #object[hugsql.core$db_fn_STAR_$y__7116 0x23cbb9a2 “hugsql.core$db_fn_STAR_$y_7116@23cbb9a2“]}] [:get-user {:meta {:doc ”“}, :fn #object[hugsql.core$db_fn_STAR_$y__7116 0x385db37f ”hugsql.core$db_fn_STAR_$y7116@385db37f“]}] [:update-user! {:meta {:doc ”“}, :fn #object[hugsql.core$db_fn_STAR_$y__7116 0xd6be777 ”hugsql.core$db_fn_STAR_$y7116@d6be777“]}] [:create-user! {:meta {:doc ”“}, :fn #object[hugsql.core$db_fn_STAR_$y__7116 0x5c9978ec ”hugsql.core$db_fn_STAR_$y_7116@5c9978ec”]}])}
picture-gallery.db.core=> db
#object[mount.core.DerefableState 0x52691944 {:status :failed, :val #error {
:cause “mount.core.DerefableState cannot be cast to clojure.lang.IFn”
:via
[{:type java.lang.RuntimeException
:message “could not start [#’picture-gallery.db.core/*db*] due to”
:at [mount.core$up$fn__100 invoke “core.cljc” 92]}
{:type java.lang.ClassCastException
:message “mount.core.DerefableState cannot be cast to clojure.lang.IFn”
:at [picture_gallery.db.core$eval7339$fn__7340 invoke “core.clj” 32]}]
:trace

Attempting to switch back to the picture-gallery.routes.services.auth namespace doesn’t work, and I assume it’s due to related causes:

picture-gallery.routes.services.auth=> (register! {} {:id “foo” :pass “12345678” :pass-confirm “12345678”})
[2016-04-10 13:36:00,878][ERROR][picture-gallery.routes.services.auth] #error {
:cause db-spec mount.core.DerefableState@52691944 is missing a required parameter
:via
[{:type java.lang.IllegalArgumentException
:message db-spec mount.core.DerefableState@52691944 is missing a required parameter
:at [clojure.java.jdbc$get_connection invokeStatic jdbc.clj 292]}]
:trace

This is using the source code downloaded from the book’s web site on ubuntu 16.04 beta, postgres 9.5. The migrate task ran successfully.

2016-05-19The error means that the *db* hasn't been started. The [mount](https://github.com/tolitius/mount) library is used to manage stateful resources, and it automatically starts any resource that's in a namespace that's referenced somewhere. However, when the namespace isn't used anywhere then the state will not be started. \n \nYou can start the database manually by running `(mount.core/start #'picture-gallery.db.core/*db*)`. However, the first task in the chapter is to reference the database in the `picture-gallery.routes.services.auth` namespace. Once that's done, the database will be started automatically when the app starts.
8ERROR

The page number is probably incorrect, I’m using the epub version of the book,and this is in chapter 8.

My problem is that binding db in the repl is failing. Here is what I’m running into:

user=> (in-ns ’picture-gallery.db.core)

user=> (in-ns ’picture-gallery.db.core)
#object[clojure.lang.Namespace 0x19dfd41 “picture-gallery.db.core”]
picture-gallery.db.core=> db
#object[mount.core.DerefableState 0x52691944 {:status :failed, :val #error {
:cause “mount.core.DerefableState cannot be cast to clojure.lang.IFn”
:via
[{:type java.lang.RuntimeException
:message “could not start [#’picture-gallery.db.core/*db*] due to”
:at [mount.core$up$fn__100 invoke “core.cljc” 92]}
{:type java.lang.ClassCastException
:message “mount.core.DerefableState cannot be cast to clojure.lang.IFn”
:at [picture_gallery.db.core$eval7339$fn__7340 invoke “core.clj” 32]}]
:trace
[[picture_gallery.db.core$eval7339$fn__7340 invoke “core.clj” 32]
[mount.core$record_BANG_ invokeStatic “core.cljc” 86]
[mount.core$record_BANG_ invoke “core.cljc” 85]
[mount.core$up$fn__100 invoke “core.cljc” 93]
[mount.core$up invokeStatic “core.cljc” 92]
[mount.core$up invoke “core.cljc” 90]
[mount.core.DerefableState deref “core.cljc” 115]
[clojure.core$deref invokeStatic “core.clj” 2228]
[clojure.core$deref_as_map$fn__6164 invoke “core_print.clj” 392]
[clojure.core$deref_as_map invokeStatic “core_print.clj” 392]
[clojure.core$fn__6170 invokeStatic “core_print.clj” 410]
[clojure.core$fn__6170 invoke “core_print.clj” 410]
[clojure.lang.MultiFn invoke “MultiFn.java” 233]
[clojure.tools.nrepl.middleware.pr_values$pr_values$fn$reify__20636 send “pr_values.clj” 35]
[cider.nrepl.middleware.track_state$make_transport$reify__36833 send “track_state.clj” 184]
[clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn_20670$fn_20683 invoke “interruptible_eval.clj” 113]
[clojure.main$repl$read_eval_print__7408 invoke “main.clj” 241]
[clojure.main$repl$fn__7417 invoke “main.clj” 258]
[clojure.main$repl invokeStatic “main.clj” 258]
[clojure.main$repl doInvoke “main.clj” 174]
[clojure.lang.RestFn invoke “RestFn.java” 1523]
[clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__20670 invoke “interruptible_eval.clj” 87]
[clojure.lang.AFn applyToHelper “AFn.java” 152]
[clojure.lang.AFn applyTo “AFn.java” 144]
[clojure.core$apply invokeStatic “core.clj” 646]
[clojure.core$with_bindings_STAR_ invokeStatic “core.clj” 1881]
[clojure.core$with_bindings_STAR_ doInvoke “core.clj” 1881]
[clojure.lang.RestFn invoke “RestFn.java” 425]
[clojure.tools.nrepl.middleware.interruptible_eval$evaluate invokeStatic “interruptible_eval.clj” 85]
[clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke “interruptible_eval.clj” 55]
[clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn_20715$fn_20718 invoke “interruptible_eval.clj” 222]
[clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__20710 invoke “interruptible_eval.clj” 190]
[clojure.lang.AFn run “AFn.java” 22]
[java.util.concurrent.ThreadPoolExecutor runWorker “ThreadPoolExecutor.java” 1142]
[java.util.concurrent.ThreadPoolExecutor$Worker run “ThreadPoolExecutor.java” 617]
[java.lang.Thread run “Thread.java” 745]]}}]
picture-gallery.db.core=> (conman/bind-connection db “sql/queries.sql”)
{:snips nil, :fns ([:delete-user! {:meta {:doc “”}, :fn #object[hugsql.core$db_fn_STAR_$y__7116 0x23cbb9a2 “hugsql.core$db_fn_STAR_$y_7116@23cbb9a2“]}] [:get-user {:meta {:doc ”“}, :fn #object[hugsql.core$db_fn_STAR_$y__7116 0x385db37f ”hugsql.core$db_fn_STAR_$y7116@385db37f“]}] [:update-user! {:meta {:doc ”“}, :fn #object[hugsql.core$db_fn_STAR_$y__7116 0xd6be777 ”hugsql.core$db_fn_STAR_$y7116@d6be777“]}] [:create-user! {:meta {:doc ”“}, :fn #object[hugsql.core$db_fn_STAR_$y__7116 0x5c9978ec ”hugsql.core$db_fn_STAR_$y_7116@5c9978ec”]}])}
picture-gallery.db.core=> db
#object[mount.core.DerefableState 0x52691944 {:status :failed, :val #error {
:cause “mount.core.DerefableState cannot be cast to clojure.lang.IFn”
:via
[{:type java.lang.RuntimeException
:message “could not start [#’picture-gallery.db.core/*db*] due to”
:at [mount.core$up$fn__100 invoke “core.cljc” 92]}
{:type java.lang.ClassCastException
:message “mount.core.DerefableState cannot be cast to clojure.lang.IFn”
:at [picture_gallery.db.core$eval7339$fn__7340 invoke “core.clj” 32]}]
:trace

Attempting to switch back to the picture-gallery.routes.services.auth namespace doesn’t work, and I assume it’s due to related causes:

picture-gallery.routes.services.auth=> (register! {} {:id “foo” :pass “12345678” :pass-confirm “12345678”})
[2016-04-10 13:36:00,878][ERROR][picture-gallery.routes.services.auth] #error {
:cause db-spec mount.core.DerefableState@52691944 is missing a required parameter
:via
[{:type java.lang.IllegalArgumentException
:message db-spec mount.core.DerefableState@52691944 is missing a required parameter
:at [clojure.java.jdbc$get_connection invokeStatic jdbc.clj 292]}]
:trace

This is using the source code downloaded from the book’s web site on ubuntu 16.04 beta, postgres 9.5. The migrate task ran successfully.

2016-04-28looks like a duplicate of #80208
245TYPO

At: “When we call a method, we pass the object its first parameter followed by any other parameters that the method accepts.”

It would’ve been clearer to me if it said: “[..] we pass the object as its first parameter […]”.

2016-04-19
7TYPO

Missing word: “This is where the majority of our application logic will live.”

2016-04-19
10SUGGEST

At “Note that using a single file for queries will not scale for larger applications and you’ll likely want to create multiple files to track different types of queries in that case.”

Why are you saying that?

2016-04-19I suppose that probably could be omitted. I find that in bigger applications I tend to group queries by purpose to make it easier to track them. However, there's not much context for this in the book.
18ERROR

I searched about an hour before I figured POST wasn’t :refer’d, I didn’t check if the version of the template you picked included it by default but the latest version didn’t. The text doesn’t seem to mention it.

2016-04-19
18TYPO

Sentence " This is where majority of our application logic will live." is missing a word (“the”, “a”) between “where” and “majority”.

2016-04-19
16SUGGEST

Might be worth adding a note on how to change the port using “lein run” in Luminus - I had another site running on the default port and had to do more digging to find the answer than I would expect.

2016-04-19
239ERROR

“We set foo to a string with value ”foo" inside our with-foo function."

There is no with-foo function, and the string is set to value “I exist!”

2016-04-21
12ERROR

In the REPL code testing the db queries, I got the following error:

user=> (use ’[guestbook.db.core :refer :all])
nil
user=> (get-messages)

IllegalArgumentException db-spec mount.core.DerefableState@755c4ad7 is missing a required parameter clojure.java.jdbc/get-connection (jdbc.clj:292)

I had to run (mount/start) before that would work.

2016-05-19The book does mention to run ` \n(mount/start #'guestbook.db.core/*db*)` in the latest version.
168ERROR

If you enter a non ascii character (the spanish ñ, in this case) in name or password input field, encodeString creates an incorrect Auth string. You cannot decode it correctly later.
I made this correction, that works correctly:
(->> (str user “:” pass) (goog.crypt/stringToUtf8ByteArray) (b64/encodeByteArray) (str “Basic ”))

Thanks for taking a look at this, unfortunately the fix doesn't seem to work for me when I test locally. When I add in `stringToUtf8ByteArray`, then the password no longer seems to validate.
32ERROR

Including the <!DOCTYPE html> entry doesn’t count as your opening html tag.

You also need to open your

tag on the line that follows.

2016-06-12
anyERROR

In many places we see a self-closing html element. Browser will support them but is invalid style, all elements (except empty elements) must have a valid closing tag.

It’s especially invalid on empty elements which should have no closing tag at all such as

and .

44ERROR

input is an empty element and shouldn’t have a closing tag.

2016-06-12
24SUGGEST

“If you aren’t already, I encourage you to start using one of the popular Clojure-aware
editors such as Light Table, Emacs, Cursive, or Counterclockwise.”

I ran into a problem trying to use Emacs and Cider. When I start the Guestbook application with ‘lein run’ it apparently starts the luminus-nrepl. When I connect to that from Emacs with M-x cider-connect (and connect to localhost port 7000), not all the Cider functions work. Cider is expecting to talk to cider-nrepl (not luminus-repl).

The way I found to work around that is this: Do not start the application with ‘lein run’. Instead, cd to the project directory then run M-x cider-jack-in. When the repl comes up (in the user namespace), run ‘(start)’.

Is this the best way to do it? Should there be a note in the book as to how to use Emacs/Cider as the Clojure-aware editor? (Then all the other Clojure-aware editor users will want their own notes also!)

Frank

I don't use Emacs myself, but that approach is fine as well. I might add a note about the alternative way to start the app, but I don't really want to get into editor configuration as it's a constantly moving target.
43TYPO

“Luminus removes the burder or having to …”

“or” should be “of”

2016-06-09
25SUGGEST

“Let’s take a look at how to handle HTTP requests and responses using Ring
and structure routes using Compojure by building a web app from scratch.”

I think the above could be clearer. Perhaps something like the following (added commas and a “how to”):

“Let’s take a look at how to handle HTTP requests and responses using Ring, and how to structure routes using Compojure, by building a web app from scratch.”

2016-06-11
30SUGGEST

“The header is a map containing the HTTP-header key/value pairs. Headers may be strings or a sequence of strings, in which case a key and a value will be sent for each string in the sequence.”

I am having trouble understanding this, especially the 2nd sentence. It looks like you might be saying the :headers key/value might look like this:

:headers {“Content-Type” [“string1” “string2 ”string3"]}

and would result in three Content-Type headers inserted into the response. Maybe the wording could be clarified?

2016-06-11You're right it's not entirely clear, I've reworded and added an example. Your interpretation is correct by the way.
4433TYPO

“Let’s add the library to the dependencies in project.clj and updating the handler
function in the project.”

“updating” should be “update”

2016-06-11
4433SUGGEST

Should you mention that after adding [metosin/ring-http-response “0.6.5”] to the dependencies, the app needs to be restarted (‘lein run’), in spite of the addition of the wrap-reload middleware added a few pages earlier? Discuss the limitations of wrap-reload either at this point or a few pages earlier where wrap-reload is introduced?

2016-06-11Makes sense, I added a note regarding this problem.
4534TYPO

curl -H “Content-Type: application/json” -X POST -d ’{id localhost:3000/json
{result

The typography does not make it clear that {result is the response from the curl command rather than an argument to the curl command.

2016-06-12
4433ERROR

In the example of response with ‘ok’ type lines of code with ‘headers’ and ‘body’ keys are not commented (not in green color), but it seems that they should be.

(response/ok "

hello world

“)
;=> {:status 200
:headers {}
:body ”

hello world

"}

2016-06-12
131ERROR

I didn’t need to dereference db in the REPL example that inserted the employees.

2016-06-12You just have to make sure you're in the namespace where the *db* var is available. The latest version uses `(in-ns 'reporting-example.db.core)` to set the REPL namespace.
6454TYPO

In the first word in the first sentence of the “Application Handler” part there is a typo: “Ihe” instead of “The”.

Sentence:
“Ihe routes function aggregates the routes for handling all the requests to our
application.”

2016-06-19
7262TYPO

Double “are” word in the penultimate paragraph.

“This allows the server to retain its state when namespaces are are reloaded during development.”

2016-06-19
8777SUGGEST

It is said on that page that, after some code modifications, we should have 404 error after the POST attempt because previously our post request was done directly to the / URI.
Maybe I’ve misunderstood smth, but it seems wrong, because at PDF pages 29, 30, 66 all POST requests were already done to the ‘/message’ URI. Please tell me if I am wrong with that suggestion.

You're absolutely right. The older version of the original example used the / URI, but I later switched to usng /message in both. I've updated the text to reflect that.
76ERROR

This is an issue with the downloadable code for the book, not the book directly.

In the downloadable code for guestbook-cljs the project.clj file has [luminus-immutant “0.1.4”] listed as a dependency, but the earlier code for guestbook has [luminus-immutant “0.1.9”] listed as the dependency.

Trying to run the code with immutant 0.1.4 threw an error “java.lang.IllegalArgumentException: No value supplied for key: Oracle Corporation”. Upgrading the dependency to 0.1.9 fixed the problem

140131ERROR

When (mount.core/start #’reporting-example.db.core/*db*) function is called, the exception shown below is raised:

Caused by java.lang.ClassCastException
mount.core.DerefableState cannot be cast to clojure.lang.IFn

111100TYPO

In the first line of the second paragraph there is a typo: “ompojure-api” instead of “Compojure-api”

138128SUGGEST

On that page, when ‘find-users’ query is defined, it is said “Let’s add a new file called resources/find_user.sql and place the following query there:”, but it seems that this query is placed to the users.sql file in the example below instead, as all previous queries.

221ERROR

Looking at the ns: media.pragprog.com/titles/dswdcloj2/code/picture-gallery-tests/test/clj/picture_gallery/test/handler.clj

Unless I wrap the app in:
(let [{:keys [body status]} (app (login-request “foo” “bar”))]

I get an error indicating too many params to app. I think it should read:

(let [{:keys [body status]} ((app) (login-request “foo” “bar”))]

This is true for all instances of app in that ns. I get the error when I run the repl through cider or connect to an existing repl.

170160SUGGEST

It is written: “Now let’s add a reference to the reagent.session namespace and update the
Cancel button in our form to remove the :modal key from the session.”,
but we have already referenced reagent.session namespace on the previous page

10TYPO

This in the MOBI, location 409 of 10210, Chapter 1, Section “Refine Your App”. In fact, I just download the PDF and it appears that the code is correct there! The code shown in the mobi is, God Save Us:

​— :name save-message’ :’ :n

Now, if I copy and paste it here, it will come out like this:

​— :name save-message! :! :n

But it absolutely appears to be an apostrophe in MOBI. I can’t attach a screenshot, or you’d see. I believe this caused me a fair amount of grief until I realized it.

5ERROR

Port numbers don’t match:
lein run -p 8000
http: / / localhost:3000

33TYPO

“Since adding a new libraries”… number error

34ERROR

> …, you can see that the home-routes are wrapped with middleware/wrap-csrf
> by calling the compojure. core/wrap-routes macro. The macro makes sure that …

`wrap-routes` is a function.

1205TYPO

What’s In the Response Map section “When the value will is a sequence”. Presumably “will” is superfluous.

18ERROR

screen.css listing specifies: ul { list-style: none; }
But screen shot on next page contains bullets next to guest book messages.
So this list-style isn’t applied to page on screenshot.

78TYPO

This sentence is repeated twice under the “concurrency” header:

Aside from these differences, development in ClojureScript is very similar to that in regular Clojure.

Aside from these differences, development in ClojureScript is very similar to that in regular Clojure.

89ERROR

The `app-routes` definition in ..guestbook/handler.clj still needs `middleware/wrap-formats` to handle the JSON in the `/messages` route. `get-messages` in the client is still an Ajax call in the WebSocket example to this point.

FROM
(def app-routes (routes
#’websocket-routes
(wrap-routes #’home-routes middleware/wrap-csrf) (route/not-found
(:body
(error-page {:status 404
:title “page not found”})))))

TO
(def app-routes
(routes
#’websocket-routes
(-> #’home-routes
(wrap-routes middleware/wrap-csrf)
(wrap-routes middleware/wrap-formats))
(route/not-found
(:body
(error-page {:status 404
:title “page not found”})))))

I got an
“Can’t coerce body of type class clojure.lang.PersistentArrayMap” error.

Thanks for writing the book and the the libraries.

164ERROR

Need to remove the “first” call below:

Before:
(defn authenticate [[id pass]]
(when-let [user (first (db/get-user {:id id}))]
(when (hashers/check pass (:pass user))
id)))

After:
(defn authenticate [[id pass]]
(when-let [user (db/get-user {:id id})]
(when (hashers/check pass (:pass user))
id)))

Otherwise, user is set to the first key-pair in the user hash, rather than set to the full user hash.

68TYPO

In the Concurrency subsection, the sentence starting with “Aside…” is repeated twice. Once at the end of the paragraph and once at the start of the next paragraph.

68SUGGEST

Argh my other erratum is on 67.

The code example is “guestbook-cljs” but there’s no information about how we got here. Are we modifying the guestbook code (then why the change?) or did we make a copy (but this isn’t mentioned). I think this could be made clearer.

148ERROR

I’ve scanned this a few times and cannot find where I missed a step. At this point, the database (db) is not started so the register! “test” always fails. Here is the list of things that had started when I called lein run:

[2016-10-24 17:01:56,462][INFO][picture-gallery.core] #’picture-gallery.config/env started
[2016-10-24 17:01:56,462][INFO][picture-gallery.core] #’picture-gallery.handler/init-app started
[2016-10-24 17:01:56,462][INFO][picture-gallery.core] #’picture-gallery.core/http-server started
[2016-10-24 17:01:56,462][INFO][picture-gallery.core] #’picture-gallery.core/repl-server started
[2016-10-24 17:01:56,462][INFO][picture-gallery.core] #’picture-gallery.core/log started

once I called:

(mount.core/start #’picture-gallery.db.core/*db*)

register! worked.

77ERROR

Page 77 says to add “[ring.util.response :refer [response status]]” to guestbook-cljs/src/clj/guestbook/routes/home.clj. Adding them as instructed leads to compile errors. Also, that file the source code tar ball does not have those references.

151ERROR

I think there may be a discrepancy with the generated template or something.

The generated .cljs file in picture-gallery.core only contains the namespace declaration and the init function that overrides the default page content with the ‘welcome to picture gallery’ string.

The code on p 149 to test the dialog, seems to presume the presence of some items that aren’t in the file

~
(ns picture-gallery.core
(:require …
[picture-gallery.components.common :as c])
(:import goog.History))
~

Prior to adding this code, there are no :requires, etc.

Then the page function

~
(defn page []
[:div
;;modal test
[c/modal “I’m a Modal” [:p “this is the body”] “this is a footer”]
[(pages (session/get :page))]])
~

refers to `pages` and `session/get` that haven’t been required into scope. Also, given the default `init!` function, the creation of the `page` function doesn’t really do anything. Presumably it would be added to the set! of the init! function

~
(defn init! []
(-> (.getElementById js/document “app”)
(.-innerHTML)
(set! “Welcome to picture-gallery”)))
~

79ERROR

In Chapter 4 (ClojureScript)

There is a route on the server that map the resource POST “/message”
On page 79, in the function called “send-message!”, the POST is made the URL “/add-message”. Which cause the request to fail (404).

By the way, not really an idiomatic way to name the path for a resource because the verb is define by the POST (~ add).
Example: “GET /add-message” makes its meaning not so obvious. “GET /message” is much clearer what it means.

140ERROR

Creation of new picture gallery project is described as

“lein new luminus picture-gallery +auth +swagger +cljs +postgres”

It should be

“lein new luminus picture-gallery +auth +swagger +reagent +postgres”

As code changes further on expect the presence of functions created by the reagent profile (e.g. the ‘pages’ def in cljs/picture-gallery.core)

17ERROR

For the guestbook/src/guestbook/models/db.clj file:

the defn create-guestbook-table [] appears to have a few technical errors. “sql/with-connection db” should be “sql/wiith-db-connection [db],” “sql/create-table” should be “sql/create-table-ddl,” and the vector of columns from :id to :message needs to be included in a separate set of [] to make it a vector of vectors. I have found that this version compiles and runs:

(defn create-guestbook-table []
(sql/with-db-connection [db]
(sql/create-table-ddl
:guestbook
[[:id “INTEGER PRIMARY KEY AUTOINCREMENT”]
[:timestamp “TIMESTAMP DEFAULT CURRENT_TIMESTAMP”]
[:name “TEXT”]
[:message “TEXT”]])
(sql/db-do-commands db “CREATE INDEX timestamp_index ON guestbook (timestamp)”)))

30TYPO

I believe the word “will” at the end of the 2nd line on the page is a typo. The sentence reads “When the value will is a sequence, then a name/value….”

173ERROR

Picture gallery, Picture Upload section: REPL code for scaling image has couple of issues:

- “org-image” -> “image”
- “File.” -> “java.io.File.”

36ERROR

The ns declaration for ring-app.core is missing the previously required “[ring.middleware.format :refer [wrap-restful-format]],” which is still used in the ring-app in the sample code file.

68SUGGEST

It appears that the book starts working with a separate project called “guestbook-cljs” starting around pg. 68, so, if that is true, I would recommend putting in a line prompting readers to create a new project called “guestbook-cljs” or to copy over the older project and somehow refactor the name of the copy into “guestbook-cljs.”

39ERROR

Parsing query params via destructuring doesn’t work for me as mentioned at the end of Chapter 2:
```(GET “/” [x y :as request] (str x y request))

I’ve found “accessing-compojure-query-string” discussion on stackoverflow which mentions that it used to be handled automatically by defroutes macro, but that’s no longer the case.
I had to wrap my handler with middleware ring.middleware.defaults/site-defaults to handle this.

79ERROR

In the ClojureScript `send-message!` function, the errors from the bouncer library need to be destructured (with `clojure.walk/keywordize-keys`. I’m pretty sure there’s a better place to do this, but this made it work. Do you know of a better place?

(defn send-message! [fields errors messages]
(POST “/message”
{:format :json
:headers
{“Accept” “application/trasnit+json”
“x-csrf-token” (.-value (.getElementById js/document “token”))}
:params fields :handler (fn [] (do ;(.log js/console (str "response: " %)) (reset! errors nil) (swap! messages conj (assoc fields :timestamp (js/Date.)))
(reset! fields {}))) ; reset fields to empty
:error-handler (fn [error]
(let [e (clojure.walk/keywordize-keys error)]
(do
(.log js/console (str “error: ” e))
;(.log js/console (str “current errors: ” @errors))
(reset! errors (get-in e [:response :errors])))))}))

148ERROR

Cannot run command (conman/bind-connection db “sql/queries.sql”)
After that command (register! {} {:id “foo” :pass “12345678” :pass-confirm “12345678”}) is failed
Follow report #80830 run command (mount.core/start #’picture-gallery.db.core/*db*) and run
(register! {} {:id “foo” :pass “12345678” :pass-confirm “12345678”}). It works, please check and update

146ERROR

Can not run (register! {} {:id “foo” :pass “12345678” :pass-confirm “12345678”})
because (:import [java.sql SQLException]) was missing.

4ERROR

I tried to specify lein template version in profiles.clj:

{:user {:plugins [[luminus/lein-template ​“2.9.10.74”​]]}}

When I run lein command I’m getting next error:

Could not find artifact luminus:lein-template:jar: in central (repo1.maven.org/maven2/)
Could not find artifact luminus:lein-template:jar: in clojars (clojars.org/repo/)
This could be due to a typo in :dependencies or network issues.
If you are behind a proxy, try setting the ‘http_proxy’ environment variable.

MacOS, leiningen: stable 2.7.1.

230TYPO

A close parenthesis is missing:

(let [{foo :foo bar :bar} {:foo “foo” :bar “bar”}]
(println foo bar)

78TYPO

Double text:
“…Aside from these differences, development in ClojureScript is very similar to that in regular Clojure.
Aside from these differences, development in ClojureScript is very similar to that in regular Clojure…”

anyERROR

Kindle location 4420 ~
"
[[: li.page-item > a.page-link.btn ​   {: on-click #( swap! page back pages) ​   :class (when (= ​@ ​ page 0) ​" disabled" ​)} ​   [: span ​“«” ​]]]
"
On this part, ‘back’ function take only one argument i. so in ‘swap!’, the correct way is #( swap! page back)

7ERROR

It looks like the generated app no longer supports the lein migratus command.

lein migratus create guestbook

Doesn’t work. I think you now have to fire up the console.

Categories: