[[example-2-phonebook]]
== Example 2: Phonebook

We have covered a lot of ground so far. Let's consolidate our knowledge
by building a simple application, using all the concepts we've learned
so far.

We'll build a simple phonebook application. Here is a the brief:

[[phonebook-requirements]]
=== Phonebook requirements

Create a simple HTTP service to represent a phone book.

Acceptance criteria. - List all entries in the phone book. - Create a
new entry to the phone book. - Remove an existing entry in the phone
book. - Update an existing entry in the phone book. - Search for entries
in the phone book by surname.

A phone book entry must contain the following details: - Surname -
Firstname - Phone number - Address (optional)

[[the-database]]
=== The database

Create a new namespace called `phonebook.db`.

[source,clojure]
----
(ns phonebook.db)
----

We'll create a database constructor, and some functions to access its
contents.

This constructor creates a map with two entries, both refs. We could use
an atom, but refs offer more flexibility.

[source,clojure]
----
(defn create-db [entries]
  {:phonebook (ref entries)
   :next-entry (ref (inc (apply max (keys entries))))})
----

Now let's add some code to add an entry.

[source,clojure]
----
(defn add-entry [db entry]
  (dosync
   (let [nextval @(:next-entry db)]
     (alter (:phonebook db) conj [nextval entry])
     (alter (:next-entry db) inc)
     nextval)))
----

[[creating-new-phonebook-entries]]
=== Creating new phonebook entries

For this requirement, we are going to support the POST method.

Let's add the following entry to the static properties of the
`IndexResource`.

[source,clojure]
----
{:parameters {:post {:form {:surname String
                           :firstname String
                           :phone [String]}}}
…
}
----

This declaration tells yada what parameters we are expecting in the POST
method. In return, yada will do the following:

1.  Validate the request, ensuring that all the mandatory parameters
have been provided
2.  Coerce the parameters to the desired types (if possible).
3.  Return a 400 response (if not).
4.  Parse the request body.
5.  Help prevent XSS scripting attacks, by ensuring that no unexpected
parameters are allowed to pass through. We should still be careful of
String parameters though.
