Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
chaimbendelac
Advisor
Advisor
0 Kudos


TinyWorld - Part 9

Application life cycle

Hello!



In Introduction to the TinyWorld application we introduced the TinyWorld muti-part tutorial, describing how to develop applications for SAP HANA and XS Advanced, using the SAP Web IDE for SAP HANA (Web IDE). Here we continue with our "advanced" topics, and this time we are going to discuss "life cycle management".



The term Application Life Cycle generally describes the processes followed by an administrator to transport, install, deploy, maintain and upgrade applications for productive systems. With SAP HANA and XS Advanced, applications are transported in the form of a (compressed and digitally signed) archive called an MTA archive (MTAR).

Deploying an MTA involves deploying each module to its corresponding target runtime.

Deploy TinyWorld

We will complete this task in two steps:

  1. First, as a developer, we create an MTA archive.

  2. Then, as an administrator, using the xs command-line tool, we will deploy it into another space, possibly on another system. The administrator must have SpaceDeveloper privileges in this space.

A. Create the MTA archive

Build the modules in the following order (right click each module folder " > Build"): tinydb, then tinyjs and last tinyui.

The ID and version properties in the mta.yaml file uniquely represent the application version in the production environment. For the first version of our application let's update the value to 1.0.0.

Now build the entire project right-click the tinyworld/ project folder and "> Build". After successful build, you will find the created MTA archive in the root mta_archives/tinyworld/ folder.

As you can see, the name of the MTA archive, tinyworld_1.0.0.mtar, is constructed from the MTA ID and version.

Download the archive to your local workstation (right-click tinyworld_1.0.0.mtar "Export").

 

B. Deploy using the xs deploy command

As an administrator, use the xs command line tool to login into XS Advanced on the target system, organization and space (see the XS Advanced documentation). In this tutorial we will use Rita as our administrator, myorg as our organization and PROD as our space.

You can use this command to verify that Rita's privileges are sufficient:


xs space-users myorg PROD




Rita's user name should appear in the users column of the "SpaceDeveloper" row. If not, an administrator with administrative rights should grant Rita the required permissions:


xs set-space-role Rita myorg PROD SpaceDeveloper




To verify that we are targeting the right space (PROD) run:


xs target




To switch to the correct space (if not already there) run:


xs target -o myorg –s PROD




Now navigate to the folder where you placed the MTA archive and run:


xs deploy tinyworld_1.0.0.mtar --use-namespaces




Wait patiently for the "Process finished" message. That's it!

Some other useful commands so you can confirm that your application is up and running:

  • List all apps in the target space: xs apps
  • List all multi-target apps: xs mtas
  • Display information about a multi-target app: xs mta tinyworld

Copy the URL of the tinyui module (xs app tinyworld.tinyui --urls) and paste it in the browser. You will get the European Countries table on the screen. The table will be empty because we have just deployed this application to a new HDI container, which doesn't have all the content we added manually earlier in this tutorial.

Upgrade TinyWorld to version 2

Now that we successfully deployed the initial version of the tinyworld application, we will add a new feature and then upgrade the production environment.

We are going to place a button on the UI to add new countries. For that, we will also create a new form for collecting country information in the tinyui module and pass this information to the tinyjs module via a POST HTTP request, doing it right this time. Next we will update tinyjs module to process this new API.

From the Web IDE, fetch the most recent code (right click on tinyworld project "Git > Fetch from upstream" and then "Rebase") and make the following changes to the project:

  • Update the file tinyui/resources/index.html with the content below.  The new and changed lines are highlighted: we added a new button above the Country table with a callback openFirstDialog that is defined in a new file, Util.js, that we will create next.


<!DOCTYPE HTML><head><meta http-equiv="X-UA-Compatible" content="IE=Edge" />


<title>DevXdemo</title>



<script src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"


id="sap-ui-bootstrap" data-sap-ui-libs="sap.ui.commons, sap.ui.table" data-sap-ui-theme="sap_bluecrystal">


</script>



<script src="./Util.js" > </script>



<script>


  var oModel = new sap.ui.model.odata.ODataModel("/euro.xsodata", true);


  var oTable = new sap.ui.table.Table({


              title: "European Countries", visibleRowCount: 5, id: "tinytab",


              toolbar: new sap.ui.commons.Toolbar({items: [


              new sap.ui.commons.Button({text: "Add Country", press:openFirstDialog})


       ]})});


    


  oTable.addColumn(new sap.ui.table.Column({ label: "Country Name", template: "name" }));


  oTable.setModel(oModel); oTable.bindRows("/euro"); oTable.placeAt("content");


    


</script>


</head>



<body class='sapUiBody'> <div id='content'></div> </body> </html>




  • Create a new file Util.js in the same tinyui/resources/ folder and copy this code there:


var oFirstDialog;



function openFirstDialog() {


  if (oFirstDialog) {


     oFirstDialog.open();


  } else {


     oFirstDialog = new sap.ui.commons.Dialog({


         width: "400px", // sap.ui.core.CSSSize


         height: "550px", // sap.ui.core.CSSSize


         title: "Country Details", // string


         applyContentPadding: true, // boolean


         modal: true, // boolean


         content: [new sap.ui.commons.form.SimpleForm({


            content: [


               new sap.ui.core.Title({ text: "Country Name" }),


               new sap.ui.commons.Label({ text: "name"}),


               new sap.ui.commons.TextField({ value: "", id: "name" }),


               new sap.ui.commons.Label({ text: "partof" }),


               new sap.ui.commons.TextField({ value: "", id: "partof" })


            ]


         })] // sap.ui.core.Control


  });



     oFirstDialog.addButton(new sap.ui.commons.Button({


         text: "OK",


         press: function() {


            var name = sap.ui.getCore().byId("name").getValue();


            var partof = sap.ui.getCore().byId("partof").getValue();


            var payload = {};


            payload.name = name;


            payload.partof = partof;


            var insertdata = JSON.stringify(payload);


         


            $.ajax({


               type: "POST",


               url: "country/country.xsjs",


               contentType: "application/json",


               data: insertdata,


               dataType: "json",


               crossDomain: true,


               success: function(data) {


                  oFirstDialog.close();


                  sap.ui.getCore().byId("tinytab").getModel().refresh(true);


                  alert("Data inserted successfully");


               },


               error: function(data) {


                  var message = JSON.stringify(data);


                  alert(message);


               }


            });


         }


   }));



   oFirstDialog.open();


}


}




This code creates a small form with two fields and 'OK' button where users can enter a new country name and continent. When the user clicks the 'OK' button we construct and send the POST request to the server.

  • To make the request reach the server we need to update xs-app.json with additional route:


{


    welcomeFile": "index.html",


    "authenticationMethod": "none",


    "routes": [{


         "source": "^/euro.xsodata/.*$",


         "destination": "tinyjs_be"


     }, {


         "source": ".*\\.xsjs",


         "destination": "tinyjs_be"


     }]


}




  • Now a small change is required in tinyjs/lib/country/country.xsjs.  We will fetch country data from the request body instead of URL parameters (as expected by the HTTP POST method) and will return success or failure status at the end (the updated lines are highlighted):


function saveCountry(country) {


var conn = $.hdb.getConnection();


var output = JSON.stringify(country);


var fnCreateCountry = conn.loadProcedure("tinyworld.tinydb::createCountry");


var result = fnCreateCountry({IM_COUNTRY: country.name, IM_CONTINENT: country.partof});


conn.commit();


conn.close();


if (result && result.EX_ERROR != null) {


      return {body : result, status: $.net.http.BAD_REQUEST};



} else {


      return {body : output, status: $.net.http.CREATED};


}


}



var body = $.request.body.asString();


var country = JSON.parse(body);



// validate the inputs here!



var output = saveCountry(country);



$.response.contentType = "application/json";


$.response.setBody(output.body);


$.response.status = output.status;




Now you can build your tinydb module, and then run the tinyjs and tinyui modules one by one.

If everything went well you will see "Add Country" button in your running application.

Press the button, then fill the input fields (Ireland, Europe) in the Country Details form and click "OK".  If you see Ireland in the table, great!  You can release the new version.

First we will update the version in the mta.yaml file to 2.0.0



Next we will push the changed and newly created files to our remote Git repository.  You can find them in the Git pane and like before, you complete the task in three steps: select "Stage All", provide a Commit Description, and click on "Commit and Push".


Now rebuild the tinyworld modules and project like before, to result in a new MTA archive in the mta_archives/ folder, called tinyworld_2.0.0.mtar, that you can export.

In your role as an administrator, you could now deploy the new version with the xs deploy command that we already used for the original installation.

However this time let's configure a lower memory limit for TinyWorld. The default deployment memory allocation is one GB, which is way too much.

In the same workstation folder where you placed the MTA archive, use a local editor to create a new file, configv2.mtaext, with the content:


_schema-version: "2.0.0"


ID: tinyworld.memory.config


extends: tinyworld



modules:


  - name: tinyui


    parameters:


      memory: 128M



  - name: tinyjs


    parameters:


      memory: 128M




We just created an extension descriptor for our MTA archive. It extends the main descriptor that was created and packaged in the Web IDE (by the developer). In this extension file you added a new parameter memory to tinyjs and tinyui modules that will be considered during deployment.

Now run the deployment command providing the configv2.mtaext file:


xs deploy tinyworld_2.0.0.mtar -e configv2.mtaext  --use-namespaces




If you now run the xs apps command, you will see that the memory configurations were applied:

 

Now take the UI module URL (xs app tinyworld.tinyui --urls) and run it in the browser. If you see the Country table, your work is done.


Note: Remember again, like the initial version, we have just deployed this application to a new HDI container, which doesn't have the content we added manually earlier in this tutorial. Thus, trying to add a country will fail for lack of continents. A real application needs to take care of such details, and programmatically handle changes to database structures as well, when necessary.



Summary of part 9

This part of the TinyWorld tutorial described the process of deploying and upgrading your application to production systems.

You can continue to explore additional advanced parts of this TinyWorld tutorial, to learn how to add authentication and authorization control to our application:

Part 10: Add authentication

Part 11: Add authorization


6 Comments