Often when working on a suite of applications you will want to encapsulate common code into reusable libraries and or components. Inside of the reusable module is a master text file, a requirement that has popped up a few times is how to merge the master text file with the translatable text file the applicaiton uses.

Below i show how its possible to merge an application i18n models texts with the texts from a reusable components i18n model.

Why would you want to do it? you are creating a suite of Sales and Distribution applications for end users, there is a common buiness vocabulary that you may want to share between applications.

The pic below shows a reusable component, later it will be loaded as a dependency in an application, in this simple example i am creating one text property which will be merged.

In the manifest we ensure the i18n model is loaded when the component is instantiated.

"models": {
    "i18n": {
        "type": "sap.ui.model.resource.ResourceModel",
        "uri": "i18n/i18n.properties"
    }
},

Next create an application which also has a single text property

To demonstrate successful merge of texts we declare a simple view which shows the two text properties.

<mvc:View controllerName="test.reuse.myApp.controller.Main" 
xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc">
    <Button text="{i18n>myAppText}"/>
    <Button text="{i18n>commonText}"/>
</mvc:View>

To consume the common component from an application, inside the manifest under “dependencies” declare the reusable component.

"sap.ui5": {
    "rootView": "test.reuse.myApp.view.Main",
    "dependencies": {
        "minUI5Version": "1.32.1",
        "components": {
            "test.reuse.common": {
                "minVersion": "1.0.0"
            }
        }
    },
    "models": {
        "i18n": {
            "type": "sap.ui.model.resource.ResourceModel",
            "uri": "i18n/i18n.properties"
        }
    },

In the example below the Component is saved as a BSP in the ABAP UI5 Repository, so at the top of the Component file we need to the following

var sUrl;
jQuery.sap.registerModulePath("test.reuse.common", {
    url: "/sap/bc/ui5_ui5/sap/zcommon"
});

Originally had this logic in the manifest “resoureRoots” but later found that absolute paths cannot be entered

If you are like me and developing in teams where members use both WebIde and thier own local development environment, you will want to overide the destination defined in the resource root and point to both local server resources and the cloud based workspace where the common component is located. In WebIDE this is similar to how you would reference the source application from an extension project.

When registeing a module path if you set the “final” flag to true then any subsequent path registration will be ignored.

var sUrl;
if (window.location.host.match(/^(localhost|127.0.0.1|0.0.0.0)/)) {
    sUrl = "../common";
} else if (window.location.host.match(/(<TENANT>)/)) {
    sUrl = "/../orion/file/<TENANT>$<USERID>-OrionContent/common/";
}

jQuery.sap.registerModulePath("test.reuse.common", {
    url: sUrl,
    final: true
});

Don’t forget to add the “neo-app.json” entries for the backend and orion paths for WebIDE.

{
    "path": "/orion/",
    "target": {
        "type": "service",
        "name": "orion",
        "preferLocal": true
    },
    "description": "Orion Server"
}, {
    "path": "/sap/bc/ui5_ui5/sap/",
    "target": {
        "type": "destination",
        "name": "abap",
        "entryPath": "/sap/bc/ui5_ui5/sap/"
    },
    "description": "Gateway Server"
}

So we have created a reusable component with a common translatable text file, added it as a dependency to our application, coded options for finding the Component when running locally and from a server, all that is left is to get an instance of the reuse component and merge the i18n models, we do that in the applications component.

jQuery.sap.registerModulePath("test.reuse.common", {
    url: "/sap/bc/ui5_ui5/sap/zcommon"
});

sap.ui.define(['sap/ui/core/UIComponent'],
    function(UIComponent) {
        "use strict";

        return UIComponent.extend("test.reuse.myApp.Component", {
            metadata: {
                "manifest": "json"
            },

            init: function() {
                // get the i18n model for the app
                var oI18nModel = this.getModel("i18n");

                // get the common component
                var oCommonComponent = sap.ui.component({
                    name: "test.reuse.common"
                });

                // get the common component resource bundle
                if (oCommonComponent) {
                    var oBundle = oCommonComponent.getModel("i18n").getResourceBundle();

                    // enhance the app i18n with the resources from the commmon component
                    oI18nModel.enhance(oBundle);
                }
                // call the init function of the parent
                UIComponent.prototype.init.apply(this, arguments);
            }
        });
    });

Then when we run the application, the two texts are merged into one model

This is a quick blog to remind myself how to support ES6 Promise’s in older versions of SAPUI5. I was developing a UI5 app for a customer with Chrome, Chrome already supports natively some of the ECMA Script 6 features like Promises and it was only when i ran the applcations Opa Tests against Internet Explorer and PhantomJS I found out that I had a couple of backwards compatibility issues which required me to add polyfills.

What is a Promise?

A promise represents the result of an asynchronous operation. In JavaScript its a nice clean way of avoiding nested callbacks.

For example a promise could represent a list being loaded and onload you want to trigger some functionality say update the list title with the count of entries

oWhenListLoadingIsDone = new Promise(function(fnResolve, fnReject) {
    // trigger resolve callback when list finished loading
    oMasterList.attachEventOnce("updateFinished", function(){ fnResolve()
    ..
}
oWhenListLoadingIsDone.then(setListTitle, errorCB)

What is a Polyfill?

A polyfill, is a piece of code that provides the technology that youexpect the browser to provide natively.

SAPUI5 is built on jQuery and jQuery has thier own version of Promise, however thier API breaks the native Promise in a couple of ways.

In my case to get Internet Explorer to support the new Promise(function(fnResolve, fnReject) syntax I had been using was quite simple.

if (!window.Promise) {
    window.Promise = function(callBack) {
        var promise = jQuery.Deferred();

        callBack(promise.resolve, promise.reject);

        return promise.promise();
    };
}

The current version of UI5 has an ECMA Script 6 Polyfill jQuery.sap.promise this version is a lot more complete than the one i mention above.

I recently had a requirement to send links to Fiori apps to users via SMS. One of main challenges was how to shorten the URL links to the allowable 160 characters, this blog quickly highlights some of the steps taken.

Requirement

The URL sent to the users via SMS should open a SAPUI5 application in a Fiori launchpad headerless window. The application is very similar to a WorkFlow app, where in a user accepts are rejects a task. The link needs to contain the paramaters and context necessary for the application to be started with the correct state, the right screen, the right data etc.

The Challenge

The main challenge faced was how to shorten the URL, the Fiori Launchpad URL is quite long before you start adding context, the template below is already at the 200 character mark

https://<server>:<port>/sap/bc/ui5_ui5/ui2/ushell/shells/abap/FioriLaunchpad.html?

sap-client=000&sap-language=EN

#<Semantic_object>-<Action>/<route_name1>/<route_number1>/<route_name2>/<route_number2>

add the parameter for removing the shell header

sap-ushell-config=headerless

and the URL that needs to be sent is exceeding 240 characters. How to limit the size of the URL to the 160 characters allowed by SMS?

Analysis

I guess there are a lot of ways to shorten the URL, the first thought was using a URL shortening service, the SAP Portal provides shortened URL’s for its content paths, unfortunately there is nothing similar for the ABAP based WebAS. The second thought was to use something like goo.gl or bit.ly. I found a couple of of ABAP based projects which provided code for using these services, however for me to implement them there would have been some technical challenges to using them.

Solution

The option we came up with i think does the job quite well.

https://<server>:<port>/flp

  • the SICF service has an ABAP HTTP Request handler which programatically redirects the browser to the Fiori Launchpad

lv_url = |/sap/bc/ui5_ui5/ui2/ushell/shells/abap/FioriLaunchpad.html?foo=bar… |.
server->response->redirect( url = lv_url ).

  • Flatten and simplify the remaining needed parameters, on the links sent to the users use cl_http_utility=>encode_base64 to obfuscate and hide the details from the user and use cl_http_utility=>decode_base64 in the http handler to map back the routing parameters

https://<server>:<port>/flp/{<Action><route_number1><route_number2>}

The result was a URL that fit well within the 160 character limit SMS has.

One more thing Configuration Table HTTPURLLOC - this table allows for entries with valid protocol, host and port combinations, can be set up and used for generating the external facing URLs sent to users for each of the ABAP Fiori instances.

I am currently in China on a working holiday. Today is Chinese New Year, a time to be retrospective and a second chance for me to start acting on some resolutions that slipped.

My observation is China is a contrast in technology trends, mobile adoption is moving faster than anywhere else I have been and in the wake a legacy of Windows XP on the desktop is refusing to go away.

Everywhere you look you see Iphone 6s and Galaxy Note 3s, prior to coming to China I knew that “brand new” mobile phones were fashionable, and I discounted as a younger generation fascinated with status and Western Culture. Being here has given me a different perspective. Not having access to sites like Google, YouTube or Facebook has not slowed down adoption of technology, from what I can see China is ahead of the curve when it comes to mobility, both in terms of adoption and how the mobile device is being used.

The stats are amazing Chinese mobile phone users to 557 million or 85.8 % of total Internet users, there is 94.5% mobile penetration and from what I can see, like their cars, they are all brand new and better than mine!

The recent article in Smashing Magazine China’s Bleeding Edge: Web Design Trends 2015 is a really good read and highlights some of what I am seeing here WeChat, light apps and QR codes everywhere. WeChat is by far the most popular Mobile application with over 400 million users, interestingly around 20% of those users are not based in China. WeChat is more of a one stop mobile platform, it is functionally rich, covering all social media, search, news, blogging, e-commerce, banking, IM, Group Chat needs and more. What makes WeChat interesting to me is that it is self contained with its own web browser, given the popularity of mobility and WeChat in particular it has meant that the way websites are built has changed. To cater for the mobile first, there has been a paradigm shift to creating what is termed “light apps”, very similar to consumer facing, fit for purpose, responsive, single page HTML5 apps. The other thing worth noting you dont see URL’s, instead of advertising thier URL’s, companies us QR Codes, they are everywhere, in shop windows, on products, on billboards etc. QR Codes might have limitations, which may have stopped adoption elsewhere, but that has not stopped the widespread adoption in China. You no longer access a website by entering a URL in the address bar in your browser.

On the flip side of this mobile first adoption is that it is leaving behind an aging desktop legacy. I am lead to believe based on observations and recent articles that the number one desktop OS here in China is still Windows XP. This is no surprise to me, many people probably don’t own a desktop or laptop, opting for mobile phones and tablets. Interestingly the majority of big clients and Government agencies I work for are also still predominantly using Windows XP, I guess holding off till it hurts, deferring to a BYOD strategy for certain use cases. However the trend I see in Australia is the adoption of Google Chrome for XP, its the proverbial lipstick on a pig, you can deploy a nice looking HTML5 UI but the UX still sucks. This trend will change as Microsoft is dropping support of XP soon, I believe it is April 2015, around about that time Google has said they will no longer support Chrome for XP also.

The stats say there is a large Chrome user base China, however from what I can see here in China based on my own access, using Chrome on XP is probably not an option and this uptake may come from Android devices where Chrome is pre-installed. I am not reading or seeing any uptake for browsers like Firefox and Opera either. Modern.ie shows whilst dropping rapidly, 3% of China still uses IE6 for a browser and of the remaining 10% that makes up the Desktop portion aging IE browsers rule, given the number of internet users those numbers whilst low in percentage are very scary. This definitely presents a technical challenge for Enterprise Software or start-up companies thinking of breaking into China and i am sure there are many who want to. Continue to support IE8, with ES6 and HTTP2 round the corner that is a massive overhead. Or hope that users will only want to use you apps on the web kit/chrome browser on their phone. Or goto where the users are, redesign mobile first, break out the QR codes and install the WeChat SDK. I think Smashing Magazine article says it all “Do China Mobile right or don’t bother”.

A couple of weeks ago I was playing around with SAP HCP Trial WebIDE and noticed that the Fiori sample applications were using the MockServer for all OData Entity requests and also for the custom OData Function Imports.

This week I had a requirement to create a simple Function Import, the function calls the backend SAP system to determine whether or not to show a button, I used as an opportunity to investigate and learn how to add my own mock xhr request to the SAPUI5 Mockserver and thought I would share.

To add your own requests to a MockServer instance is quite simple, first set up the MockServer, retrieve the current requests, then add your request and then set the updated requests back to Mockerver.

//initialize the MockServer as per normal
jQuery.sap.require("sap.ui.core.util.MockServer");
var oMockServer = new sap.ui.core.util.MockServer({
    rootUri: sServiceUrl
});
oMockServer.simulate("model/metadata.xml", "model/");
 
//add your requests to the ones already set 
try {
  jQuery.sap.require("myapp.model.mockRequests");
  var aMyRequests = myapp.model.mockRequests.getRequests();
  if (aMyRequests.length > 0) {
    oMockServer.setRequests(oMockServer.getRequests().concat(aMyRequests));
  }
} catch (oErr) {
  jQuery.sap.log.debug(oErr.message);
}
 
//start the mockserver
oMockServer.start();

The documentation for UI5 MockServer setRequests gives a good explanation on the structure of requests

method : “GET”|”POST”|”DELETE|”PUT”
path : “/path/to/resource”
response : function(xhr, param1, param2, …) { }

Here is the code I wrote for the ShowAddButton Mock call

sap.ui.define(['jquery.sap.global'],
    function(jQuery) {
        "use strict";
        var mockRequests = {
            /**
             * This mock determines whether the '+' add button should be shown
             */
            mockShowAddButton: function() {
                return {
                    method: "GET",
                    path: new RegExp("ShowAddButton?(.*)"), 
                    response: function(oXhr, sUrlParams) {
                        jQuery.sap.log.debug("Incoming request for ShowAddButton");
                        oXhr.respondJSON(200, {}, JSON.stringify({
                            d: {
                                ShowAddButton: true
                            }
                        }));
                    }
                };
            },
            /**
             * get requests
             * @return {array} Array of mock request
             */
            getRequests: function() {
                return [mockRequests.mockShowAddButton()];
            }
        };
        return mockRequests;
    },
    true);

For those interested here’s a link to the Fiori Reference Apps

in the WebIDE you can find them under File->New->Project from Sample Application

A few people have asked me to share the slides from the talk I gave at SAP DCode 2014 Las Vegas.

The talk was aimed at developers who had already started writing SAPUI5 apps, the objective was to highlight a variety of patterns, principles and best practices to help them take their development to the next level.

The takeaway points

1. Follow JS Best Practices - a lot of the tutorials and documentation for SAPUI5 is centred around using Eclipse as an IDE, in my opinion which is shared by many others there is “no one size fits all”, to get the right developer workflow it is better to build your JS developer toolchain from the ground up, that way you get to know what works and why. Start by investigating how developers using other JS toolkits and frameworks set up theirs, experiment, add the additional functionality as it is needed rather than start with something that is preconfigured and abstracts away the detail making it hard to change. The best practices section covered things like the need for automating repetitive develop, build and deploy tasks using Grunt, using a distributed version control system like git to reduce the risk of introducing errors, and ensuring the quality of the code pushed back to SAP is always production ready, also covered was following Web development best practices to reduce the complexity and improve the performance of your apps etc.

2. Don’t Build Big Apps - this is true for any programming paradigm, don’t build big apps, build lots of small ones, wire them together with events. In this section I covered the different techniques available for modularizing your code into smaller units, and then how to bring the small units together using techniques like routing, which enable you to set up the state of the application from the URL, i.e. what views need to be visible and what data needs to be shown and then how to use events to seamlessly navigate to different states of the application.

3. Use fit-for-purposes API’s - the inside-out approach for creating services with Netweaver Gateway sounds like a good idea, take an existing BAPI and expose it. This approach lends itself to complexity, BAPI’s are normally quite complex to start with, they have to cater for lots of different scenarios, as you come across business logic and functionality not available in the BAPI developers will often try workarounds and build the logic into the front end, you should let the data drive the application not the other way around. In this section I talked about the advantages of taking a mock model first approach. Flesh out the screens you have designed and build an information architecture. Use this as a basis for a data model to build your Gateway services. Once you have modelled your services you can easily generate mock data for the service, this will allow UI5 developers to quickly build the shell of the application and validate the completeness of the data model. Other benefits of using mock data first are that developments can happen in parallel, different parts of the UI can be developed independent of other UI and backend ABAP developments. Using the MockData Server makes it easy to create Unit and End-to-End tests allowing you to quickly find issues, perfect for quickly validating new feature request and changes made during bug fixes.

The Fiori 1:1:3 mantra whilst an over simplification was a very timely reminder to keep UI design simple, the same thinking should be applied to development and how we develop, regardless of the size of apps we are building, one size does not fit all, keep things simple and fit for purpose.

Originally published in InsideSAP Magazine

SAPUI5 is a hot topic right now due to the popularity of the SAP Fiori mobile application suite. SAP Fiori is a collection of apps built on frequently used SAP functionality, they provide users with “an easy to use, consumer grade experience”, and SAPUI5 is the HTML5 library that makes it possible. A lot of customers are so impressed with the simple, consistent look and feel that they are requesting developers to “build me an app that looks just like Fiori”. Building mobile applications is not as simple as choosing a framework because it is aesthetically pleasing, there are many factors you need to consider, in this article you will get introduced to SAPUI5 and get an overview of what it delivers and what it doesn’t.

What is SAPUI5? SAP’s UI development toolkit for HTML5 also known as SAPUI5, enables developers to easily create write once, deploy (nearly) anywhere applications, without having to worry about cross-browser compatibility, touch device support or adherence to web standards. The key features of the toolkit are - a large set of configurable and customizable Rich UI controls including interactive charts and data visualizations, which work across all devices - tools, templates and techniques for creating your own UI controls - easy to use theming and branding tools - available on all SAP platforms, ABAP, Java and HANA based - has a programming model that gives a scalable, reusable structure to applications - international language and RTL support - built on top of some of the popular open source JavaScript libraries including JQuery and JQuery Mobile - a low barrier for entry, targeting developers with HTML, CSS3 and JavaScript skills

The differentiators

There are lots of alternatives in the HTML5 mobile space; they range from roll your own solutions combining open source libraries like jQuery, jQuery Mobile and Bootstrap, to mature commercial frameworks like Sencha Touch and Kendo UI. Some of the features that make SAPUI5 stand out from the others are - Simplified Integration, SAPUI5 is optimized for OData service (Netweaver Gateway) consumption, seamlessly binding the data to the UI controls. Within a few lines of JavaScript you can connect to a backend and start consuming and manipulating data online. - Interoperability, SAPUI5 is now on all platforms, each providing a set of backend UI Services for a consistent portal like way to manage end-to-end how users access and interact with SAPUI5 applications, covering roles, personalization and configuration. With the Theme Editor a consistent way to style and brand not only SAPUI5 but your Webdynpro application and NWBC. - Scalability, SAPUI5 is a pivotal part of SAP’s “new” solutions UX strategy, it is being used in anger by SAP themselves on countless developments around the world, developers can develop locally using their favourite tools and then deploy to the server where familiar version control and transport mechanisms manage the dependencies and system synchronizations. - Extensibility, SAPUI5 is very modular, this makes it easy to enhance or extend by writing your own code or by adapting third party libraries. SAP also provides Extension Points in their delivered applications, giving customers added flexibility to meet their requirements.

What are the limitations?

If you have read any articles on Native vs. HTML5 mobile development you will are probably aware already what the limitations are. - Very limited support for offline storage, simple scenarios can be catered for using the available local storage API’s, limited to 5 MB. Alternatives are available using third party plugins and techniques. To get any kind of data synchronization to a SAP backend would require a significant amount of effort. - Minimal support for devices OS capabilities like GPS, audio and video - Minimal support for application security It has to be said that some of these short comings are not within the scope of the product and could be addressed by SAPUI5 when combined with a hybrid container like Apache Cordova (previously PhoneGap) and a mobile platform like SAP’s SMP 3.0. On the horizon OData Version 4 promises to provide better offline data sync capabilities and as HTML5 matures it is likely these feature and others will be incorporated into the product.

Takeaways

There are many things you need to consider when developing mobile applications for an Enterprise, multi-platform support, security, performance, usability, backend integration and offline capability to name a few. No one product will meet all your requirements. SAPUI5 is a good choice for rapidly creating online mobile applications that have a consistent consumer like experience and work across all devices. Where SAPUI5 excels is in providing simplified integration, allowing your backend and frontend developers to easily communicate requirements and respond to them quickly. It has been designed to be extensible making it easy to grow and cater for your future requirements. Backend services are provided to manage both the development lifecycle and how users access applications, providing a consistent approach with existing developments and functionality. Lastly it is supported by SAP as part of the Netweaver licence and when it finally becomes Open Source it will be used by and supported by a much bigger community of developers, all the more reason to “build me an app that looks just like Fiori”.