BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Articles Interactive Microservices as an Alternative to Micro Front-Ends for Modularizing the UI Layer

Interactive Microservices as an Alternative to Micro Front-Ends for Modularizing the UI Layer

Key Takeaways

  • Micro front-ends are an attempt at bringing the benefits of microservices to the UI layer, but the rate of adoption by the IT community has remained tepid so far.
  • Qworum is a Platform-as-a-Service that defines the interactive microservice concept as an alternative to, and also a complement for, micro front-ends.
  • In contrast to micro front-ends, Qworum enables unbounded composability, full-page UIs and distributed web applications in both intra-organisation and cross-organisation settings.
  • Qworum empowers software architects to formulate UI modularity in terms of composable web APIs, which may be a more familiar level of abstraction for some architects compared to micro front-ends.
  • Whereas the World Wide Web and the Semantic Web are about interlinked content, Qworum’s Service Web is about interlinked services.

Microservices architectures have found widespread adoption amongst the IT community, as is confirmed by InfoQ’s latest Software Architecture and Design Trends Report, with microservices and event-driven architecture being listed in the “late majority” section of the report.

A fact that may seem surprising in this report is that micro front-ends are still mentioned in the “early adopter” bracket rather than being listed as a late majority trend alongside microservices. This is despite the general availability of several mature micro front-end frameworks. What is more, a survey conducted in 2020 among 650+ tech leaders has found that only 24% of respondents had made use of micro front-ends. 

One can only conclude that, while microservices architectures are well established for the backends of software systems, the same cannot be said for front-ends. Needless to say, having front-ends that are still mostly monolithic represents an operational and productivity bottleneck for large scale software systems where several DevOps teams are involved.

It appears that there is room for new technologies on the front-end that are complementary to, or a replacement for, micro front-ends. Enter interactive microservices.

Interactive microservices

Interactive microservices, also called Qworum services, are a new concept that is being pioneered by the Qworum platform for modularising web front-ends.

Multi-phase web APIs

Interactive microservices are based on a new type of web API that Qworum defines, the multi-phase web API. What differentiates these APIs from conventional REST or JSON-RPC web APIs is that endpoint calls may involve more than one request-response pair, also called a phase.

Multi-phase call receiving call arguments and returning a result

If a call has arguments, Qworum will not actually send those to the server, but will make them available to the called service in the browser. If necessary, the called service can then send the data to a server by itself without using Qworum.

HTML-based user interactions

Being multi-phase allows endpoints to interact with the end-user through web pages before returning a result. This is how microservices become interactive.

Interactive multi-phase call

Service composition

Another significant feature of Qworum is that endpoints can call other endpoints, and even themselves, by telling the web browser to make the call on their behalf. These other endpoints can be hosted on the same website as the caller, or on other websites anywhere on the web.

Service composition mediated by the web browser

A new top-level web format

You may be wondering how a Qworum service performs a nested call, and how these services return a result.

For this purpose, Qworum defines a new top-level web format called the Qworum script. Qworum-enabled browsers have a built-in interpreter that can run these scripts. See the section titled “The Qworum script” below.

The user experience 

The experience of using Qworum-based web applications is similar to using conventional web applications. 

One difference the user will notice when using a Qworum application is that the DNS domain of the page that the browser shows can change from time to time, although all pages will feel as an integral part of the application. This is because Qworum applications are distributed applications that can be built by combining several Qworum services that are hosted on different origins. A video showing a Qworum application that spans several DNS domains is available on YouTube.

Example of a user flow that spans several origins and DNS domains

A second difference is that the browser’s back button becomes useless for navigating back in the history of the application’s UI, because Qworum applications and services take care not to add new entries to the browser tab’s history during execution. The reason for this restriction is that otherwise the application’s UI could go out of sync with the application state that Qworum attaches to tabs.

Differences with micro front-ends

Several differences between Qworum and micro front-ends are already apparent at this point:

  • Unbounded composability — Interactive microservices can call other end-points and even themselves during their execution. The maximum depth of allowed nested calls is unbounded, and each call disposes of a full-page UI regardless of nesting depth. This is unlike micro front-ends which typically cannot be nested beyond 1 or 2 levels at most, because the UI surface area that is allocated to each micro front-end becomes vanishingly smaller with increasing nesting depth.

  • General applicability — Qworum services are more generally applicable for distributed applications than micro front-ends, as the latter are generally tied to a particular web application (ad hoc micro front-ends), front-end framework (React micro front-ends, Angular micro front-ends etc) or organisation (micro front-ends are generally not shared between organisations).

Qworum’s “everything is a microservice, including applications” UI paradigm and the “micro frontends plus container applications” UI paradigm

A new web browser capability

Qworum brings the following tried-and-true computing mechanisms to the web environment:

  • Subroutines — Subroutines are the most fundamental mechanism by which software is made modular. This mechanism is so fundamental that most if not all CPU instruction sets have opcodes for calling, and returning from, subroutines. In high-level programming languages, the subroutine manifests itself as procedures, functions and methods. Qworum’s endpoint calling mechanism is another high-level manifestation of subroutines.

  • Objects — In object-oriented programming, an object primarily serves as a container for data that is shared between, and remains accessible to, a set of subroutines, called “methods”, during the lifetime of the object. This concept manifests itself in Qworum as Qworum objects, which are useful for implementing stateful services such as shopping carts.

Framework and beyond

To be clear, Qworum isn’t yet another JavaScript framework that makes it easier to work with the browsers’ existing capabilities. Rather, Qworum itself defines a new browser capability that web applications can leverage.

So although there is an official Qworum JavaScript library for web front-ends, this library is only a thin layer over the capability offered by the official Qworum browser extension. Qworum currently supports Chromium-based browsers, and support for all other mainstream browsers is on the short-term roadmap.

Qworum’s official extension as installed on Google Chrome

A new in-browser data storage mechanism

The reason why Qworum cannot be implemented as only a JavaScript library and why Qworum requires an implementation in the form of a browser extension or a native browser implementation is that browsers are currently geared towards enabling single-origin web applications, whereas Qworum allows for distributed web applications, which is a new and more general concept that is being pioneered by Qworum. Here is a point that illustrates why current browser capabilities are not enough for supporting distributed applications:

  1. Standards-compliant web browsers are required to implement the so-called same-origin policy for the purpose of isolating origins from each other. This policy notably states that “JavaScript in one origin cannot read from or write to the storage belonging to another origin”.

  2. The same-origin policy is too restrictive for Qworum, because Qworum sessions make use of a single call stack that all Qworum services in a session must be able to have access to, regardless of their origin. In conventional programming it is standard practice for a thread of execution to have a single call stack as well. So instead of a per-origin data separation policy, Qworum implements a new finer-grain per-object data separation policy. This policy mandates that (1) all phases of endpoints belonging to the same Qworum object must be contained within one single origin, and that (2) a Qworum object A can only access data belonging to another Qworum object B if A contains B or if B calls one of A’s endpoints and passes its data as call arguments. In addition to this policy, Qworum objects can further take the initiative of denying service to callers based on the caller’s URL as indicated by the Referer header in HTTP(S) requests. This last point means that even if A contains B, in some cases B will not provide meaningful data to A.

Qworum uses these per-browser-tab cross-origin call stacks internally for handling service calls and data during the execution of Qworum applications. The call stacks only exist during application execution, and they are deleted when an application exits or the application’s browser tab is closed by the end-user. This is similar to opening up a Deno or Node REPL session in a terminal, and having all session objects automatically deleted on exit.

Note that although the browsers’ History API already provides a stack-like structure for attaching data to browser tabs, this data structure is unsuitable for managing Qworum’s call stack, because the two data structures are addressing different use cases and because the History API’s data stack is directly accessible to web front-ends and can be tempered with or used for purposes that are independent from Qworum.

Enabling Qworum for a website

Qworum will only work on a given website if all of the following conditions are satisfied:

  • The Qworum extension is installed on the browser.
  • The Qworum extension has not been disabled by the end-user.
  • The website’s DNS domain is currently subscribed to Qworum. By default Qworum is only enabled for local development.

Websites can use the Qworum JavaScript library for checking these conditions, and prompt the end-user if they are not met.

Programming with Qworum

The Qworum script

Qworum defines a new top-level web format, the Qworum script, in the official Qworum specification. This is an XML-based format that web servers will sometimes send to browsers instead of an HTML page. XML has the property of being styleable, which allows script content to be hidden from the end-user.

Qworum scripts are served by web servers as standard XML documents, with either application/xml or text/xml as the content type. Browsers will understand that an XML document is in fact a Qworum script by looking at the namespace of the document’s root element. 

The recommended file extension for Qworum scripts is .qrm.xml. Qworum provides an official Visual Studio Code extension for facilitating the creation of static Qworum scripts. This extension currently only provides snippets. Additional planned features include checking the script syntax and the syntax of any JSON or semantic data that scripts may contain, as well as syntax highlighting for the embedded data.

Qworum’s official VS Code extension in action

Client-side script generation

Qworum scripts do not have to be sent to browsers from servers as XML. Web front-ends can also generate and execute them through the official Qworum JavaScript library.

In the library documentation, one API method that the reader will notice is Qworum.eval() which allows the execution of dynamically generated Qworum scripts. Knowing that the use of eval() in JavaScript code is considered a security risk, one question that may come to mind is whether Qworum.eval() is safe to use. The answer, reassuringly, is yes, for the following reasons:

  • Qworum scripts are written in a domain-specific language rather than a Turing-complete language. Qworum scripts can only redirect the end-user to new URLs or close browser tabs.
  • Redirections that are initiated by Qworum scripts consist of HTTP GET requests. In other words Qworum scripts do not send any data to servers.
  • Qworum scripts only have indirect access to the Qworum call stacks through the Qworum browser extension which stores and manages them internally. The browser extension has oversight on what the scripts can do with the call stacks.
  • Qworum scripts do not have access to the data that web front-ends store in client-side storage such as localStorage, sessionStorage and IndexedDB.

The user experience

Most Qworum scripts will redirect the end-user to a new URL when executed. For example, the links and buttons of this sample e-commerce demo project all execute Qworum scripts which will redirect the end-user when clicked on.

Clicking on a button runs a Qworum script which redirects the user (see video)

In some cases a Qworum application will exit by closing its browser tab. One reason this can happen is when a Qworum script’s evaluation raises a fault that is not caught by the application. Qworum applications should prevent this situation wherever possible, as this disrupts the user experience.

A Qworum application exits due to an uncaught fault (see video)

A sample Qworum application

Let’s go into more detail about how the e-commerce demo project mentioned above works. Note that Qworum is currently more useful for business and enterprise applications rather than for consumer applications, because browsers do not currently come with Qworum pre-installed.

Pseudocode

We’ll first describe at a high level how the distributed e-commerce application is structured. Any object-oriented programming language is suitable for this task, because the Qworum platform is itself object-oriented. We will use TypeScript. Note that this code is not meant to be executed by Qworum. Rather, it is meant to help the reader understand how the distributed application is structured.

The pseudocode below describes a software system consisting of two types of Qworum services:

  • E-shops with two interactive endpoints home() and viewArticle(), and a shopping cart as the object state.

  • Shopping carts with two interactive endpoints addItems() and showCart(), and the cart total and the list of articles as the object state.

Pseudocode for a distributed Qworum application consisting of two services (source code)

This pseudocode describes an e-shop Qworum application that depends on a shopping cart Qworum service. By convention, all interface methods are assumed to represent interactive Qworum API endpoints. 

Using Qworum’s JavaScript library

Before using Qworum from JavaScript, web pages first need to import the Qworum library. The figure below shows how this is done.

Importing the Qworum JavaScript library (source code)

You will notice in the pseudocode above that e-shop Qworum objects contain a shopping cart object. This means that any e-shop endpoint has access to the cart’s total and its list of line items. For example, an e-shop endpoint can read the cart total by using Qworum.getData() as follows:

An e-shop endpoint reads cart data (source code)

Qworum.getData() receives the data container’s path as the call argument. In the code above,  Qworum.getData() will look for a data container named ‘total’ which is contained in a Qworum object named ‘shopping cart’ which in turn is contained in the Qworum object that owns the current Qworum endpoint call, as indicated by the ‘@’ path element.

A Qworum.setData() method is also available for setting the value of a data container.

A shopping cart endpoint sets the cart state (source code)

Generating and executing a Qworum script is equally easy:

The shopping cart’s showCart() endpoint ends its execution (source code)

This will redirect the end-user to a new URL. Web front-ends could want to check whether the browser is online before executing a Qworum script. The current Qworum implementation assumes that the browser is online, although in the future a script that attempts to initiate a redirection could automatically raise a network fault when offline.

Note that Qworum endpoints do not know what happens after their execution is finished. Contrast this with the current situation where web applications must pass a return URL to the login dialog page for example, and they must even pass several return URLs if they want to handle error conditions on separate return pages. The takeaway from this example is that Qworum makes web programming much more similar to conventional programming than is currently the case.

Some execution flows

When the end-user clicks on the add-to-cart button in one of the e-shop’s article details pages, the following JavaScript function gets executed:

User adds an article to the shopping cart from the e-shop application (source code)

A couple of remarks about the code above:

  • When the call instruction gets executed, this will not terminate the script’s execution but merely interrupt it, and the script’s execution will resume when the call returns a result or raises a fault.
  • When the call to the cart’s addItems() endpoint finishes, this will also finish the e-shop’s viewArticle() endpoint call. This is because the top-level sequence instruction will yield the result that is returned by addItems(), and when the top-level instruction yields a result in a Qworum script, then the current endpoint call returns that result.
  • If the goto instruction were uncommented, then the viewArticle() endpoint call would instead continue with its next phase as defined by goto when addItems() returns.

Now let’s examine what the shopping cart does when its addItems() endpoint is called. Here is the function that gets executed:

The shopping cart updates its stored session state when new items are added (source code)

Again a couple of remarks:

  • Call arguments are available to Qworum endpoints as local data that is readable using Qworum.getData().
  • The addItems() endpoint merely updates the cart state without interacting with the end-user; it calls the showCart() endpoint for showing a UI to the end-user.
  • The addItems() endpoint will return the same result as the nested call to showCart().

As this example shows, Qworum brings a set of highly effective object-oriented programming primitives to web developers.

Enterprise and business use cases

Although this article is mainly a technical description of the capabilities provided by the Qworum platform, I will briefly touch upon using Qworum as a Platform-as-a-Service offering for enterprise and business software. 

Qworum is a general purpose platform that is particularly well-suited as an infrastructure for microservices architectures, because Qworum helps modularize the UI layer of software systems.

Vendor use cases

Some of the scenarios that Qworum enables for software vendors are as follows:

  1. An enterprise suite vendor uses Qworum internally for integrating the different elements of their enterprise suite.
  2. An enterprise suite integrates with best-of-breed applications.
  3. Several independently available best-of-breed applications are integrated using Qworum.

Deployment use cases

Qworum is suitable for all types of deployments and integrations, from on-premises to cloud, and from tailor-made software to off-the-shelf software to SaaS.

A sample project management application

An example might be a project management application which integrates with an HR application, a resource reservation application and an online collaboration application. Although this article doesn’t include working code for this use case, here is what the pseudocode for such a system might look like:

High-level description of a distributed project management application (source code)

Intellectual property

Multi-phase web APIs were first described in the utility patent titled “Method and a system for the composition of services”. Although this patent has since expired, obtaining additional patents for new Qworum features remains an option for preventing platform fragmentation, as fragmentation would adversely affect developer productivity.

Although Qworum is a commercial operation, the wider IT community is naturally welcome to contribute to the official Qworum Google group any feedback, suggestions and requests as pertains to the official Qworum implementations or the Qworum specification.

Conclusion

It is worth remembering that the World Wide Web was initially conceived as a platform for content rather than applications, so while Qworum may seem like a rather big update to the web platform,  it is hardly surprising that there is still room for improvement in terms of providing better support for applications on the web given the web’s history.

In summary, what Qworum brings to the web platform are advanced browser features that are productivity boosters and use case enablers for devops teams working with microservices architectures.

About the Author

Rate this Article

Adoption
Style

BT