Welcome to the Homelibrary project page
Homelibrary is a simple application for categorizing books. I originally developed the application for my wife to help her with categorizing books.
- Automatically obtaining information about a book by specifying its identifier (either
ISBN13) and downloading from Google Books
- Anonymous mode for browsing the books, administration mode for editing
- Easy categorization of books, attaching tags
- Instant search (results get updated as you type) according to the book title, its authors and attached tags
The application also serves as a showcase of interesting Scala and Play features, most notably:
- Consuming RESTful web services with Play Scala API
- Working with JSON using the Play API
- Internationalization in Play
- Database migration using Play evolutions
- Utilizing the flash scope to display messages to the user
- Performing DB access with Anorm - a simple yet powerful database layer
- Power of the Scala collections API when dealing with nontrivial Anorm result sets
- Elegant programming style with no mutable state
- Simplifying AJAX calls using the Play typesafe templates (since Play templates compile to Scala methods, which just return HTML fragment, it is very convenient to use AJAX for partial page update. The role of the server is just return the HTML generated by the template)
- Utilizing Play templates to create reusable HTML components
For each book the following attributes are stored:
- ISBN10, ISBN13
- Title (required field)
- Author(s) (required field)
- Date published
- Language (available languages are: Czech, Danish, English, French, German, Italian, Norwegian, Polish, Spanish and Swedish)
- Page count
- Cover picture
Architecture and technical description
Homelibrary is a standard Play2 application. The high-level application architecture, therefore, follows its concepts.
There is a Netty HTTP server instance, which handles requests and passes them to the Play router. The Play router then consults the
conf/routes configuration file and decides which action will be invoked for a particular request. Actions are contained in controllers and they are responsible of handling a request and returning a response. They typically access the database (using the Anorm layer, in case of Homelibrary), perform some operation with the result (filtering, sorting, ...) and return a response.
In Homelibrary, there are basically three types of actions according to response they generate:
- Responses containing whole HTML page. In such case, the action calls a template which then calls a layout template and passes itself result as an argument. This is a very flexible way of creating consistent page layouts, built in the Play framework (third party frameworks such as Tiles or Sitemesh are, therefore, not needed in Play).
- Responses containing just an HTML fragment. HTML fragment is returned when the action calls the template, but the template is not calling the layout template. This is very elegant way to achieve partial page updates using AJAX. Since the Play action just calls the template and returns its result, the client can directly update some part of the page with the received result.
- Responses containing a JSON value. In this case the action does not call any template at all, it merely serializes the result (usually obtained from the database) into JSON and puts it into the response directly. The client then parses the JSON and makes appropriate changes in the DOM. Play framework has very concise and elegant API for dealing with JSON values.
Limitations and possible future development
- Currently, there is no advanced user management. Since the application was originally written for purely personal use, there is a single administrator account, whose password is hardcoded in the application configuration (
- Since I'm not really good at design, the application uses Twitter Bootstrap as it is, without any significant modifications
Packaging and running
You can run the application using
play run and then open http://localhost:9000 in the browser. In the default configuration, it uses an in-memory H2 database, which is discarded on application restart. In order to make the changes persistent and thus keep them between application restarts, you need to edit the
db.conf configuration file, comment out the in-memory database definition and uncomment the line with flat-file database configuration. Part of the persistent database query string is also the path where database files will be stored (defaults to the user's home directory
You can also package the application for a production using
play dist, which creates a zip file with a packages application. In the zip archive, there is a
start script which starts the application.
I have learnt many of the concepts used in Homelibrary from an excellent book Play for Scala by Peter Hilton, Erik Bakker and Francisco Canedo. The Play framework documentation is also very well structured and information rich.