Skip to Content
Technical Articles

XSA Fiori Launchpad On-Premise Configuration With SAP Fiori Launchpad Plugins

Rest assured, it is possible to use SAP Fiori Launchpad Plugins with XSA On-Premise.

It was extremely difficult to find information for this configuration online, to my knowledge there was none available at the time of writing.

As many of the steps for the launchpad configuration have been covered in my previous post, I will only take you through the steps required to add the plugin in detail. https://blogs.sap.com/2020/02/03/xsa-fiori-launchpad-on-premise-configuration-with-cross-mta-dependencies./

A full working example of the source code has been made available on Github.https://github.com/bigsmity/xsalaunchpadextensiondemo

 

Create the plugin

Unfortunately there is no template available in SAP Web IDE On-Premise for the SAP Fiori Launchpad Plugin. But all is not lost, The Full Stack Web IDE provided by the SAP Cloud Platform has the template that we need! It is free to register for a trail account and I highly recommend doing so.

 

Generate plugin from SAP Cloud Platorm Full Stack Web IDE

In the Full Stack Web IDE, select new project from template.

 

Select “New SAP Fiori Launchpad Plugin” and click Next.

 

Enter the name “launchpaddemoplugin”

click “Next”

 

Enter the Plugin ID “launchpaddemoplugin”

Enter the Title “Launchpad Demo Plugin”

Check the box labelled “Add button to launchpad header”

Click “Finish”

 

The new plugin has now been generated, complete with a demo button and action.

 

Create the MTA in your On-Premise Environment

 

Create an MTA named “launchpaddemoplugin”

 

Add a new “SAPUI5 HTML5 Module” named “launchpaddemoplugin” with the namespace “launchpaddemoplugin”

 

Delete all the contents from the webapp folder

 

Add the files from the launchpaddemoplugin module created with the Full Stack WebIDE from Cloud Platform.

 

rename the webapp folder to “launchpaddemoplugin”

 

On your On-Premise system, your file structure now appears as follows:

 

The Component.js file as generated by the Cloud Platform template:

sap.ui.define([
	"sap/ui/core/Component",
	"sap/m/Button",
	"sap/m/Bar",
	"sap/m/MessageToast"
], function (Component, Button, Bar, MessageToast) {

	return Component.extend("launchpaddemoplugin.Component", {

		metadata: {
			"manifest": "json"
		},

		init: function () {
			var rendererPromise = this._getRenderer();

			// This is example code. Please replace with your implementation!

			/**
			 * Add item to the header
			 */
			rendererPromise.then(function (oRenderer) {
				oRenderer.addHeaderItem({
					icon: "sap-icon://add",
					tooltip: "Add bookmark",
					press: function () {
						MessageToast.show("This SAP Fiori Launchpad has been extended to improve your experience");
					}
				}, true, true);
			});

		},

		/**
		 * Returns the shell renderer instance in a reliable way,
		 * i.e. independent from the initialization time of the plug-in.
		 * This means that the current renderer is returned immediately, if it
		 * is already created (plug-in is loaded after renderer creation) or it
		 * listens to the "rendererCreated" event (plug-in is loaded
		 * before the renderer is created).
		 *
		 *  @returns {object}
		 *      a jQuery promise, resolved with the renderer instance, or
		 *      rejected with an error message.
		 */
		_getRenderer: function () {
			var that = this,
				oDeferred = new jQuery.Deferred(),
				oRenderer;

			that._oShellContainer = jQuery.sap.getObject("sap.ushell.Container");
			if (!that._oShellContainer) {
				oDeferred.reject(
					"Illegal state: shell container not available; this component must be executed in a unified shell runtime context.");
			} else {
				oRenderer = that._oShellContainer.getRenderer();
				if (oRenderer) {
					oDeferred.resolve(oRenderer);
				} else {
					// renderer not initialized yet, listen to rendererCreated event
					that._onRendererCreated = function (oEvent) {
						oRenderer = oEvent.getParameter("renderer");
						if (oRenderer) {
							oDeferred.resolve(oRenderer);
						} else {
							oDeferred.reject("Illegal state: shell renderer not available after recieving 'rendererLoaded' event.");
						}
					};
					that._oShellContainer.attachRendererCreatedEvent(that._onRendererCreated);
				}
			}
			return oDeferred.promise();
		}
	});
});

 

The fioriSandboxConfig.json as generated by the Cloud Platform template:

{
	"applications": {},
	"bootstrapPlugins": {
		"lpe": {
			"component": "launchpaddemoplugin",
			"url": "../../../../../"
		}
	}
}

 

The manifest.json as generated by the Cloud Platform template:

{
	"_version": "1.5.0",
	"sap.app": {
		"_version": "1.2.0",
		"id": "launchpaddemoplugin",
		"type": "component",
		"applicationVersion": {
			"version": ""
		},
		"title": "{{plugin_title}}"
	},
	"sap.ui": {
		"_version": "1.3.0",
		"technology": "UI5",
		"deviceTypes": {
			"desktop": true,
			"tablet": true,
			"phone": true
		},
		"supportedThemes": []
	},
	"sap.ui5": {
		"_version": "1.1.0",
		"contentDensities": {
			"compact": true,
			"cozy": false
		},
		"dependencies": {
			"minUI5Version": "1.38.1",
			"libs": {
				"sap.ui.core": {
					"minVersion": "1.38.1"
				},
				"sap.m": {
					"minVersion": "1.38.1"
				}
			}
		},
		"componentName": "launchpaddemoplugin"
	},
	"sap.flp": {
		"type": "plugin",
		"config": {}
	}
}

 

The mta.yaml will need to be updated as per my previous blog post to allow cross-MTA dependency

ID: launchpaddemoplugin
_schema-version: '2.1'
version: 0.0.1

modules:
 
 - name: launchpaddemoplugin
   type: html5
   path: launchpaddemoplugin
   parameters:
      memory: 64M
   properties:
      CORS:
        - uriPattern: .
          allowedMethods:
            - GET
            - POST
          allowedOrigin:
            - host: '*'
   provides:
      - name: launchpaddemoplugin_ref
        public: true
        properties:
          url: '${default-url}'
     

 

Build and deploy your launchpaddemoplugin application.

 

Create the Launchpad and configure the plugin

 

Create the launchpad as per the steps in my previous blog https://blogs.sap.com/2020/02/03/xsa-fiori-launchpad-on-premise-configuration-with-cross-mta-dependencies./

Note that the step for creating the application entry in the launchpaddemo-Content site-content.json file will change as we no longer need a tile and need to apply different settings for the plugin.

 

Once the launchpad is created, the application reference to the plugin can be added.

 

The following application entry is to be added to the launchpaddemo-Content site-content.json applications object:

"launchpaddemoplugin": {
			"sap.app": {
				"_version": "1.3.0",
				"id": "launchpaddemoplugin",
				"title": "launchpad demo plugin",
				"i18n": "i18n/bundle.properties",
				"tags": {
					"keywords": []
				},
				"crossNavigation": {
					"inbounds": {
						"siteShow": {
							"semanticObject": "Shell",
							"action": "plugin",
							"deviceTypes": {
								"desktop": true,
								"tablet": true,
								"phone": true
							},
							"signature": {
								"parameters": {
									"sap-ushell-plugin-type": {
										"defaultValue": {
											"value": "AppWarmup"
										}
									}
								}
							}
						}
					},
					"outbounds": {}
				}
			},
			"sap.ui": {
				"_version": "1.3.0",
				"technology": "UI5"
			},
			"sap.ui5": {
				"componentName": "launchpaddemoplugin",
				"_version": "1.2.0"
			},
			"sap.platform.runtime": {
				"componentProperties": {
					"url": "/launchpaddemoplugin_dest"
				}
			},
			"sap.flp": {
				"type": "plugin"
			}
		}

The semantic object is set to “Shell”

The action is set to “plugin”

The “signature” object is added with the sap-ushell-plugin-type value of “AppWarmup”

The component name is set to “launchpaddemoplugin”

The url is set to the destination path “/launchpaddemoplugin_dest”

The sap.flp object is added with the type “plugin”

 

Entire launchpaddemo-Content site-content.json:

{
	"_version": "1.0.0",
	"site": {
		"_version": "1.0",
		"identification": {
			"id": "499c36e2-687e-11e6-8b77-86f30ca893d3",
			"namespace": "",
			"entityType": "site",
			"description": "",
			"i18n": "",
			"title": "Fiori Launchpad Sample"
		},
		"payload": {
			"groupsOrder": [
				"5acadc20-687e-11e6-8b77-86f30ca893d3"
			],
			"config": {

			},
			"sap.cloud.portal": {
				"_version": "1.2.0",
				"config": {
					"theme.id": "sap_belize",
					"theme.active": "[\"sap_hcb\",\"sap_belize_plus\",\"sap_belize\"]"
				}
			}
		}
	},
	"catalogs": {
		"07889260-3021-4ef6-ba85-edd311738f9a": {
			"_version": "1.1",
			"identification": {
				"id": "07889260-3021-4ef6-ba85-edd311738f9a",
				"namespace": "",
				"title": "{{sample_catalog_title}}",
				"description": "{{sample_catalog_description}}",
				"entityType": "catalog",
				"i18n": "i18n/i18n.properties"
			},
			"payload": {
				"appDescriptors": [{
					"namespace": "",
					"id": "6ef9cdd2-687e-11e6-8b77-86f30ca893d3"
				}, {
					"namespace": "",
					"id": "73c3f80a-5245-4e6c-a51d-d9436b1cb530"
				}]
			}
		}
	},
	"roles": {
		"Everyone": {
			"_version": "1.0",
			"identification": {
				"id": "Everyone",
				"title": "Everyone",
				"entityType": "role"
			},
			"payload": {
				"catalogs": [

				],
				"groups": [{
					"id": "5acadc20-687e-11e6-8b77-86f30ca893d3"
				}]
			}
		}
	},
	"applications": {
		"launchpaddemoplugin": {
			"sap.app": {
				"_version": "1.3.0",
				"id": "launchpaddemoplugin",
				"title": "launchpad demo plugin",
				"i18n": "i18n/bundle.properties",
				"tags": {
					"keywords": []
				},
				"crossNavigation": {
					"inbounds": {
						"siteShow": {
							"semanticObject": "Shell",
							"action": "plugin",
							"deviceTypes": {
								"desktop": true,
								"tablet": true,
								"phone": true
							},
							"signature": {
								"parameters": {
									"sap-ushell-plugin-type": {
										"defaultValue": {
											"value": "AppWarmup"
										}
									}
								}
							}
						}
					},
					"outbounds": {}
				}
			},
			"sap.ui": {
				"_version": "1.3.0",
				"technology": "UI5"
			},
			"sap.ui5": {
				"componentName": "launchpaddemoplugin",
				"_version": "1.2.0"
			},
			"sap.platform.runtime": {
				"componentProperties": {
					"url": "/launchpaddemoplugin_dest"
				}
			},
			"sap.flp": {
				"type": "plugin"
			}
		}
	},
	"groups": {
		"5acadc20-687e-11e6-8b77-86f30ca893d3": {
			"identification": {
				"id": "5acadc20-687e-11e6-8b77-86f30ca893d3",
				"i18n": "i18n/i18n.properties",
				"namespace": "",
				"title": "{{group_title}}"
			},
			"payload": {
				"tiles": [{
					"id": "mySapTile",
					"appId": "73c3f80a-5245-4e6c-a51d-d9436b1cb530",
					"entityType": "tile",
					"target": {
						"semanticObject": "Sap",
						"action": "show",
						"parameters": [

						]
					}
				}, {
					"id": "myUi5Tile",
					"appId": "6ef9cdd2-687e-11e6-8b77-86f30ca893d3",
					"entityType": "tile",
					"target": {
						"semanticObject": "app",
						"action": "show",
						"parameters": [

						]
					}
				}]
			}
		}
	},
	"siteThemes": {
		"sap_hcb": {
			"description": "SAP High Contrast Black",
			"name": "sap_hcb",
			"path": "sap_hcb"
		},
		"sap_belize_plus": {
			"description": "SAP Belize Plus",
			"name": "sap_belize_plus",
			"path": "sap_belize_plus"
		},
		"sap_belize": {
			"description": "SAP Belize",
			"name": "sap_belize",
			"path": "sap_belize"
		}
	}
}

The launchpaddemo mta.yaml is modified the same way in my previous post to allow cross-MTA dependency

ID: launchpaddemo
_schema-version: '2.1'
version: 0.0.1

modules:
 - name: launchpaddemo-launchpaddemo
   type: siteentry
   path: launchpaddemo
   parameters:
      memory: 64M
   requires:
    - name: sap-portal-services-host-launchpaddemo
    - name: portal-uaa-launchpaddemo
    - name: sapui5-provider
      properties:
         sapui5url: ~{url}
    - name: launchpaddemoplugin_ref
      group: destinations
      properties:
        name: launchpaddemoplugin_dest
        url: '~{url}/launchpaddemoplugin'
        forwardAuthToken: true


 - name: launchpaddemo-Content-launchpaddemo
   type: sitecontent
   path: launchpaddemo-Content
   parameters:
      memory: 32M
   requires:
    - name: sap-portal-services-client-launchpaddemo
    - name: portal-uaa-launchpaddemo

resources:
 - name: sap-portal-services-host-launchpaddemo
   parameters:
      config:
         siteId: launchpaddemo
   type: com.sap.portal.site-host

 - name: portal-uaa-launchpaddemo
   parameters:
      service-plan: space
   type: com.sap.xs.uaa


 - name: sapui5-provider
   parameters:
      provider-id: com.sap.ui5.dist.sapui5-dist-xsa.XSAC_UI5_FESV5:sapui5_fesv5
      version: '>=1.60.0'
      provider-nid: mta
   type: configuration


 - name: sap-portal-services-client-launchpaddemo
   parameters:
      config:
         siteId: launchpaddemo
   type: com.sap.portal.site-content
   
   
 - name: launchpaddemoplugin_ref
   type: configuration
   parameters:
      provider-nid: mta
      provider-id: launchpaddemoplugin:launchpaddemoplugin_ref
      version: '>=0.0.1'

Build and deploy the launchpad

 

Run the launchpad

You can now see the + button added to the header of the launchpad by the plugin.

 

When you click on the + button in the header the functionality provided by the plugin is executed.

 

Congratulations! This SAP Fiori Launchpad has been extended to improve your experience, On-Premise!

 

4 Comments
You must be Logged on to comment or reply to a post.
  • First of all, many thanks for sharing all what you bring in your blogs. For all of us landing on XSA this information is priceless. As you mention, there is no much info out there and, particularly in my case, I guess the learning curve on this topic is taking a bit ūüôā

    What it leads to this silly question, but trying for a time with no success: https://answers.sap.com/questions/13027301/xsa-apply-a-custom-theme-to-launchpad-site.html

     

    Given the fact that I’m unable to make it work following the natural way: Theme UI Designer + themes local folder + settings in site-content.json and xs-app.json… is there any way, by using plugins, to change the logo in Launchpad?

     

    Many thanks in advance.

    Regards,

    Daniel

    • Hi Daniel,

       

      I am glad you have found my blogs useful. This should be done with theme designer, I would not attempt to do it with extensions/plugins. I have spotted an issue with your config and replied directly to your question.

       

      Thanks,

      Brad.

  • Hi Brad,

    great content and as said before there isn’t much out there that gives examples. Now I’m left with a question that might be so simple that you found it not worth mentioning: Which settings do I need to call my XSA UI5 application? I believe I need to set it in the manifest.json:

    	"sap.ui5": {
    		"componentName": "sap.ushell.demo.AppPersSample2",
    		"_version": "1.2.0"
    	},
    	"sap.platform.cf": {
    		"uri": "/maintain_contact_person/webapp",
    		"oAuthScopes": []
    	}

    And I suspect it ought to be set in the two entries above. But I couldn’t find how to do it. Also I wonder (as the port changes dynamically of each app) how the launchpad will get that information (application router)? Any hint? Above was just a rough guess and it didn’t work.

    Thanks,

    Gunter

    • Hi Gunter,

      It is difficult to tell exactly what you are referring to without seeing all of your code. You do not need to set anything up in the manifest.json of the plugin application.

      The linking works via destination. As you can see in my example in the site-content.json I have ‚Äúlaunchpaddemoplugin_dest‚ÄĚ in the url property.

      "sap.ui5": {
      	"componentName": "launchpaddemoplugin",
      	"_version": "1.2.0"
      },
      "sap.platform.runtime": {
      	"componentProperties": {
      		"url": "/launchpaddemoplugin_dest"
      	}
      },

       

      This is referencing the destination setup in the mta.yaml. This works by referencing the mta containing the application. The actual url with any ports is registered when the launchpad is deployed.

      you can see this in the cockpit under user provided variables for the launchpad application:

      destinations	[
      {
      "forwardAuthToken": true,
      "name": "launchpaddemoplugin_dest",
      "url": "https://hxehost:51069/launchpaddemoplugin"
      }
      ]

       

      under resources in the mta.yaml:

      - name: launchpaddemoplugin_ref
         type: configuration
         parameters:
            provider-nid: mta
            provider-id: launchpaddemoplugin:launchpaddemoplugin_ref
            version: '>=0.0.1'

      This is how the plugin mta is linked.

       

      under modules in the mta.yaml:

      modules:
       - name: launchpaddemo-launchpaddemo
         type: siteentry
         path: launchpaddemo
         parameters:
            memory: 64M
         requires:
          - name: sap-portal-services-host-launchpaddemo
          - name: portal-uaa-launchpaddemo
          - name: sapui5-provider
            properties:
               sapui5url: ~{url}
          - name: launchpaddemoplugin_ref
            group: destinations
            properties:
              name: launchpaddemoplugin_dest
              url: '~{url}/launchpaddemoplugin'
              forwardAuthToken: true

       

      In the requires section, you will see we declare the destination name ‚Äúlaunchpaddemoplugin_dest‚ÄĚ which is used in the site-content.json.

      the route is also added to the xs-app.json file in the launchpad allowing access to the destination:

      {
      	"routes": [{
      		"source": "^/launchpaddemoplugin_dest/(.*)$",
      		"destination": "launchpaddemoplugin_dest",
      		"target": "$1"
      	}]
      }

       

      Feel free to download the sample code from my github and get that running on your server. You will need to deploy the plugin application before the launchpad.

      You may also choose to embed the plugin into the launchpad itself. In that case you would place the plugin under the folder ‚Äúlaunchpaddemo/launchpaddemo/resources‚ÄĚ The destination does not need to be setup in this case, and the url would simply point to the folder created under resources.

       

      I hope this helps to answer your question.

       

      Thanks,

      Brad.

       

       

      /