CRXDE Lite is a web-based repository browser for CRX's JCR repository and a development environment for CQ5 Platform in CRX, based on Apache Sling content delivery and development platform and Apache Felix OSGi runtime framework.
In contrast to the CRX 1.x Content Explorer, which maintains a server-side CRX session, CRXDE Lite handles all modifications directly within the browser and uses the JCR remoting interface to retrieve content and persist changes.
This article looks behind the scenes of how this rich set of functionalities was implemented in the browser. CRXDE Lite functionality and tips&tricks for using it were presented in the previous blog entry on CRXDE Lite.
CRXDE Lite Design Goal. The most important design goal for CRXDE Lite was providing rich functionality with a near-desktop experience in a web application. There were three main architectural decisions we had to make while designing CRXDE Lite:
- Where to host the CRXDE Lite web application?
- How to implement remote access to JCR repository & server-side features from the browser user interface code?
For the user interface framework the natural choice was the ExtJs library, which provides good user experience and is used in CQ5 Platform hosted in CRX. It also has a good internal architecture, separating the underlying model from the view.
For the deployment model, we decided to host the CRXDE Lite application in CRX's web application. It minimizes the dependencies on other parts of the system, like OSGi container & Apache Sling content delivery platform. CRXDE Lite is available also when Apache Sling does not run, which helps in cases of system troubleshooting, recovery, etc.
ExtJS provides a good separation of model and view. In ExtJs, list-style content, like properties of a node, is stored in records which are maintained by so-called stores. Stores are responsible for retrieving and persisting the content and defines the serialization format and the server endpoint. For tree-style data, like JCR nodes, ExtJS defines a tree node type that handles the common properties of a node like display text, parent node or child nodes. When a tree node is assigned to a tree the rendering of that node is delegated to a separate configurable view class. Retrieval of data is managed by an instance of the tree loader class.
For CRXDE Lite we make use of both, JCR nodes are represented as tree nodes and properties of a node are handled as records. To integrate with the JCR remoting server endpoint a custom tree loader was implemented that is able to deal with the JSON format that is used by JCR remoting and which creates nodes and records for the properties of a node.
The records for properties can be displayed and edited in the property grid at the bottom. Once a record was edited it automatically gets marked dirty so we can easily find modified records when we want to persist our changes.
Handling content changes. If a new node is created, it gets marked as transient and gets added to a list of transient nodes that is maintained by the store. Like with dirty records this allows for easy finding of new nodes in order to persist them. Deleting a node that is already persisted does not remove it automatically from the tree but just hides the according node and all its children. This allows to easily revert such changes by just displaying it again. We don't need to keep the path somewhere. If changes are persisted those nodes are deleted on the server first and only if this was successful they are deleted locally.
When the changes that a user has made should be persisted, the transient storage generates a multi-part message body that is send via an AJAX call. Once all changes are persisted and the call returns successfully all dirty flags are removed from the according records, the list of transient nodes gets cleared and deleted nodes are removed from the tree.
Note: The current version of CRXDE Lite persists all changes since the last save operation at once, which is similar to saving the changes made in a CRX Session. Future version might support more fine grained support for saving so you can just save single files like with a Desktop based IDE. While this is technically possible with JCR remoting, it will require some more research on display models and user feedback. Imagine you want to save a file whose parent is a transient node and not stored in the repository yet. In this case you either need to persist the parent automatically or prevent saving only that file in which case we need some means to find the parent that can be saved.
Plugins. CRXDE Lite architecture is internally based on a plugin concept. The plugin architecture helped us to develop and maintain CRXDE Lite code in a clean, modular manner.
The first parameter has to be the ID of the widget that will be extended (e.g., the ID of a menu or toolbar) and the second will be the plugin class.
Each plugin has to provide 2 static methods:
canHandle(context): check if plugin is active for the current context (e.g., menu item active for selected node
getInstance(context, args): return instance of the plugin
Note: CRXDE Lite Plugin API is not yet a supported CRXDE Lite feature as of CRX 2.1 and is only used internally by the implementation. It may change or be removed in the next versions.
At the moment plugins are not loaded from the repository but have to reside in the web-apps working directory and added to the index.jsp manually. One of the possible extensions in the future future would be to allow loading of the plugins directly from the repository so you could modify and adapt CRXDE Lite according to your needs.