Packaging Fiori Applications – Architecture and Life Cycle Management
SAP Fiori is SAP’s new web-based User Experience approach going forward. Being designed for omnichannel consumption of information, it is a natural fit with SAP’s Mobile offering. Nevertheless Mobile Computing is a broad field that comes with its own specific requirements and challenges. This paper discusses some advanced topics centred around architecture and life cycle management that apply to Hybrid applications in general, and to SAP Fiori in particular. First a description of various consumption models is given. Then the strengths and weaknesses of these approaches are presented. Finally reference architectures for Life Cycle Management are given for each of the approaches.
How to Create The Offline CRM App Part 1 | Part 2 | Part 3 | Part 4
Fiori applications are typically consumed via standard browsers on desktop computers. In this scenario the Fiori Frontend Server (FES) acts as a web server, providing both the web applications and the underlying web services on a single host. Since Fiori apps are thick clients, the server does not need to provide any complex services beyond what is encapsulated by the OData services serving the corresponding application.
Figure 1 depicts this situation using the example of the Fiori Launchpad itself. It should be noted that it is not treated specially by the FES, making it a regular Fiori application. In this case we assume a simplified scenario, where the Launchpad is loaded as a whole, and does nothing but querying its associated OData services for the current user’s Fiori application catalog and configured home screen tiles. In reality Fiori applications are typically loaded in modules, meaning that requests retrieving code and data are interleaving each other. This applies to the Fiori Launchpad in particular, since it first retrieves the minimal amount of information required to display one’s applications. Only when an application tile is clicked, the remaining code for this particular application is being lazily loaded.
Figure 1: Standard Fiori client-server architecture and interaction
While this architecture implies that the application itself needs to be transferred to the client before it can be executed, it makes managing updates rather easy. Proper browser-based caching will ensure that round trips are reduced once the code has been transferred to the device, while still allowing code updates once the application deployed on the FES is changed centrally.
As can be seen in Figure 2, the Fiori Client runtime looks very similar to regular browser-based Fiori consumption. Most notably no changes on the server side are involved. The difference is that this consumption form applies exclusively to mobile devices, such as iOS and Android phones. Rather than opening a browser window to the Launchpad, the users are installing a proper application that emulates browser behavior. Technically speaking, the Fiori Client is a simple single-screen application, which contains a single WebView. Those views are used to embed HTML content from external and local sources into native applications, and in this case it is used to display the whole user interface in terms of the Fiori Launchpad. While this brings Fiori closer to a native experience in terms of a proper application icon on one’s phone home screen, it is important to note that from the server-side both consumption forms are equivalent.
Figure 2: Fiori Client client-server architecture and interaction
What is the added value of using the Fiori Client then? A look under the hood reveals that the Fiori Client is in fact implemented using Cordova, a hybrid application framework that exposes native device capabilities to web-based applications. While the HTML standard is generally catching up with the features available on the average computer (i.e., including phones) nowadays, there are still huge gaps. For instance, Cordova provides access to sophisticated capabilities such as the user’s personal address book, and even platform-specific features such as the iOS fingerprint protection. This generally enables developers to write true cross-platform omnichannel applications, while still allowing access to platform-specific features depending on the runtime environment.
Figure 3: Cordova Architecture. Based on the official documentation.
While the above setup generally works extraordinarily well under office conditions, it is important to note that we are in fact looking at a distributed system, and with that come the challenges particular to distributed computing, the most important one being the network itself. Despite the perceived stability of networks, they are very fragile especially in large scale. Not only are there many potential points of failure on longer routes, the data transfer rate typically also declines, leaving more time for failures to actually become apparent.
There is a multitude of possible causes of network failures, e.g. faulty hardware, peaks in data centers, or just the user moving between access points. Therefore in this section we are emphasizing the symptoms rather than the causes during two different points in time of the application life cycle: One while arbitrary code is being loaded, and one while data is being transferred.
Figure 4: Network failure during initialization
Figure 4 depicts the former scenario, in which a network outage occurs while code is being loaded. In this case the effects are difficult to anticipate, since it depends on which component exactly failed to load. Continuing the example of the Launchpad, here are some examples:
- The style sheets fail to load. The page works but looks broken.
- The application fails to load altogether and the WebView displays some network error message.
- Either of these errors may occur when a tile is clicked, resulting in a failure to open the corresponding application.
These scenarios have in common that it is generally very difficult to catch and handle the related failures, the problem being simply that an application that is not fully loaded is unable to handle errors of any kind. In addition browsers do not expose an API to detect script load errors from within the WebView, making recovery even more difficult. Regardless if the Fiori Client or a browser is being used, there is no reliable and consistent way to deal with these failures short of having the user reload the application until it works. Caching does help a lot to mitigate these issues, albeit only once the application has been loaded successfully and until the caches are invalidated.
Figure 5: Network failure after initialization
In comparison, failures while loading data, as shown in Figure 5, can be handled easily by the application itself. Since it should generally be assumed that any network request may fail easily, most applications should deal with this failure scenario out of the box, e.g. by automatically retrying a number of times or notifying the user that due to network issues the requested information could not be displayed. What is crucial in these scenarios is the distinction between code and data: Even though the same causes for failure may apply, error recovery in the latter scenario is much easier, simply because the code required to handle it is already on the device.
Packaging is a means of ensuring that failures such as depicted in Figure 4 can never happen by making sure the code is already on the device. This is actually the “intended” way of working with Cordova: When a template project is created from the Cordova Command Line Interface (CLI), a web app folder is actually created within the generated native application. The web app sources reside within this folder, rather than being loaded from the server. In that regard the Fiori Client is a special case, somewhere in between standard Cordova applications and the more traditional use of WebViews: While it enables the consumption of device-native features, it does not require you to have the application sources on the mobile device. This also makes it rather easy to derive the meaning of “Packaging” in the context of the SAP Mobile offering: It means moving the Fiori application code, including a Launchpad, from the server to the mobile devices, so that both native and web application code are installed alongside on the device.
Figure 6: Packaged application client-server architecture and interaction
Figure 6 outlines the difference to the other consumption models. Most notably it is irrelevant to the mobile application what is being deploy server-side in terms of web applications. The only thing that matters is that the required web services are up and running. This does not imply that there must not be application code deployed to the FES. On the contrary, both packaged and traditional applications may be used alongside each other.
As was discussed in the Section “Failure Scenarios”, the most obvious benefit of packaging applications is that network-related crashes are impossible, assuming that the packaged applications themselves are properly suited to deal with such situations. However, there is another benefit related to eliminating the network factor during initialization: Startup time. Especially the first start of a Fiori application may take longer than usual because the application code actually needs to be downloaded before it can be run. This means an occasional additional round trip, which may or may not be very noticeable depending on the network quality. Worst case the previously outlined failures may occur. On average the startup time is increased significantly due to the low transfer rates on mobile data networks. Once the applications are fully cached, best-case performance can be reached by saving these addition server round trips. Packaged applications, however, always guarantee the best-case application performance.
On the other hand, packaging is a typical time-space-tradeoff: Processing and network time is reduced by increasing the size of the built application. This is an issue with the average UI5 application since packaging also involves all dependencies of the packaged applications, and a full packaged UI5 distribution may lead to application packages well beyond eighty megabytes in size. However, considering that UI5 may be minimized in terms of the number of packaged modules, in practice the increased application package size may be neglected. Packaged applications and the Fiori Client alike are typically around thirty megabytes in size, most of that being plugins. For instance, the popular Crosswalk (XWalk) drop-in WebView replacement alone consumes around twenty megabytes in size on Android.
There also is an innumerable amount of differences in implementation details between a packaged Fiori application and the Fiori Client. While both are Cordova applications inside, the standard Fiori Client comes prebuilt with a huge number of plugins. This is the reason that the standard Fiori Client has a “double tap to open menu” feature, while standard packaged applications do not have it. Since both the Fiori Client and packaged applications may be customized to the heart’s content, this is more a matter of degrees than a sharp line between both consumption models. Generally a packaged application can be taken arbitrarily close to the Fiori Client in terms of behavior and features, and the other way around also works. It would, for instance, be possible to copy an arbitrary amount of Fiori applications and a Launchpad into a Custom Fiori Client project, and have the Custom Fiori Client display the local Launchpad rather than the FES Launchpad. Whatever is implemented in the Launchpad can easily be moved to packaged applications. The only real challenges are server-side components that are not part of the actual Launchpad, such as Gateway Logon classes. When the SAP Mobile Platform (SMP) is not used, it may be necessary to add a login view to the local Launchpad that sends the user logon data to the Gateway logon class.
However, the biggest open question is: How do the applications actually get from the FES onto the device, when they are not being loaded directly during runtime?
Life Cycle Management for the Fiori Client
In order to comprehend the full implications of packaging, especially when it comes to Life Cycle Management (LCM), we first need to establish a reference architecture for the development environment prior to packaging. For that purpose, we revisit the simplified architecture from Figure 1. Figure 7 shows the same situation in a bigger context. Most notably, it can be seen that the simplified model introduced in Figure 1 is actually replicated across a number of mostly identical system landscapes: One for development, one for tests, and one for production. This is in fact more an example than a fixed rule; there may also be less or more stages on the way from development to production. The important thing is that applications are deployed once to the first stage (development), where they are tested. Once the quality check passes, a transport is requested from the first to the second stage, effectively updating the application on the second stage to the version on the first stage. This is repeated from stage to stage until the application is finally being deployed in production. This does not only apply to the FES, but also to backend systems. The FES separates the upstream landscape simply by means of named connection mappings. The application itself does not know to which backend system it is talking, but requests a generic endpoint that the FES would resolve appropriately according to the system configuration.
Figure 7: Mobile Fiori Life Cycle Management architecture
The journey of the code does not begin in the first deployment stage, however. The application is code in the WebIDE and shared between team members via Git, a source code management (SCM) system. Once a unit of work, e.g. a feature, is completed, the change is pushed into the upstream Git repository, from where the current project status is retrieved by a Continuous Integration (CI) server. The CI server then continues to build the project and execute the project test suite. Only when these steps are successful, the built application is deployed to the first test stage.
It is easy to see how manual tests would be carried out from the browser: Each of the deployment stages comes with a full Fiori stack, so that each of the FES has its own Launchpad. On the mobile device this is somewhat trickier: A Standard Fiori Client is configured against a single FES, and one application (identified by its bundle ID, e.g. com.sap.fioriclient) may only be installed once per mobile device. Therefore it is either necessary to use different mobile devices for each of the stages, or to build three Custom Fiori Clients with different bundle IDs that may be deployed to the same device (e.g. com.sap.fioriclient.dev, com.sap.fioriclient.test, com.sap.fioriclient.prod).
Going forward we are going to assume the latter approach is taken. Since now development, build and distribution of the Custom Fiori Client itself become a concern, Figure 8 shows the corresponding LCM view on the mobile development landscape.
Figure 8: Typical Mobile Life Cycle Management architecture
It can be seen that apart from using a different set of tools for development, the build and test infrastructure still is the same with Git and the CI server in its center. The first large difference is that a Mobile Device Management (MDM) solution such as SAP Afaria is the target of the CI server deployment rather than a FES. Secondly, it can be seen that it is not typical to replicate MDM systems for each testing stage. Instead, different application configurations are created in the MDM system, one for each Custom Fiori Client. Thirdly, the CI server builds one version per stage per update, resulting in three built Custom Fiori Clients per update in the current example, which are then pushed to the client devices. As outlined before, the mobile applications only differ in their configuration, and the subjects under test (SUTs) are the Fiori applications rather than the Custom Fiori Client. Therefore the separation between FES is sufficient, and switching to a different Custom Fiori Client stage is equivalent to switching to another FES Launchpad stage. The beauty here is in the clean separation between web application and native code, as was hinted in Figure 3. The Custom Fiori Client merely provides a shell in which the Fiori applications may run, and it only contains the rather rarely changing native components of a hybrid application. The more frequent application updates follow the quality assurance path shown in Figure 7, whereas Custom Fiori Client updates are shipped occasionally via the MDM solution.
Life Cycle Management for Packaged Applications
Now that a reference LCM architecture has been established prior to the implementation of packaging, we can now take a glimpse at the changes packaging would introduce. Figure 9 provides a unified view on LCM for (packaged) mobile and web-based Fiori applications.
Figure 9: Basic packaged application Life Cycle Management architecture
The first conclusion is that both approaches may actually coexist, which makes it easy to experiment with packaged applications while the existing system landscape remains largely untouched. In fact the packager included in the SAP Mobile SDK leverages FES as the source of truth, downloading apps and their dependencies from there. Secondly the CI server now not only builds and deploys to the FES once per Fiori application update, but it will also need to rebuild and redistribute the packaged applications to the mobile devices. This potentially introduces significant additional load on the MDM, depending on the frequency with which Fiori application updates are checked in. For this reason SAP provides the App Update plugin, which enables packaged applications to connect to the SMP and update themselves if a newer version of the web applications is available.
Figure 10 shows an updated architecture incorporating the (so far optional) SMP. In this setup the MDM service is only used for the first-time installation and updates when changes are made to the native application components.
Figure 10: Packaged application Life Cycle Management using SAP Mobile Platform
Just as before, when a Fiori application is updated in Git, the packager is triggered to assemble the required web assets for the packaged application Cordova build. This intermediate build result can now be used to create a web application package using the Mobile SDK Kapsel CLI and upload it to the SMP. Then it can be rolled out either automatically or manually to a number of test devices, or to all registered devices. The most important bit here is that the SMP calculates a delta based on previously uploaded web application packages, and only sends the differing files to the devices. This way frequent updates of thirty megabytes and above can easily be cut down to single-digit numbers and below.
Challenges unaffected by Packaging
On the previous pages we considered how packaging Fiori applications affects the LCM and client-server interaction. However, it is also important to understand that there are challenges in Mobile Computing that cannot be addressed by packaging, the most notable being processing power. Mobile devices generally have less computing power, main memory and storage capacity than the average desktop computer. While it is true that packaging may improve overall performance by eliminating server round trips due to code loading, it does not affect the performance of the applications themselves, i.e. their consumption in terms of processing power and main memory. To the WebView, it does not matter if the same piece of code was loaded from the local file system or from a remote server. The remaining network performance is not affected either, i.e. slow data requests in the Fiori Client will not complete faster in packaged applications.
Further Steps – Taking It Offline
With the packaging in place, network-related failures to load the application are mitigated. While this greatly improves stability, it does not address performance issues, since uncached data requests still require full server round trips, and especially time-intensive data requests are vulnerable to connection interruptions. Therefore it makes sense to think about going the extra mile and also implementing the SMP Offline OData support. Figure 11 shows an updated runtime architecture diagram, continuing the Fiori Launchpad example we used previously.
Figure 11: Packaged offline-enabled application client-server architecture and interaction
Rather than having the applications access the remote OData service directly, the SMP provides the client with a local database that is used to feed a local OData producer. Requests on the client are then rewritten to the local OData provider, allowing near-instant access to the data. Not only does this enable scenarios that are otherwise impractical due to network unavailability, but it also helps you provide a very fluent user experience. The local offline data can be synchronized with the backend in the background whenever network connectivity is available.
In this paper the technical concept of packaging, i.e. moving web application code from the Fiori Frontend Server onto a mobile device, was discussed. It was shown that both traditional Fiori consumption models (browser, Fiori Client) may coexist with packaged deployments without interfering with each other. The biggest difference between the approaches is in the life cycle management, which may or may not lead to additional load on the Mobile Device Management solution. It could be shown, however, how this issue can be addressed by leveraging the web app delta update capabilities of the SAP Mobile Platform.
 Throughout this paper the term SAP Mobile Platform may be exchanged equivalently with HANA Cloud Platform mobile service.
 This blog describes a typical approach to separating finished work and work in progress by means of Git branches.
 Martin Fowler described CI in depth on his homepage.
 Throughout this paper the term SAP Afaria may be exchanged equivalently with SAP Mobile Secure.
thank you for this great overview. Do you have any plans to provide details on the CI implementation for i.e. the automated build of a Cordova/Kapsel Hybrid that was developed in the SAP Web IDE and checked into Git? Would be great if you could contribute that to Continuous Integration (CI) Best Practices with SAP.
Whoopsie, looks like I missed that notification bubble for quite a while! I do in fact have CI on my content agenda, so stay tuned for more to come in the following weeks. If I am not actually going to contribute it to the central CI guides, I will make sure that the articles are linked.
better late then never :-). Would think the central CI guide would be the best place as it would allow also community contributions by pull requests.
I have a customer asking to have Fiori Apps also available available.
e.g. they would like to use the App "Request Maintenaince" offline. how complex is it to enable a existing app to work also offline?
That really depends on the app, the underlying data source, and ultimately also the business process. Generally speaking, it is much easier to build an OData service with Offline in mind in order to make sure that you don’t run into any limitations. We have had projects following that approach in which going from an Online app to an Offline app was a mere question of configuration. In my experience, however, it is rather unlikely that it will “just work” with any random app, because the quality of OData services varies. In addition, you need to consider that Offline enablement may impact the underlying business processes. A typical example is concurrent modification. In online apps, this is less of an issue as there is little opportunity for data to diverge. In offline apps, however, the question is: When a conflict occurs, who is going to resolve it? The user? The back-office? How should the error be resolved? And why can it happen in the first place? Does it make sense to adjust the process?
So generally speaking, Offline enablement can be very easy, but also very tricky. What most people don’t expect, however, is that the issue is most commonly found in processes, not the technology.
Hi Michael, thank you for taking the time to write such a comprehensive yet clearly explained article. I wonder why they don't make the Fiori Client handle a number of launchpad urls, rather than just one. Switching the url can be a pain for users, although your suggestion of delivering a number of custom Fiori Clients is a good one.
Interesting point. Without knowing more about the use case, I would consider having multiple custom Fiori Clients a reasonable approach, though. I could imagine a number of scenarios where this would have an advantage or two over switching URLs. On the other hand, if this is a hard requirement, why not build a Custom Fiori Client that implements this? 🙂
The reason I don't want to build 3 x custom clients is that then I will have to maintain them and release new versions. If the SAP Fiori client supported multiple launchpad urls I could just use that and users would get their regular updates.
With the right automation infrastructure, I don't really see an issue here. Have a build job exchange the bundle IDs and launchpad URLs, and you are good to go. However, I understand that your release processes may, for instance, require that all of them are tested individually so I do see how your concerns come into play.