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).
Now it is time to dive under the hood, and understand a little bit more of the concepts related to the development of multi-module applications.
As discussed in the introduction of this tutorial, business applications usually consist of multiple modules, e.g. a database model, Java or Node.js business logic, a UI app that are deployed to different target runtimes.
Development of such applications requires careful coordination of APIs and dependencies. Deploying such applications is even more challenging due to the need to orchestrate and provision the different parts and targets.
The SAP Web IDE supports the development, testing and deployment of entire multi-module applications in the context of a so-called multi-target applications (MTA) project. The development process is governed by a special meta-file, which we have already met, the MTA descriptor (mta.yaml).
The following illustration shows the structure of the fully expanded TinyWorld project (a few hidden "system files" are intentionally not shown):
The Local folder is the root folder for all projects, and represents your "workspace". There can be more than one project per workspace. A project is simply a folder structure with multiple modules. Here we can see three modules:
module type | source folder | special files | special file role | ||
TinyDB | HANA database type: hdb | src/ | - | ||
TinyJS | Node.js (xsjs) | lib/ | package.json | identifies "server.js" as the "main" entry point of the application | |
server.js | imports "xsjs" compatibility layer and refers to "lib/index.xsjs" | ||||
TinyUI | HTML | resources/ | xs-app.json | names the default html file ("index.html"), determines whether users can access the app anonymously or need to authenticate, and declares a mapping of external URLs, called "routes" | |
package.json | Future: currently do not change this file. |
In addition to the above structure, there may be additional, normally hidden, special files: a folder called .git/ (used by the version control system), a folder called .che/ (used to record workspace state), and within HDB source folders, two files respectively called .hdbconfig, and .hdbnamespace. You normally don’t need to be concerned with any of these files.
Each project root folder also contains the MTA descriptor, mta.yaml, discussed in more details below.
The MTA descriptor file is automatically created and maintained by the Web IDE. When we created the application project in part 2 of this tutorial, a small skeleton was created. Initially, it didn't have a lot of interesting content:
As we started adding modules to the project, the MTA descriptor file automatically changed. Here is what it looked like at the end of part 3 of this tutorial:
Let's take a closer look.
Lines 1-3 are like a header, providing the application unique id and its current version. The ID and version properties uniquely represent the application version in the production environment. By convention, ID is a reverse-URL dot-notation, e.g. com.acme.demo.tinyworld. In this tutorial, we keep it simple: just tinyworld. Version follows the semantic versioning standard (http://semver.org/).
Lines 5-31 describe the modules of the application. Each module has a type (hdb, nodejs or ui5) and a path to its source code, relative to the MTA root. TinyWorld has three modules.
Lines 33-35 describe the resources on which the application depends. Here, we have only one resource, a HDI container (of type "com.sap.xs.hdi-container") named laconically hdi-container.
One of the most complex aspects of developing interacting application modules in XS Advanced is the question of how a module knows the access point of another module.
How can you write a UI that calls an OData service, when you don’t know what the URL of that service will be at runtime, as it can theoretically be deployed on any host under XS Advanced management? Or, how can you write a database module that must run inside an HDI container that may later be established by a HANA administrator on a productive database? Or how can you specify that a certain business logic module should only be deployed after the database module it depends on has been deployed?
The role of the MTA descriptor is to describe the logical dependencies between all the modules of an MTA. It does this with variables in "requires" and corresponding "provides" sections, and with predefined (reserved) variables, like ${default-url}. The value of this variable will be determined and substituted when the application is deployed (a topic we will discuss in more detail in part 9 of this tutorial).
Let’s examine the dependencies of our small application.
On line 10 you can see that the tinydb module uses a "requires" section to declare the specific database container to which the code will deployed (lines 10). The MTA descriptor is tracked by the development and deployment tools. For instance, when you "build" the tinydb module, the tools will automatically create and provision the necessary database container and associated XS Advanced services, technical users and permissions, both during development, and later during deployment.
Line 16 shows how the tinyjs module has a dependency on tinydb (so you won’t be able to run tinyjs unless you first build tinydb) and on the HDI container which its code accesses (line 17).
The tinyjs module has a "provides" section (lines 18-21), containing a variable tinyjs_api with a property named service_url that has the reserved value of ${default-url}. So how does this work?
Check out the definition of tinyui. As we already know, this module is going to call the OData interface exposed by tinyjs, and thus needs to know its URL. It therefore "requires" the variable tinyjs_api.
The actual "binding" to the URL of tinyjs is performed by the XS Advanced "approuter" application.
This application expects to access an environment variable called destinations, which has a predefined "grouped" structure of name-value pairs. We create this grouped structure via defining a property tinyjs_be with the value of the local variable ~{service_url} i.e. tinyjs's runtime URL. To close the loop, the same property must also be listed as a route in the approuter's configuration file, xs-app.json, as already discussed in part 3 of this tutorial:
{"source": "^/euro.xsodata/.*$", "destination": "tinyjs_be"}
To summarize: the "approuter" will use this information to route euro.xsodata to the destination URL defined by the tinyjs_be property, which is automatically mapped to the OData service of the tinyjs module.
Yes, it looks a little complicated at first, but the benefits far outweigh this. As mentioned, the MTA descriptor is tracked by the development and deployment tools which automatically create and provision the necessary dependencies and associated XS Advanced services, technical users and permissions, both during development, and later during deployment. This beats, hands-down, the need to hard-code absolute values in various "manifest" files, and modify these hard-coded values for each landscape that you deploy your application to!
CDS artifacts are created in a context, which adheres to certain conventions. While this is not a CDS tutorial, the following table will help you keep things consistent when creating and deploying CDS artifacts with the Web IDE:
Web IDE concept | workspace | matching CDS code | resulting HANA entity |
project name P | project folder P | - | |
module name M | module subfolder M | - | |
namespace N | in file .hdbnamespace | namespace N | |
CDS filename C | file C.hdbcds | context C | |
- | entity E | table named: N::C.E in container called workspace<id>-P-hdi-container[_n] |
XS Advanced is based on the cloud principles of the Cloud Foundry architecture. This imposes new challenges when it comes to developing the multiple parts of a business application, in a way that is independent of the actual system and landscape in which the application will be deployed. Here we took a look under the hood of MTAs - the muti-target source specification that makes this possible. More details can be found in the SAP HANA developer documentation.
You can continue to explore the more advanced parts of this TinyWorld tutorial, covering things like the use of version control, adding authentication and authorization control to our application, and how to manage the life cycle of our application, from development to deployment, in the following parts of the TinyWorld tutorial:
Part 8: Source control
Part 9: Application life cycle
Part 10: Add authentication
Part 11: Add authorization
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
17 | |
14 | |
14 | |
12 | |
11 | |
9 | |
9 | |
8 | |
8 | |
7 |