Project structure
Overall structure
The project can be roughly divided into four parts:
- The step-web project contains the HTTP handlers. The goal of this project is to provide a thin layer around the core.
- The step-web project also contains all the HTML/Javascript code that make up the UI
- step-core is the main project where most of the functionality is written. The main entry points should be via the Services which either provide functionality or are wrappers around other classes/services (for example ''BibleInformationService'' is a wrapper around some of the Crosswire JSword project API).
- The step-core project also contains a "data" section under ''com.tyndalehouse.step.core.data''. This package is responsible for all the creation of data as well as functionality to retrieve data from the database. This for all JPA entities that can be stored in a relational database.
- The JSword service may eventually be split into several different services. Its main goal is to abstract away as much as possible the JSword API. This is so that if the API changes, only changes in JSword service wrapper can be made.
step-web
Presentation layer
All the HTML/Javascript code is contained within the step-web project and is abstracted away and self-contained. It communicates with the server via AJAX requests (facilitated by the JQuery library). The AJAX requests follow a notation similar to the REST protocol (more on this in the section below). All requests are defined in src/main/webapp/js/ui-hooks.js
There is very little HTML markup. Most of the UI is generated via Javascript using JQuery. The HTML code is used to provide the basic structure and layout and ease development.
Functionality locations
All HTML code is defined in src/main/webapp. This directory contains the following elements:
- /js directory contains all custom code
- /libs contains all third party libraries
- css contains all CSS markup
The following files are noteworthy:
- index.html file includes a number of libraries (JQuery, Google Maps, etc.) and then all the custom code.
- js/init.js: There is only 1 entry point to run the STEP code which is in js/init.js with the init(); function. This triggers the start up of the whole presentation layer. Eventually we should try and reduce this layer to a minimum which just sets up all the dependencies between the different presentation layer components.
- js/ui_hooks.js defines all URLS to interface with the server as global constants. It also defines all "hooks" that the HTML code or Java code may need to call. For example, a menu may need to call back to the Javascript library - these are extra "entry" points used in event driven scenarios.
- libs/jquery-shout.js defines a event bus. An event bus is a simple register of listeners for particular events. In order to avoid lots of tangles, each "widget" communicates with other widgets by sending events through the event bus. For example, the passage.js object may communicate to the event bus via a .shout call that the "PASSAGE HAS CHANGED". The jquery-shout library will then notify any other object that registered interest (for example the maps, the timeline component, etc.). Interest is registered through a .hear call.
- js/passage.js is the main passage display component.
Web-tier Java layer
The step-web is built as a Front Controller pattern, where all client requests are caught by the ''FrontController''. This then dispatches requests to the relevant method in the relevant controller. The ''FrontController'' is also responsible for serialising responses. At time of writing this takes 2 forms:
- The role of this tier is to abstract away the type of interface from the rest of the application, allowing future development of native interfaces in Android and other Java-enabled OSs. So for example, the concept of a cookie is wrapped around, etc.
- If the response is part of the Avaje Bean package (i.e. a entity or list of entities retrieved by the database) then serialisation is done using the Ebean JSON serialiser
- In all other cases, the Jackson mapper is used to serialise POJOs.
FrontController
The FrontController object takes in a request URL, calls the relevant controller method and finally returns a serialised UTF-8 encoded response. The FrontController is configured by the web.xml descriptor to listen to all requests under /rest/.
For example,
http://localhost:8080/step-web/rest/timeline/getTimelineConfiguration
- Tomcat (or another container) passes the request to FrontController
- The FrontController looks at the remainder of the url /timeline/getTimelineConfiguration
- Identifies the controller based on the first portion: /timeline => TimelineController (simply suffixing the word Controller)
- Using Guice (see section on dependency injection), it retrieves the identified Controller singleton instance
- Reflectively calls the method called "getTimelineConfiguration" based on the next section
- finally if any parameters are passed in, these are passed to the method in order of appearance.
step-core
The following section outlines the key areas in this project
- com.tyndalehouse.step.core.service contains all the interfaces and implementations of the services. These services (except for the ''JSwordService'') are called by the step-web project. This package should be the entry point to any external user interface or external program.
- com.tyndalehouse.step.core.models contains all non-database models. This is currently mainly used to transfer data from the Crosswire JSword components.
- com.tyndalehouse.step.core.guice contains any related classes for the dependency injection framework (more on this below)
- com.tyndalehouse.step.core.data.create contains code that will be used to load up data into the SQL database (SQL Lite, H2 or a more robust database). The database is currently used to store the timeline data and is expected to be used for all data that is relational.
- com.tyndalehouse.step.core.data.entities these classes use JPA (Java Persistant Objects) and are used by our ORM layer Avaje Ebeans. Currently Ebeans creates the schema on start into an in-memory database. This is used for development. On Android we are hoping to use the SQL Lite database. On desktops, the intention is to use SQL Lite or H2. Finally on the server architecture, we may use either of the previous 2 aforementioned databases, or a database more adequate for a client-server infrastructure (e.g. MySQL or Postgres)
Data
The data is currently stored in CSV files and the ''Loader'' and ''TimelineModuleLoader'' are currently used to load into a Lucene Index. This is currently done manually through firstTime.jsp. (Modules, texts, commentaries, ...) can be found under $USER_DATA/Sword/... whereas the Lucene Indexes can be found under $USER_HOME/JSword/step. Under Windows, USER_HOME defaults to USER_HOME/AppData/Roaming. On linux, Sword and and JSword are .sword and .jsword.
Â
Â