Web Interface - UBOdin/mimir GitHub Wiki
The Play Framework
Mimir's web interface is built on top of the Play Framework. This framework has a built-in web-server. There is no need to mess around with installing and maintaining a separate server process. Calling sbt run
in the application starts up the embedded server.
The current interface
As of this writing, Mimir is a single page web application. The main page contains a navigation bar and a query box. The last part of the page can either be textual status messages or tabular query output. Only state information that is kept is the current working database, and that is maintained through a hidden field. Dynamic content such as query explanations are handled through AJAX. An asynchronous request is made to the server and the server responds with JSON content.
Adding functionality
Adding new functionality could mean adding a new page or new services that can be accessed through AJAX requests.
- If the new functionality is a service, add JavaScript to call the appropriate service and render the response in
/public/javascripts/main.js
or a new file in that folder. - Add an entry to the
/conf/routes
file, specifying the URI and anAction
to be called that would handle requests for that URI. The URI could beGET
,POST
or other HTTP methods. - Define the
Action
in/app/controllers/Application.scala
.GET
Action
s accept query string parameters as method arguments. Responses can be HTML specified in/views
, JSON or XML. Play provides utilities to convert data objects into JSON/XML and vice versa. - Use existing methods in the
mimircore/src/main/scala/mimir/WebAPI.scala
to call into the core mimir code or add new methods if necessary.
Debugging
In Play code changes are auto-reloaded. There is no need to restart the server for most code changes to be reflected. However, changing application configurations does require a restart. This includes modifying the routes
file. Debug paths do not cross process lines. Each line of code from the incoming request to sending out the response can be stepped through and inspected, including request headers. The only code path that is separate from this is the client JavaScript that generates AJAX requests. In case a new service does not work as intended, the first step would be to inspect the request headers, to ensure that the client JavaScript generated the correct request.
Unit tests can be specified using specs2
and are contained within the /test
folder.
A note on synchronization
All Action
s are asynchronous, which means there can be multiple Action
s executing at the same time. The bulk of the debugging in Mimir happens on the SQLite database, which does not support multiple connections to the same database file. Therefore, opening and closing connections to the backend need to be synchronized. At present, a semaphore like solution is implemented in /mimircore/src/main/scala/mimir/sql/JDBCBackend.scala
to deal with this issue.
Future work
- Add support for connecting to databases backed by backends other than SQLite.
- Possibly, add user sessions and maintain state information. This could lead to a more elegant solution to the synchronization problem with SQLite. Backend connections would be opened and closed in session scope instead of per query.