Design Notes

Component Preparation

When the code was added to the 2.1 Sakai release, it became apparent that it would be difficult to extract a clean component/service/api layered structure. If we use any hibernate based components that are loaded from the component, shared or server class loaders in the request cycle it will become necessary to complete this refactor.

Package Sub Tree: uk.ac.cam.caret.sakai.rwiki.service

All packages in this subtree are pure API, that can be placed in the shared area. They do not depend on components or tool.

Package Sub Tree: uk.ac.cam.caret.sakai.rwiki.component

All packages in this subtree are pure Component. They depend on the service api. They are used by the tool. It is expected that this super component will be deployed under the components class loaded in the future. All Hibernate DAO's and related POJO implementations are at this level. There is nothing specific to the tool at this level.

Package Sub Tree: uk.ac.cam.caret.sakai.rwiki.tool

The tool implementation is located in this package, which will in the future be deployed in the war.

Status

Currently this code is only available under the Sakai 2.1 local branch which mirrors the main Sakai 2.1 Trunk work. We have not separated the deployment descriptors, so the application is still stove pipe in nature.

Model Implementation

Seperated History

We have now separated the Current wiki objects from the historical or versioned wiki objects. They are no longer linked at the hibernate level but are linked at a higher level.

The aim of this approach is to avoid loading all the history content when a page is accessed. Lazy loading would have performed this, however the implementation of Lazy loading in Hibernate is such that we loose some control and often see multiple statements issued for each lazy object. The code now contains RWikiCurrentObject to represent the current objects in the model, and RWikiHistoryObject to represent the versioned objects.

  • Status: Implemented and tested
  • Loacation: In Trunk

Unlinked content

Even with the above restructure, Hibernate loads the content of each page when any field in the page is accessed. Hence the service method getRWikiCurrentObject will cause the whole of the content of the object to be loaded regardless of if we wanted to use the content or not.

In effect this means as a page is rendered, and the exists() method on the service is invoked, potential all the linked content could be loaded. It would be far better if a lightweight index object was available that contained the smaller fields and a lazy loaded content field was present in the RWikiObject (Current and History) to ensure that the content was only loaded when the content was required.

I don't know if you can have lazy loaded one-to-one relationships in the same table. If you can, then that will address the issue. If not then we will need a separate table with a one-to-one relationship with the 'index' table.

On further investigation one-to-one lazy loading in hibernate is not possible, we could use one-to-many lazy loading, but only ever have one.

One to many lazy loading does not make sense, so we have implemented explicit lazy loading with an object proxy to inject the necessary DAO objects so that loading can take place. This approach works quite well but has the drawback that we have to proxy the object, and that Lists need a proxy implementation, however this is far faster than using an AOP or introspection based proxy, as its direct method to method calls.

  • Status: Implemented and tested
  • Loacation: In trunk

Data Migration

The above generates a problem. When someone updates the wiki, changes in schema will cause and apparent loss of functionality and content. Hibernate will perform the schema update, but it will not migrate content to the new scheama. So objects derived from the new schema will be missing data.

We need a mechanism, hooked into the last ContextListener that tomcat invokes that will migrate the data. This could be a simple SQL statement that is run against the schema, or it could use the objects present in RWiki to do more complex transformations.

RWiki not has a context listener that loads an injected DataMigrationSpecification from spring. This Specification contains a list of DataMigrationAgents, which it uses, insequence to migrate the data between schema version. To perform the above migrations we have a sql script migration agent, that runs sql script against the database. This is almost the same as the update schema mechinsim in hibernate.

Since we have added SHA1 hashes against the content, we have also added a SHAHashMigration component that extracts all objects of a type from the database using hibernate, and then computes the SHA1 hash of the content before updating them. This is configred in components.xml

We have tested this on our content in sakai-beta, which contains about 200 pages with an average of 20 versions per page. On a G4 1.3 the migration process, on startup takes 27 seconds.

  • Status: Implemented and Tested
  • Loacation: trunk

Schema Version Control

In order to be able to perform schema data migration, we need to know which version the code is and which version the database is at, independant of Hibernate. A sepeperate object that stored persisntat site wide properties will be created. This object will store, amongst other things, version numbers. Once of these version numbers will be the database scheam version number. This will enable the data migration listener to invoke the correct sequence of sql data migration statements on startup.

If any of the statements fail, this operation will fail and refuse to allow the Tool to start.

See data migration above

  • Status: Implemented and tested
  • Loacation: Trunk

SHA Hash of Content

Since we now version every change to the page including history, we need a fast way of determining if the page has changed or not. We have added a SHA hash to the content that can be used for this purpose, without going to the expense of loading all the content. We still need to modify the History page to indicate where no content has been changed between pages. At the moment it just displays the hash.

  • Status: Implemented and tested
  • Loacation: Trunk

Diagrams

These shoul be links

Info Page

  • Info Page Wireframe
  • Info Page Wireframe v2

Permissions Rules Diagrams

  • Can Admin a page
  • Can Create a page
  • Can Read a page
  • Can Update a page

Code Sequence

  • Request Processing sequence
  File Modified

PDF File infopagewireframe.pdf

Apr 25, 2006 by Former user

PNG File infopage2.png

Apr 25, 2006 by Former user

PDF File canadminaction.pdf

Apr 25, 2006 by Former user

PDF File cancreateaction.pdf

Apr 25, 2006 by Former user

PDF File canreadaction.pdf

Apr 25, 2006 by Former user

PDF File canwriteaction.pdf

Apr 25, 2006 by Former user

PDF File requestprocessing.pdf

Apr 25, 2006 by Former user