Push presentation and control logic up to the browser

Push presentation and control logic up to the browserIntroduction

One of the important promises of Service Oriented Architecture (SOA) is that service clients, frequently front-ends, can aggregate data from multiple sources independently from the back-end technology. So far so good, however what if the front-end is a user interface and the UI is browser-based? Hmm, it’s getting interesting speaking about a browser UI which aggregates data from multiple back-ends. Wait a minute, browsers just render formatted data (HTML) provided by the back-end, so where is the hack? We’ve got tremendous computing power and JavaScript in the browser so let’s think about a browser contained user interface which communicates with the outside world only by XMLs and is implemented in JavaScript.

Push the Presentation & Control Logic up to the Browser

Implementing presentation & control logic within Service Oriented Architecture can be pretty confusing, as current “out of the box” solutions for web UIs rely very much on back-end components. The confusion comes from two sources:

  1. Although it is possible and strongly advised to logically separate the Presentation & Control Layers, they still run on the back-end, and more importantly they’re implemented with the same technology as the business logic. We all know “if it’s possible to intermingle somethin’, they’ll be mingled”.
  2. Where to inject the Service Bus?
  • Letting the Control Layer communicate with the service bus and keeping the business logic intact from the integration issues seems to be natural. After all, it is the control logic’s responsibility to aggregate / distribute data and transform UI events to business events anyway. However if you do so, you have to “marshall” and “unmarshall” objects from xml back and forth and invoke web services instead of normal method calls. Ouch!
  • Pushing web service communication down to the Integration Layer is more logical from a technical point of view and this also facilitates keeping the UI and corresponding business logic as an intact entity. Here however, for the Application, we’ve got to flow data coming from other sources through the Business Logic Layer. Ouch!

Push presentation and control logic up to the browser

To keep this post’s focus, I’ll stop discussing other considerations and even other architectural options at this point, and will land straightaway at my conclusion: What about pushing presentation & control logic up to the browser?
Doing so, we can expect three sorts of advantages:

  1. Logical design
  • Both the UI and the Business Logic subsystems are more self-contained, cohesive and able to provide restricted and straightforward access. The back-end provides web services; the front-end, the UI, directly consumes them. There is no presentation or business logic in the back-end and there is no business logic in the front-end. Both subsystems can focus exclusively on their own purpose.
  • By using distinct technologies in the two major subsystems of an application, there is less opportunity to mingle them together.
  • If data integration is only about simple data aggregation, then that can be done by the browser-based front-end. If data integration involves business logic, then that can be done by the Business Logic Layer. Wow, pretty straightforward.
  • As we can safely suppose that a modern browser UI features AJAX anyway, this architecture makes the concept that much more clear.
  • Technological
    By freeing the back-end server from processing presentation & control logic we can expect a significant performance boost. We can avoid extra object-xml marshalling and unmarshalling on the back-end.
    1. Development
      As both the front-end and back-end are self-contained subsystems with clear interfaces, it’s far easier to have them developed by different teams, which is the reality in many cases.

    Well, at this point, it might be wise to step back and take a look at the big picture, to see what we’ve been talking about.

    It’s a self-contained user interface, running in the browser and consuming web services from, potentially, any source available on the Internet.    

         Push presentation and control logic up to the browser
    With such a solution it will be possible, among other things, to develop useful applications just by aggregating and presenting existing data and functionality in a new way.

    Finally, let me share a less causal argument. More and more applications feature a browser-based UI; in fact many don’t even have a GUI. An implication of this trend is that “The Browser” becomes the operating environment for the UI, for the front-end, and therefore we need UI libraries running in the browser. Think about the advances of HTML5. From this point of view the situation is similar to the mid 80’s when windowing UIs started to evolve.
    This series of posts is about a working solution for such a browser-based UI library written in JavaScript.

    Bird’s Eye View of the UI Library

    If we want to stick with the idea that the front-end communicates with the back-end only through web services, we then need a component which interprets SUIML (a Simplified UI Markup Language) and builds up the complete UI. That’s exactly the purpose of the DesktopConfigurator in the diagram below. As long as DesktopConfigurator is responsible for creating fundamental parts of the UI such as headers, footers, columns and panels, SmartDocuments and BrowserWidgets fetch data XML, render this data according to a document definition and also handle the user interaction. Yeah, and here is a nice twist: the desktop itself is composed of widgets and documents. The header and footer, the panels, all contain documents and widgets. As this UI library starts to become more complex, it is sensible to embed a WebUILogger. An extra bonus of having logging capability in the browser is the ability to perform custom user activity analysis. A component UserAnalitics (not depicted in this diagram) can aggregate user actions and send processed data to the back-end.

    Push presentation and control logic up to the browser
    Ok, let’s take a step closer to the JavaScript UI Library and take a look at some code skeletons:

    var DesktopConfigurator = new Class({
    Implements : [Events, Options, TimeOutBehaviour],
    options : {...},
    initialize : function( webUIConfiguration, resourceBundle, options ) {
    this.componentStateManager = Class.getInstanceOf( ComponentStateManager );
    this.columns = new LinkedHashMap();
    this.configurationXml = new XmlResource( this.options.configurationURI, { 
    nameSpaces : this.options.configurationXmlNameSpace });
    this.logger = Class.getInstanceOf( WebUILogger );
    this.messageBus = Class.getInstanceOf( WebUIMessageBus );
    this.panels = new LinkedHashMap();
    this.resourceBundle = resourceBundle;
    this.state = DesktopElement.States.UNINITIALIZED;
    this.webUIConfiguration = webUIConfiguration;
    this.windows = new HashMap();
    //Public accessor and mutator methods
    construct : function() {...},
    destroy : function() {...},
    showNotification: function( notificationText ){...},
    showWindow: function( windowName, onReadyCallBack ){...},
    unmarshall: function(){...},
    webUIMessageHandler: function( webUIMessage ){...},
    //Protected, private methods
    configureLogger : function() {...}.protect(),
    determineCurrentLocale : function() {...}.protect(),
    loadResources: function(){...}.protect(),
    loadI18Resources : function() {...}.protect(),
    subscribeToWebUIMessages: function() {...}.protect(),

    As you can (and should!) deduce from the method names, creating the whole desktop consists of three simple steps:

    var desktop = new DesktopCofigurator(...);

    This doesn’t seem to be overwhelming, but what about creating and displaying content? You just need to instantiate one or more Smart Documents:

    var SmartDocument = new Class({
    Implements: [Events, Options],
    options: {...},
    initialize: function( i18Resource, options ){
    this.logger = Class.getInstanceOf( WebUILogger );
    this.messageBus = Class.getInstanceOf( WebUIMessageBus );
    this.state = AbstractDocument.States.UNINITIALIZED;
    //Public mutators and accessor methods
    construct: function(){...},
    destroy: function(){...},
    unmarshall: function(){...},
    webUIMessageHandler: function( webUIMessage ){...},
    //Protected, private helper methods
    attachEditor: function(){...}.protect(),
    constructBody : function(){...}.protect(),
    constructFooter: function(){...}.protect(),
    constructHeader: function(){...}.protect(),
    loadDocumentContent: function() {...}.protect(),
    loadDocumentDefinition: function() {...}.protect(),
    loadResources: function(){...}.protect(),
    subscribeToWebUIMessages: function() {...}.protect(),

    again in three simple steps:

    var document = new SmartDocument(...);

    In case you want highly interactive elements, like a calendar, tree or video player either within panels or even within the documents, you have to instantiate one or more widgets. Let’s see what this looks like:

    var BrowserWidget = new Class( {
    Implements : [Events, Options],
    options : {...},
    // constructor
    initialize : function( options, resourceBundle, elementFactoryOptions ) {
    // private instance variables
    this.state = BrowserWidget.States.INITIALIZED;
    // public accessor and mutator methods
    construct : function() {...},
    destroy : function() {...},
    restoreComponentState : function() {...},
    storeComponentState : function() {...}.protect(),
    unmarshall : function(){...},
    webUIMessageHandler : function( webUIMessage ) {...},
    // Properties
    // Private helper methods
    broadcastConstructedMessage: function(){...}.protect(),
    loadWidgetContent : function() {...}.protect(),
    loadWidgetDefinition : function() {...}.protect(),
    subscribeToWebUIMessages : function() {...}.protect(),
    var widget = new BrowserWidget(...);

    You might (and I really hope you do) discover a few recurring patterns. All building blocks of the user interface have unmarshall(), construct() (and destroy()) methods, and furthermore they are referring to two instances of XMLResource, namely definitionXml and contentXml. These are the consequences of restricting the communication between the browser and the back-end to XML only. That will be the focal point of my next post.

    Stay tuned and please provide feedback!