Development Milestones Overview
Each Milestone represents enough completed functionality to add a new use case. They represent units of work that can be completed and tested as a complete unit.
Testing of a milestone will include unit tests which will use simulated server stubs as needed as well as at least one example usage of the main feature milestone represents. The example usage also be run as a regression tests and may communicate with the server.
Milestone 1
Complete the entire in-memory Anzo JavaScript RDF API consisting of the classes mainly the anzo.rdf namespace.
Sub-Milestone 1.1
Milestone 1 will demonstrate an entire JavaScript RDF API with the ability to
- create in-memory named graphs.
- add/remove statements.
- search for statements via patterns.
- listen for events fired on graph changes.
This milestone sets the most basic data structures such as Resources, Literals, URIs, Statements, NamedGraphs and QuadStores.
Sub-Milestone 1.2
Optimize the in memory QuadStore to make it as fast as possible while at the same time having a small memory footprint.
Milestone 1 Example Feature Usage
Add statements to a new graph and read back the results the results. Handle the addition events and ensure they all arrive. Remove some statements from the graph and ensure that they are removed and the deletion events all occurr.
Milestone 2
Add parsers for loading graphs from strings in various formats such as RDF XML and N-Triples.
NOTE: This is a small addition to milestone 1 and is separated because it is a distinct task that may be prioritized differently and possibly moved later in the development process.
Milestone 2 Example Feature Usage
- Parse an N-Triple document into memory and query the graph using the find method to assert that various statements exist.
- Prase an RDF/XML document into memory and query the graph using the find method to assert that various statements exist.
Milestone 3
This milestone adds the beginning of communication with the Anzo server. It adds support for creating a graph which can be replicated to/from the Anzo server via the JMS/Cometd network protocol. This milestone introduces the DatasetService class which models the Anzo repository.
We split this milestone into subsections where the milestone is partially complete.
Sub-Milestone 3.1
The DatasetService at this milestone will have the ability to
- create a ReplicaGraph graph object backed by the repository.
- group additions and deletions into transactions via the begin/commit/abort methods.
- send the transaction queue to the server to commit the changes to graphs.
- read statements from the in memory store
This sub-milestone encompasses the management of the transaction queue and sending it up to the server.
Sub-Milestone 3.2
This sub-milestone adds the remaining portion of replication. It adds the ability to create a LocalGraph that will pull down store a replica of graphs from the server. It will also have the ability to
- register selector trackers to affect which portions of the graph are replicated to the client.
- receive contents of a graph from server based on the registered trackers during replication.
- fire events to signal replication progress.
- fire events to signal changes on graphs.
- replicate either manually, on a scheduled internal (automatic), or upon committing a transaction (immediate async).
The system at this point must be able to properly handle error in preconditions and errors in transactions. It must report the errors to the API user appropriately.
Milestone 3 Example Feature Usage
Create a new replicated graph. Add the data from a FOAF N-Triples document to the graph. Replicate the graph to the server. Now, close the original graph and create a new local graph pointing at the same named graph. Add a command that adds a new person to the graph but only if a particular person exists. That is, use a Command with a precondition. The precondition should be one that is expected to fail. Replicate the graph. Verify that the transaction Command wasn't run failed and that the graph brought down the original FOAF data.
Milestone 4
Notification is main addition in milestone 4. The DatasetService will gain the ability to register trackers such that notifications of any changes on the server that match those trackers will fire events on the client and store the additions and removals in the appropriate graphs for query.
Milestone 4 Example Feature Usage
Create a local graph and fill it with some FOAF data. Replicate the graph to commit it to the server. Open a new local graph based on a different DatasetService pointing at the same named graph on the same server. Register a tracker on the second graph to listen for new FOAF people being added to the graph. Now add a new FOAF person using the first graph. Listen for the tracker event in the second graph. Once it fires, read the data FOAF data from the second graph. It should contain the newly added person.
Milestone 5
Milestone 5 focuses on adding SPARQL Query support to the Anzo JavaScript client library. In this milestone SPARQL queries will only be sent to the server for execution. The milestone will allow callers to send an arbitrary SPARQL query and receive result sets, graphs, boolean results, etc. as the query requires.
SPARQL queries will not be executed on the replicated data on the client. They will go directly to the server for execution in this milestone.
Milestone 5 Example Feature Usage
Create a local graph, add some FOAF data to the graph and replicate to commit the data to the server. Perform a SPARQL query on the server and verify the results.
Future Work
The above milestones describe the immediate plan and the milestones that have been gone through a design process. There is more functionality that may be considered for future milestones such as
- Performance Analysis and Optimization
- Possible Optimization Idea: Cache the data from recently closed ReplicaGraphs so that if someone opens a new ReplicaGraph to the same graph URI soon after somebody just closed another for the same graph URI, the replication will reuse the already replicated data.
- Client SPARQL queries
- Client-persisted replicas and transaction queues (perhaps via Google Gears). This possibility has been considered in the design of the initial milestones so that persistence fits in the architecture.
Milestone Dependency Analysis
M1 ----> M2
|
|--> M3 --> M4
|
|--> M5
Time Estimates
Estimates are in person days. See below for explanation of this document's idea of person days.
Detailed Initial Design: 3 pd Milestone 1: 3 pd Milestone 2: 2 pd Milestone 3.1: 5 pd Milestone 3.2: 10 pd Milestone 4: 5 pd Milestone 5: 4 pd Create Unit Testing Helpers: 3 pd Tutorial Documentation: 3 pd
Total: 35 pd
A rough calendar time estimation accounting for the number of people working and some overhead in a non-scientific manner yields that the task can be complete in: 1 month.
- person day (pd)
- one person working without interruption for 8 hours on the task.
These estimates include time for: * coding * writing unit tests * debugging * javadoc of code and comments within * minor design done during coding
It does not include: * writing guides and tutorials as documentation * preliminary detailed design for the task
Unit Testing Strategy
To effectively unit test Anzo.JS without the presence of a server, we will build a JMS client provider that will returned canned responses based on investigating the request.
The Maven build will run the unit tests using the Dojo D.O.H framework on Rhino.
Asynchronous tests may have problems running in Rhino so a solution will be explored for handling that.
Unit tests will also periodically need to be run on IE due to different behavior in JavaScript implementations.
Alternative Unit Testing Strategy
To unit test Replication, Notification, and transaction components in the Anzo client, we will create simple stubs that implement the ModelService, ReplicationService, and NotificationService.
To test the actual JMS-based service, we will separate the communication code from the (de)serialization logic. We will unit test the (de)serialization logic. The communication logic (cometd/Bayuex) will be tested only when communicating with a real server in integration tests, other than basic method unit tests.
A Unit testing AHA' moment
The problem with testing our asynchronous operations in anzo.client is predicated on the assumption that the calls are actuallying being invoked asynchronously. That is, the callbacks are invoked some unspecified time after the call itself returns. However, if we are using a dummy implementation of JMSClient then we can make sure the callbacks, and in fact notifications as well, all fire before we return from JMSClient.requestResponse. So for testing all of the anzo.js functionality, we avoid the async testing problem. However, we still have the problem we went want to run regression tests on the messaging system itself.
To implement the dummy JMSClient we simply create an object that maps request-signature to a JSON object. These expected request response pairs will of course be implemented in conjunection with the tests to which they correspond. In fact, we need not implement a whole new JMSClient. The unit testing code can simply say
JMSClient.requestResponse = function(msg, callback) {
callback(requestResponsePairs[getMessageSignature(msg)]);
}
An automated trace mechanism for anzo.js and in fact, dojo in general.
The main issue we have with dojo's loading mechanism is that it hides the line number from us when stuff goes wrong in Firefox, making it really difficult to figure out where errors occurred. It's manageable when we are debugging while building up the system because we know what code has changed, and where things could have potentially broken. However, when Mojo lenses and other Anzo.JS based apps are deployed in the field, we will be completely clueless as to where problems in Anzo.JS are occurring.
A way to help us narrow down the problem is through entry-exit trace logging. We have added automatic entry/exit tracing to Anzo.JS. Read more at AnzoJSLoggingGuide.
Note that with entry-exit trace in JavaScript we don't get getter and setter tracing because most of that is done via direct member variable references. However, in Firefox, for example, we can actually map a particular member variable to a getter and setter such that accesses go to the setter, and assignments go to the getter. However, many of the objects are not defined at initialization time. This may be worth investigating in the future.
Various debugging strategies are also discussed in the Anzo.JS Debugging Guide.


