Quantcast
Viewing all 676 articles
Browse latest View live

Exact Months/Years/Quarter etc.. between two dates by Stored Procedure

We generally face issue while deriving Number of years/Months and Quarter etc. between 2 DATES.  Below is the code I have implemented for one of my application , which I am sharing.

 

We can use the "_SYS_BI"."M_TIME_DIMENSION" table in various other way, but this is one of its way of using and calling that where ever necessary.

 

 

/********* Begin Procedure Script ************/ 
BEGIN
IF UPPER(:IP_TYPE) = 'M' 
 then
 var1 =  SELECT 
 COUNT(*)-1 as VAL
FROM
 (
 SELECT DISTINCT YEAR, MONTH FROM "_SYS_BI"."M_TIME_DIMENSION"
 WHERE DATE_SQL BETWEEN :IP_DATE1 AND :IP_DATE2
 );
ELSEIF UPPER(:IP_TYPE) = 'Q'
 then 
 var1 =  SELECT 
 COUNT(*)-1 as VAL
FROM
 (
 SELECT DISTINCT YEAR,QUARTER FROM "_SYS_BI"."M_TIME_DIMENSION"
 WHERE DATE_SQL BETWEEN :IP_DATE1 AND :IP_DATE2
 );
ELSEIF UPPER(:IP_TYPE) = 'Y'
 then 
 var1 =  SELECT 
 COUNT(*)-1  as VAL
 FROM
 (
 SELECT DISTINCT YEAR FROM "_SYS_BI"."M_TIME_DIMENSION"
 WHERE DATE_SQL BETWEEN :IP_DATE1 AND :IP_DATE2
 );
END IF;
OUTPUT_TABLE = select * from :var1;
END;
 /********* End Procedure Script ************/

After activating the SP, we can call from SQL console and it will show the output as below.

 

call "_SYS_BIC"."users.Chandan/SP_TEST_TIME_DIM"('2015-03-01','2016-03-01','m',NULL);
call "_SYS_BIC"."users.Chandan/SP_TEST_TIME_DIM"('2015-03-01','2016-03-01','q',NULL);
call "_SYS_BIC"."users.Chandan/SP_TEST_TIME_DIM"('2015-03-01','2016-03-01','y',NULL);
call "_SYS_BIC"."users.Chandan/SP_TEST_TIME_DIM"('2015-03-01','2016-03-01','M',NULL);
call "_SYS_BIC"."users.Chandan/SP_TEST_TIME_DIM"('2015-03-01','2016-03-01','Q',NULL);
call "_SYS_BIC"."users.Chandan/SP_TEST_TIME_DIM"('2015-03-01','2016-03-01','Y',NULL);

The output we are going to get is as below.

 

Image may be NSFW.
Clik here to view.
Capture.PNG

 

Hope it will helps!

 

I welcome any upgradation on this. Image may be NSFW.
Clik here to view.


Hana Smart Data Integration - SQL Server LogReader Adapter

This SDI adapter is used to read and load SQL Server data and supports batch and realtime. It is based on the Sybase RepAgent for realtime capture of changes.

 

SDA usage

 

The remote source object in Hana is pretty much what one would expect. It asks for the SQL Server hostname and port, login credentials and a database name. The same parameters entered when connecting to a SQL Server database using any other tool.

 

Note: We talk about the MSsqlLogReaderAdapter here, not the ODBC driver!

 

Image may be NSFW.
Clik here to view.
sqlserver1.png

 

But let's go though the settings slowly.


  • Rest should be self explanatory.The Instance Name is any arbitrary text. The logreader adapter will create a subdirectory with all its settings for this remote source. And since a remote source points to one database of a SQL Server Instance, there might be multiples.
  • Administraton Port is the port to be used by the RepAgent. Again, any will do as long as this port (plus the next higher number) is available. A common choice for the first remote source on this SQL Server instance is 13456, meaning it will be using the port 13456 and 13457.
  • Data Server used by the adapter. Typically the logreader adapter is installed on the SQL Server computer itself. Therefore, as seen from the adapter, the SQL Server instance is installed on the local host. Remember: The communication between Hana and the adapter hapens via the DPAgent. When configuring it, the remote server name was specified.
  • Port Number of the SQL Server instance. The default port for SQL Server's first instance is 1433. To find out for sure, see below the installation chapter.
  • DAC Port Number: By default one higher than the standard port. Certain SQL Server operations are not allowed via a regular SQL connection, an Direct Administration Communication protocol is required for that. For pure SDA use cases it is actually not used.
  • Database Name with the data. This remote source points to one database of the SQL server instance only, an existing database has to be specified.
  • The Use Remote Database setting is again used for realtime only, it hints to the adapter if the adapter runs on the SQL Server computer or somewhere remote.

 

To find out the SQL Server Port being used, open the SQL Server Configuration Manager.

Image may be NSFW.
Clik here to view.
sqlserver2.png

 

 

 

With these settings the remote source can be browsed and all virtual table be created.

Image may be NSFW.
Clik here to view.
sqlserver3.png

 

The SDA part of the adapter is fairly simple. It gets a SQL statement in Hana syntax and translates it into SQL Server syntax, data is converted from source into Hana datatypes.

Hence the adapter supports all typical pushdowns, joins, where clauses, functions,.... really extensive.

It even supports insert/update/delete statements executed against the virtual table.

 

Installation of the Adapter

 

The adapter itself is part of the DPAgent installer, but its JDBC driver is missing as SAP cannot distribute software owned by somebody else. Therefore the MSSQLServer JDBC driver in version 4.0 has to be downloaded, extracted and then the JAR file is copied into the <DPAgent>/lib/ folder.

The download page is here: https://www.microsoft.com/en-us/download/details.aspx?id=11774

On the next page the 4.0 version should be selected for download and once available locally, the content can be extracted - the exe files are self packed archives either.

Locate the sqljdbc4.jar file and copy it into the lib folder of the location where the DPAgent was installed - by default that would be c:\usr\sap\dataprovagent.

 

Image may be NSFW.
Clik here to view.
sqlserver4.png

 

 

Now the Adapter can be deployed via the AgentConfig Tool (see here how to install it).

 

Image may be NSFW.
Clik here to view.
sqlserver5.png

 

 

Realtime

 

SQL Server supports one method to identify changes in the database, the CDC API. This adds a change table for every source table, thus every change in the original table causes one full row to be written into the change table. And when reading all changes, every single change table has to be queried to find out what kind of changes there had been. For a handful of tables that is okay but scanning 1000's of change tables every second just to find out that nothing was changed? This is a huge overhead.

SQLServer also supports reading the transaction log, which contain all the changes the database made anyhow. So this would be a much better starting point. The command "dbcc LOGINFO" provides some insight and there are more hidden options (described e.g. here). But this is more for recovery purpose. One major issue with that other than being hard to decode the data is the fact that SQL Server might truncate the transaction log at any time. In case the reading of the log is too slow that would mean data can be lost. Not acceptable of course. But there is another SQL server feature, the Replication option, which works on transaction logs as well and for that Microsoft had to solve the log transaction problem as well - they do not truncate the log until the replication process is done. This proofs the fact that transaction log reading is an option, just very difficult.

Sybase has solved that problem already, hence the Logreader Adapter can utilize the RepAgent code as second option.

 

So the adapter supports two replication technologies, "Native Mode" means reading the transaction log or "MSSQL CDC Mode" using the SQL Server CDC API.

 

For the MSSQL CDC Mode nothing has to be done. The adapter does issue the required SQL Server commands and starts reading the changes.

 

Setting up Transaction Log reading

 

For the transaction log reading, that is where SQL Server has no direct support and requires a few steps hence. Actually, the documentation describes these steps quite nicely, hence the steps are copied only but augmented with images and hints.

 

The first step is to create a user called DP_USER and make it a sysadmin.

 

use master

go

create login DP_USER with password =‘<password>

go

use <your database>

go

create user DP_USER for login DP_USER

go

EXEC sp_addsrvrolemember ‘DP_USER’, ‘sysadmin’

go

 

 

Aforementioned Direct Administration Connection (DAC) is used by the RepAgent to execute statements not possible via a regular SQL connection, hence needs to be enabled.

Log on to Microsoft SQL Server using the DP_USER login and change the Microsoft SQL Server Remote Admin Connections Configuration option to enable DAC to allow remote connections.

sp_configure ‘remote admin connections’, 1

go

reconfigure

go

Verify the remote admin connection string.

sp_configure ‘remote admin connections’

go

 

 

Make the SQL Server log files available to RepAgent

 

In Windows Explorer, navigate to the sybfilter driver installation directory. This directory is located at <DPAgent_root>\LogReader\sybfilter\system\winx64, where <DPAgent_root> is the root directory of the Data Provisioning Agent installation.

Right-click the sybfilter.inf and select "install" to install the sybfilter driver.

Under any directory <DPAgent_root>\LogReader\sybfilter\system\winx64 create a file named LogPath.cfg.

Add a system environment variable named RACFGFilePath and set its value to the full path of the configuration file.

In Windows Explorer, navigate to <DPAgent_root>\LogReader\sybfilter\bin\, and right-click the sybfiltermgr.exe file and then select "Run as administrator" to start the sybfilter driver management console.

To start the sybfilter driver, enter "start" in this screen.

Add the log file path to the sybfilter driver by typing "add serverName dbName logFilePath" in the sybfiltermgr program. For example, to add log file named pdb1_log.ldf for the database pdb1 on the data server PVGD50857069A\MSSQLSERVER, use this:

add PVGD50857069A\MSSQLSERVER pdb1 C:\Mssql2012\MSSQL11.MSSQLSERVER\MSSQL\DATA\pdb1_log.ldf

 

Restart Microsoft SQL Server to make the log file readable.

Execute the "check" command in the sybfiltermgr console screen.

Image may be NSFW.
Clik here to view.
sqlserver6.png

 

Open the Windows Services screen and stop all services related to the database instance, the database, the agent, all...

Right-click your Microsoft SQL Server instance and choose Properties

Under Start parameters, enter -m

Click Start to restart the instance in single user mode

 

Connect to Microsoft SQL Server using dedicated administrator connection (DAC)

Start SQL Server Management Studio without logging in and select File -> New -> Database Engine Query.

In the Connect to Database Engine dialog box, in the Server name box, type ADMIN: followed by the name of the server instance. For example, to connect to a server instance named ACCT\PAYABLE, type ADMIN:ACCT\PAYABLE.

Complete the Authentication section, providing credentials for a member of the sysadmin group and then click Connect.

In case this connection is the first one the login will succeed and the connection has full control of the SQL Server instance including hidden features. To validate the server truly is in Single User Mode, type

use mssqlsystemresource

go

In case this hidden database cannot be found, either the server is not in single user mode or the connection is not using DAC.

Copy the script contents from <DPAgent_root>\LogReader\scripts\mssql_server_init.sql into the SQL Server Studio Query screen and execute the script to initialize the server for replication.

Stop and restart Microsoft SQL Server service back to normal mode by removing the -m option from above.

 

 

Using the realtime subscriptions

 

With the adapter being ready, it is just a matter of setting up a realtime subscription for the virtual table and doing something with the data. For this there are multiple options, starting from creating a .hdbreptask to simply replicate a few tables from this source database into Hana or using the previously imported virtual table in a realtime .hdbflowgraph.

Or simply using SQL commands which the UIs do under the cover as well.

 

create column table t_test1 like v_test1;

 

 

create remote subscription s_test1 on v_test1 target table t_test1;

 

 

alter remote subscription s_test1 queue;

 

 

insert into t_test1 select * from v_test1;

 

 

alter remote subscription s_test1 distribute;

 

select * from v_test1;

select * from t_test1:

 

In above example a table in Hana is created with the exact same structure and primary key as the source.

Then a remote subscription is created loading all change data into the target table.

With the alter remote subscription .. queue command the adapter is told to start capturing changes in the source.

Then the current data is copied from the source into the target table - else a source update statement would not find a row to update in the target.

And finally with the distribute the changes are really starting to be applied to the target table and from now on the target table will be in sync with the SQL Server table.

 

 

Stored Procedure to check the Change record movement Status across Landscape in CTS+

This blog will show how to use the system table "_SYS_REPO"."CHANGES" to check the Transport movement successful or not in CTS+.

Many a times we face difficulty in checking the change record movement across landscape, because:

  1. 1.Transport Request, which is created in SOLMAN will show Error Code 8 but we need to ignore this after checking the Changes in SQL or Field, individually in the system.
  2. 2.We have to make frequent decision to move the back-out TR, but face many difficulty in finding dependency, as the CTS+ message would not be clearly stating the dependency.
  3. 3.Modeller might not be around to quickly guess, if we have some table creation error/Table updating error.

 

 

So I have created this Stored Procedure, which will quickly check the change record if moved or Not moved.

 

Code Snippet for Stored Procedure:

 /********* Begin Procedure Script ************/ 
BEGIN 
-- Declare variables
DECLARE VAR1 NVARCHAR(10);
select count(*) INTO var1 
from "_SYS_REPO"."CHANGES"
where  CHANGE_NUMBER = :IP_CHANGE_ID
or TO_CHAR(SRC_SYSTEM||'//'||CHANGE_NUMBER) = :IP_CHANGE_ID;
if var1 > 0 
then 
OUT_TABLE =  select 'Yes moved' as RETURN_VAL from dummy;
else
OUT_TABLE =  select 'Not Moved' as RETURN_VAL from dummy;
end if;
END;
 /********* End Procedure Script ************/
call "_SYS_BIC"."users.Chandan/SP_TEST_CHANGE_DONE"('29012',NULL);

 

Hope this logic you can also use to quicken the validation.

I welcome the change or ammendement of this document.

Cheers!

Chandan

Hana Smart Data Integration - The writer types, another hidden gem

Mode "Replication"

 

In the most simple case the goal is a 1:1 replication. The source table and the target tables are identical in structure and content.

The easiest way to accomplish that is via creating a RepTask object.in the WebIDE of Hana and keeping the Load Behavior set to "Replication".

 

Image may be NSFW.
Clik here to view.
replication_load_behavior_replicate.png

 

If the "initial load only" flag is deselected, a realtime subscription for each replicated table is created as well.

 

Image may be NSFW.
Clik here to view.
replication_load_behavior_replicate_subscription.png

 

During the execution, the subscription is activated and all current data copied so that the source and target table contain the very same data.

 

Source

Image may be NSFW.
Clik here to view.
replication_load_behavior_replicate_source1.png

 

Target

Image may be NSFW.
Clik here to view.
replication_load_behavior_replicate_target1.png

 

Whatever changes are made in the source, they are redone in the target as well, for example executing the commands against the source table

 

insert into "D050767::Customer.VT_""dbo"".""address_input"""

values ('2', 'North 1st Street', 'San Jose', '????', 'US');

 

insert into "D050767::Customer.VT_""dbo"".""address_input"""

values ('3', 'Hill Rd Drive 532', 'LA', '90003', 'US');


update "D050767::Customer.VT_""dbo"".""address_input"""

set "postalcode" = '95121' where "customer_id" = '2';


delete from "D050767::Customer.VT_""dbo"".""address_input"""

where "customer_id" = '1';

 

will cause the source to contain this data

 

Image may be NSFW.
Clik here to view.
replication_load_behavior_replicate_source2.png

 

and the target follows suit.

 

Image may be NSFW.
Clik here to view.
replication_load_behavior_replicate_target2.png

 

 

Mode "Replicate with logical delete"

 

As the adapter does send change data, Hana knows what kind of change had been made on the source system. And when loading those changes, it can apply this information plus the time the change was received. That is a quite nice feature as now the user can see what records have been recently changed. Except for deletes, it is hard to see the change information for a record which no longer exists. Therefore the feature "Replicate with logical delete" was added, where a record is not physically deleted but marked as deleted.

If a user wants to see the current data, all he has to do is to filter the records where _CHANGE_TYPE = 'D'. If the user wants to know all changes since a given time, he queries the data based on the _CHANGE_TIME.

 

Image may be NSFW.
Clik here to view.
replication_load_behavior_logical_delete.png

 

Using above example, initially the table is loaded with all the current rows from the source and the _CHANGE_TYPE is 'I' for insert, the _CHANGE_TIME is the time of the execution of the initial load.

 

Image may be NSFW.
Clik here to view.
replication_load_behavior_logical_delete_target1.png

 

And after running above sequence of changes with insert, update and delete the target table looks just like above, but with record customer_id=1 being marked as 'D' for delete instead of being physically removed.

 

Image may be NSFW.
Clik here to view.
replication_load_behavior_logical_delete_target2.png

 

This feature is very important when it comes to loading change data in batch. A source usually does not have any change indicator. That is what makes ETL processes so complex. But with this feature the adapter is sending the changes in realtime into a replica table of Hana and is adding the change type and timestamp columns in addition. Now the batch processes can read from that table as if the source does have a delete marker and a change timestamp for each row.

And to be complete, why does the insert row have a _CHANGE_TYPE of 'A' meaning AutoCorrect Load or upsert? Because a row might have been deleted and then inserted again. The delete would not delete it but mark it as a delete-row. And if a row is inserted after, a primary key violation would be triggered, So instead of executing an insert for insert rows an upsert statement is executed.

And an expert question: Why is the update row an 'A' row? For performance reasons an update is executed as delete followed by an insert. And inserts show up as 'A' rows as stated above.

 

 

Mode "Preserve all"

 

In the most extreme version, the user does want to see all changes being made to a row, not just the latest version like above. This is the Preserve All mode.

This adds the _CHANGE_TYPE and _CHANGE_TIME columns but in addition a _CHANGE_SEQUENCE column as well. The latter is required as within one transaction the same row can be modified multiple times and if such change sequence would be an insert followed by an update 1 and update 2, the order is necessary to replay those changes.

 

Image may be NSFW.
Clik here to view.
replication_load_behavior_preserve_all.png

 

When running the initial load, all rows are copied and the _CHANGE_TYPE is 'I', the _CHANGE_TIME the current time of the start and the _CHANGE_SEQUENCE is irrelevant - one row per source primary key.

 

Image may be NSFW.
Clik here to view.
replication_load_behavior_preserve_all_target1.png

 

After applying the changes to the source table, the target table does look like this

 

Image may be NSFW.
Clik here to view.
replication_load_behavior_preserve_all_target2.png

 

Record with customer_id = 1 got deleted, record customer_id = 2 got inserted and then updated - note the adapter did send a before and after image with the identical _CHANGE_TIMESTAMP. The row with customer_id = 3 inserted.

 

Attention: Be very careful when using such table. This essentially dumps the information Hana gets from the adapter into a table. An adapter is not required to send a before image row, only if the source provides that information.

But more important, there are more _CHANGE_TYPEs than Insert/Update/Delete/Beforeimage/AutocorrectLoad. See Hana Smart Data Integration - The magic behind Adapter Opcodes for details.

 

 

Above modes in FlowGraphs

 

When using Flowgraphs to model data transformations, the same options are available. They are just presented differently.

In the Data Sink object, the target table, there is a Load Type setting. By default it is empty meaning it is a regular loader which does insert insert records, update update records etc.

Setting that to Upsert is what the "Replicate with logical delete" mode does.

And setting it to Insert means writing out all changes in the form of a change log, the "Preserve all" mode.

 

Image may be NSFW.
Clik here to view.
replication_load_webide1.png

 

The columns for the _CHANGE_TYPE and _CHANGE_TIME are available in the second tab. Although these are optional, from a logical point of view they are needed for sure. A logical delete without the information that this row was deleted, so without a change type, makes little sense.

 

Image may be NSFW.
Clik here to view.
replication_load_webide2.png

 

Time for an expert question again: Where is the _CHANGE_SEQUENCE column? (The sequence column in above screen is something else, that is an optional surrogate key)

The Flowgraph cannot cope with multiple changes within one transaction, like the insert-update-update of a single row. The Flowgraph gets an aggregated set of data always, so in this example an insert row with the final update's value.

Hana Smart Data Integration - Transactional consistency and delta handling

When it comes to comparing SDI with other solutions, one major difference is the support of transactional consistency. Some examples where this might come in handy:

 

1. The source has an order table and a reserved goods table. Whenever something is ordered, the goods are reserved and taken out of the stock and then both changes are committed together. So a user in the source system will always see the orders and reserved goods being in sync.

If both tables are copied independently, a user querying the sum of orders and the sum of reserved goods will constantly see those two numbers to be different as there are new orders all the time.

Transactional consistency across tables.

 

2. In the financial booking table every debit booking has a matching credit booking and both are committed together. Hence the sum of bookings is zero always, money is moved from one account to another. It would be outright wrong if the data is replicate and committed in the target differently.

Transactional consistency within tables.

 

3. A new customer called and ordered something. So first the customer master data was entered and a minute later a sales order placed. If both tables are replicated independently, then it might happen that in the target table there is a sales order for a customer did does not exist yet.

Transactional order.

 

4. In the source system a new material was entered, hence inserted into the database but not saved/committed. The user went to lunch and saved it 30 minutes later. The record in the database has a create data, which is 30 minutes before but whoever queries the table does not find the record until it is committed. This is a major problem if for example a delta process relies on this timestamp as it might read all changes with a recent create date but does not see this record for 30 minutes and then it is not recent anymore.

Long running transactions.

 

All of the above examples are huge problems for any ETL tool in the market. But because they ignore above problems they can be very fast during the initial load and partly for the delta loads.

 

With SDI the initial load does happen by reading in parallel for maximum speed and depending on the settings, it works just like all other ETL tools. But during the initial load all changes in the source tables are recorded already and later merged into the target to get a consistent state. The subsequent realtime push of the changes does happen in a transactional fashion honoring the above cases 1-3.

This is possible because the adapter does send all change rows of all tables in the correct order and a commit is a change row of its own, hence the Hana Data Provisioning server can replay the changes with the same transactional bracket and in the same order.

 

This can be seen in the following example, where an insert loader semantic is used:

 

The execution order in the source had been

 

(change 1 via initial load)

insert into address_input

values ('1', 'Innsbrucker Straße 34', 'Salzburg', '5070', 'AT');

commit;

 

(change 1)

insert into address_input

values ('2', 'North 1st Street', 'San Jose', '????', 'US');

commit;

 

(change 2)

insert into address_input

values ('3', 'Hill Rd Drive 532', 'LA', '90003', 'US');

commit;


(change 3 modifying the old record to change 4, the new values)

update address_input

set "postalcode" = '95121' where "customer_id" = '2';

commit;


(change 5)

delete from address_input

where "customer_id" = '1';

commit;


After all these changes the various records look like in the target

customer_id = 1: Had been inserted into Hana at 03:26:55 and deleted at 03:28:56

customer_id = 2: Inserted at 03:28:02 and updated 03:28:44

customer_id = 3: Inserted at 03:28:22

Image may be NSFW.
Clik here to view.
replication_load_behavior_preserve_all_target2.png

 

Preserving the order is key here, e.g. customer_id=2 has to be inserted before being updated, else it does not make sense.

 

Looking at the CHANGE_TIME more closely reveals more details.

First, all rows within the same source transaction all have the same value. In above example all changes have a truly ascending timestamp except for the update, where a before and after image row was generated. This does not have the same value because these rows followed so quickly after each other, they have the exact same value, even at the nano second.

 

This is more obvious when executing a few more changes in the source database.

 

(change 6)

insert into address_input

values ('4', 'Shoreline Bld 1', 'Los Angeles', '90002', 'US');


(change 7)

insert into address_input

values ('5', 'Page Mill Dr', 'Mountain View', '95111', 'US');


(change 8 & 9)

update address_input

set "street" = 'Page Mill Dr 435' where "customer_id" = '5';


(change 10, as this is executed on the Hana system against the virtual table, the insert statement is using the Hana(!!) current timestamp)

insert into address_input

values ('control', now(), now(), null, null);


commit;

 

 

Image may be NSFW.
Clik here to view.
replication_load_transactional_consistency.png

 

All these changes have the same CHANGE_TIME although they have been entered over a period of 5 minutes.

And the last row proves the values does not reflect the change in the source as it was inserted at 03:36:49 in the source but in the target at 03:37:42.

Hence the CHANGE_TIME is not only strictly ascending, it also has no issues with system times being slightly off between different databases, different timezones or whatever.

 

Simply because this value does neither come from the source nor from the adapter but from the Data Provisioning server process of Hana. The DP Server does receive all change rows from the adapter and queues them up until a commit row is received. This is the point in time the CHANGE_TIME variable gets a value, the current timestamp (down to the nanosecond) of the Hana(!) instance, and the Applier process starts merging the data into the target tables.

 

Hence it is the perfect column for a timestamp based delta of subsequent processes.

 

Note: Above works identical if multiple tables are used. The examples show the behavior with a single table for better readability only.

Developing with XS Advanced: A TinyWorld Tutorial

 

TinyWorld - Part 1

Introduction to the TinyWorld application

 

Image may be NSFW.
Clik here to view.
image001.png

 

Hello!

 

In his recent blog post, SAP HANA SPS 11: New Developer Features; XS Advanced, Thomas Jung introduced XS Advanced, the new application service that is included with SAP HANA, starting with SPS11.

 

This blog is the first part in a multi-part tutorial, in which we will learn how to develop business applications for SAP HANA and XS Advanced.


In the past you may have used the SAP HANA studio. In this tutorial, we will build our application using the brand new SAP Web IDE for SAP HANA.


SAP Web IDE for SAP HANA (herein: Web IDE) is available with HANA SPS11 and later, for use with XS Advanced. It is a new adaption of the existing SAP Web IDE (available on HCP), and is specially designed for developing entire business applications on SAP HANA.


Image may be NSFW.
Clik here to view.
screenshot.842.jpg

Figure 1 - SAP Web IDE for SAP HANA


For more information on how to obtain and install the SAP Web IDE for HANA, and for full documentation, see http://scn.sap.com/docs/DOC-71432.



Multi-module business applications

 

Business applications usually consist of multiple tiered parts (modules) which together form a complete application.

 

The most common case is a multi-module application consisting of a database model, some business logic (written in a server-side programming language like Java or Node.js), and a user interface app that accesses the data model via the business logic or via OData interfaces.

 

Developers of multi-module applications must carefully agree on APIs. Testing, installing and deploying such applications (particularly in cloud environments) is very challenging due to the need to orchestrate all these different activities.

 

SAP HANA based multi-module applications usually follow a standard pattern: the database model consists of data aggregations, filters and selection logic on top of basic tables, designed using CDS specification language and rich Calculation Views. The data model can be accessed via SQL, or can be exposed via OData to allow UI apps to directly access the data. UI apps usually use the SAP UI5 design library.

 

 

The TinyWorld application

 

To illustrate the use of the Web IDE and of programming in the SAP HANA XS Advanced environment, we are going to develop a small application called "TinyWorld".

 

TinyWorld is an example of such a three-tier multi-module application. Users use it to create and view a simplified model of the world, merely consisting of continents and their countries.

 

TinyWorld comprises the following modules:

 

  1. tinyui: A UI app module, written with HTLM/JS
  2. tinyjs: A business logic module, written with Node.js
  3. tinydb: An SAP HANA database module

 


As you may have inferred, it is intentionally a really small application, so that you will not be distracted by unnecessary details, and can focus on the development experience of working with SAP HANA and XS Advanced.

 

To gain a good understanding of the development process we recommend that you try to follow the steps of the tutorial in the order it is presented. However, if you do not have time, you can also access and study the source code, and then read this tutorial to understand how it was constructed (see the Appendix for instructions).

 

 

The entire TinyWorld tutorial is structured as follows:

 

Part 1: Introduction to the TinyWorld application (this blog)


The basic tutorial

Part 2:   Get started with the SAP Web IDE for SAP HANA

Part 3:   Create a SAP HANA based client-server application

Part 4:   Add SAP HANA business logic

Part 5:   Add business logic with Node.js


Advanced topics

Part 6:   Create Node.js unit tests

Part 7:   Under the hood

Part 8:   Source control

Part 9:   Application life cycle

Part 10:Add authentication

Part 11:Add authorization


Appendix: Getting the source code

 

More sections will be added over time, so keep checking back.

 

 

Prerequisites for this tutorial


Become a qualified developer

 

To access the Web IDE, you will need the username and password of a development user.  Details depend on how users, authentication and XS Advanced orgs are configured in your landscape. If SAP HANA is the identity provider of your system (usually), here is how your administrator might create a development user called Peter:

 

  • Using a HANA console (Studio, Cockpit, hdbsql client, etc.), enter the following SQL:

 

createuserPeterpassword"MySecret1"setparameter'XS_RC_XS_CONTROLLER_USER'='XS_CONTROLLER_USER'

  • Using the XS command line tools, login to xs (system/installation dependent) and enter:

 

xs set-space-role Peterinitial SAP SpaceDeveloper


Note: In order to deploy applications into another space, you will require SpaceDeveloper rights in that space as well.

 

 

 

Login to the Web IDE and the SAP HANA run time tools

 

The actual URL of the Web IDE is installation dependent. The following command returns the URL in your system:

 

xs app webide -urls

 

Use the resulting URL in your browser (Chrome, Netscape). For the first time, you may be required to change your administrator-provided password (i.e. Mysecret1, in the above example). Also, ignore any "your connection is not private" messages you may see.

 

Similarly, the URL of the SAP HANA runtime tools (herein RTT) can be determined via the following command:


xs app hrtt-core -urls

 

This tool is loaded in a separate browser window.

 

Summary of part 1

This blog is the first of a multi-part tutorial, teaching you how to develop HANA based applications with XS Advanced, using the new SAP Web IDE for SAP HANA development tools.

 

We hope that you will enjoy the rest of this tutorial.

 

And now, let's get started: Get started with the SAP Web IDE for SAP HANA !

Developing with XS Advanced: Get started with the SAP Web IDE for SAP HANA

TinyWorld - Part 2

Get started with the SAP Web IDE for SAP HANA

 

Image may be NSFW.
Clik here to view.
image001.png

 


This is part 2 of the "Developing with XS Advanced" tutorial. In part 1, Introduction to the TinyWorld application, we introduced the TinyWorld application.

 

Now we will get started, by creating a project with three modules, then build and run the first version of this application.

 

Create a project

 

An application is created within a context of a project. There are three options to set up a new project:


  • Create it from scratch, using a "project template"
  • Import a previously exported project archive (zip file)
  • Clone a project from an existing Git repository.

 

Here, we will start completely from scratch. From the file menu, select the "New > Project from Template" wizard:

 

Image may be NSFW.
Clik here to view.
image003.png


There is currently only one project template to select, so click "Next", enter the Project Name tinyworld, optionally add a description, and click "Next" again to complete the wizard. The IDE should now show your tinyworld project like this:

Image may be NSFW.
Clik here to view.
image004.png

 

 

Create a SAP HANA database module

 

Now that we have an empty application project, we can add our first module, which will be a SAP HANA database (HDB) module. Select the tinyworld/ folder, right-click > "New > HDB Module" wizard:

 

Image may be NSFW.
Clik here to view.
image005.png

 

 

Call it tinydb. Keep the default namespace. Complete the wizard to create the module.

 

We will now use CDS to design a small database model. CDS is a SAP enhancement to SQL for defining and consuming semantically rich data models. Navigate to the src/ subfolder of the tinydb/ module folder, right-click it and select "New > CDS Artifact". On the window that opens switch to the text editor, and enter the name of the file: tinyf. Once the editor opens, type the following text into the file, and save it (CTRL/S on Windows).

 

 

namespace tinyworld.tinydb; 

context tinyf {

 

  entity world {

    key continent: String(100);

  };

};

The file is automatically suffixed with .hdbcds. This suffix is important – it determines how the file will be treated in the SAP HANA database. As you can see, our data-model has a single entity (database table) called world, with a single field (column) called continent. Our next step is to build this module, in order to deploy this design-time data model into database catalog objects that can subsequently be used.

 

Build the HDB module

 

Select the tinydb/ module folder, right-click "> Build" (or: select "Build > Build" from the top-menu). This starts the build process.


After a short time you will see this on the console: (Builder) Build of /tinyworld/tinydb completed


The data-model was successfully activated in a SAP HANA database container (aka HDI container), and can now be used to store and retrieve data. We will do this in the next part of this tutorial.


 

Create a Node.js module

 

Next we create our first Node.js app, conveniently based on the XSJS library. First, create a Node.js module. Select the tinyworld/ folder, right-click "New > Node.js module", call it tinyjs, check the "Enable xsjs support" checkbox and finish the wizard. You will now have a new module folder with several files. Look for a file called lib/index.xsjs, and double-click it.  It opens in the JavaScript editor to show code similar to the following:

 

$.response.contentType = "text/html";

$.response.setBody("It's a tiny JS World!");

We could first build the Node.js module, but we can also just directly run it (this will automatically build it too). Select the tinyjs/ module folder, right-click > "Run > Run as Node.js Application".  A new browser tab will open with the URL of the app.


Return to the Web IDE tab, to watch progress on the "Run console". After some delay, the status switches from "New" to "Running" to indicate that your small Node.js app has been deployed to the XS Advanced Node.js runtime. Switch to the app's tab, or access it with the URL you see at the bottom of the Run console, like this:


Image may be NSFW.
Clik here to view.
image006.png

And you will now see "It's a tiny JS World!" on your screen.

 

 

Create an HTML5 module

 

Similarly, add an HTML5 module to the project and call it tinyui. Then, double-click the generated resources/index.html file to open it in the Web IDE HTML/JS editor. Select and replace the file content with the following:

 

<!DOCTYPE html>

<html> <body> Tiny HTML World! </body> </html>

 

Then, run the web app from the toolbar or right-click the tinyui/ module folder > "Run > Run as > Web Application":

 

Image may be NSFW.
Clik here to view.
image007.png

 

The text "Tiny HTML world" will appear in another tab of your browser. You can also click the link to the app which appears at the bottom of the tinyui run console.

 

 

Summary of part 2


In a few minutes, we learned how to use the Web IDE to develop a small (and, admittedly, pretty useless…) application, consisting of three separate modules.


Note that each module stood by itself: the business logic didn't access the data model, and the UI app didn't access the business logic. We will address this in the next part of this TinyWorld tutorial (Create a SAP HANA based client-server application).

 

Other parts of the TinyWorld tutorial:

 

Part 1:Introduction to the TinyWorld application


The basic totorial

Part 2:   Get started with the SAP Web IDE for SAP HANA

Part 3:   Create a SAP HANA based client-server application

Part 4:   Add SAP HANA business logic

Part 5:   Add business logic with Node.js


Advanced topics

Part 6:   Create Node.js unit tests

Part 7:   Under the hood

Part 8:   Source control

Part 9:   Application life cycle

Part 10:Add authentication

Part 11:Add authorization

 

 



Developing with XS Advanced: Create a SAP HANA based client-server application



TinyWorld - Part 3


Create a SAP HANA based client-server application

 

Image may be NSFW.
Clik here to view.
image001.png

 

Hello again!

 

In part 2 (Get started with the SAP Web IDE for SAP HANA) of this TinyWorld tutorial we learned how to create a project, and create, build and run application modules. Here, in part 3, we will extend our application to actually do something more useful.

 

NOTE: In the following, you will need to update the MTA descriptor file – mta.yaml. The YAML syntax is indentation-sensitive, and you should always use spaces, never tabs. The role of the mta.yaml file is further explained in part 7 (Under the hood).

 

Advanced HANA development

Using the CDS graphical editor

 

You can use the CDS text editor, introduced in part 2, to create large and complex data models, but you can also use the CDS graphical editor, side by side with the text editor. Right-click tinyf.hdbcds> "Open with > Graphical Editor" to see:

Image may be NSFW.
Clik here to view.
image008.png

Click the (left-most) Add-Entity icon to create a new entity, and call it country. This will bring up the columns and associations wizard. Click the "+" to add a new column (field), rename it name, change the Data Type to "String", enter a length of 100 and mark it as a key column.

Then click the "Associations" tab, and add a new association. Rename it partof. Under "Target Entity", select the world entity. Now click "< Back" to the main tree view; you should have the following model:

 

Image may be NSFW.
Clik here to view.
image009.png

Save it (CTRL/S). You can switch to the CDS text editor tab to see the same mode in text form:

 

  Image may be NSFW.
Clik here to view.
image010.png

 

We created a data-model with two associated entities. Next: rebuild it (see part 2 for details). You will notice in the console that only this file is incrementally built, since the other files didn't change.

 

 

Using the HANA Run Time Tools

 

Open the RTT in your browser. To review the tables we just created, you may first need to bind to the HANA database container in which they were created:

 

Image may be NSFW.
Clik here to view.
image011.png

Press the "Search HDI Containers" icon, and bind to the appropriate tinyworld workspace container (called something like <your user name>…tinyworld-hdi-container). Now, open the "Catalog > workspace… > Tables", and you will see the two tables that we just created, respectively called "tinyworld.tinydb::tinyf.world" and"tinyworld.tinydb::tinyf.country". You can now open the SQL console (right click on your container and select Open SQL Console) , and enter some data, for instance:

 

INSERT INTO "tinyworld.tinydb::tinyf.world" VALUES ('Europe');

INSERT INTO "tinyworld.tinydb::tinyf.world" VALUES ('Asia');

INSERT INTO "tinyworld.tinydb::tinyf.country" VALUES ('Spain', 'Europe');

INSERT INTO "tinyworld.tinydb::tinyf.country" VALUES ('Japan', 'Asia');

INSERT INTO "tinyworld.tinydb::tinyf.country" VALUES ('Denmark', 'Europe');

(Run it by pressing Image may be NSFW.
Clik here to view.
image012.png
in the toolbar). You can check it out, for instance like this:

 

SELECT * FROM "tinyworld.tinydb::tinyf.country" WHERE "partof.continent" = 'Europe'

 

 

 

Adding a Calculation View to the model

 

In this step, we use the SAP HANA modeler to graphically add a Calculation View to show only European countries.

 

Navigate to the src/ subfolder of the tinydb/ module folder, right-click "> New > Calculation View". Call it, for instance myview, select “Data Category” as “Dimension” from the dropdown and click "CREATE". Wait a few seconds, until you see:

  Image may be NSFW.
Clik here to view.
image013.png

 

From the toolbar, click the Image may be NSFW.
Clik here to view.
image014.png
(Create Projection) icon once, and then (without holding the mouse button) move your mouse to an empty space below the existing projection on the canvas and click again, to create a new projection, called Projection_1. Select it, and "drag" the little arrow that appears on the right to the bottom of Projection, to connect them:

Image may be NSFW.
Clik here to view.
image015.png

Now, let's create the projection in order to show the results only for European countries. Select the Projection_1 node. On the "mapping" tab on the right, click the "+"; a search wizard will appear. Enter tiny to search for the tables that we created in part 2. Select tinyworld.tinydb::tinyf.country in the search results, and click "Ok". We first want to connect the "Data Sources" to the "Output Columns": select the table and click the Image may be NSFW.
Clik here to view.
image016.png
(Add to Output) icon:

 

   Image may be NSFW.
Clik here to view.
image017.png

 

 

Next, click on the "FILTER EXPRESSION" tab, open the "Columns" element, and then double-click partof_continent. In the Operators selector click once on "=". The expression appears at the top; complete it by typing 'Europe':

 

Image may be NSFW.
Clik here to view.
image018.png

 

 

Next, select the Projection node on the left, and in its MAPPING tab, select and drag name from "Data Sources" to "Output Columns" with your mouse.

 

Finally, to support anonymous users, select the "Semantics" node at the top of the graph, select the "VIEW PROPERTIES" tab, and change Apply Privileges from "SQL Analytical Privileges" to empty.

 

Save the calculation view (CTRL/S), and rebuild the tinydb module again. This accomplishes our task: we created a view that shows only the name of only European countries.

 

 

Using OData

 

One of the most common usage patterns is to expose a data model via the OData protocol (see: www.odata.org). This is very easy to do with the Web IDE, by means of adding a single file to our small Node.js module.

 

In the folder tree (navigation pane), right-click the tinyjs/lib/ folder, create a "New > File" and call it euro.xsodata. Note that the suffix is important – it determines how the file will be treated in the HANA database. In the editor, type:

service {

  "tinyworld.tinydb::myview" as "euro" keys generate local "ID";

}

 

Then save the file. We just defined a new OData service named euro.xsodata, and defined an entity euro, based on the myview Calculation View (using the name of the HANA table, which is prepended by the namespace). The euro entity uses an auto-generated key called ID.

 

Before we can run the OData Service, we need to create dependency from the Node.js module that exposes the OData service, and the underlying HDB module, on which it depends.

 

Open the mta.yaml MTA descriptor, and look for the tinyjs module. You will see something like this:

  Image may be NSFW.
Clik here to view.
image019.png

 

Append the following text to the attributes of the tinyjs module:

 

# ------- dependency on DB

  requires:

    - name: tinydb

    - name: hdi-container

#---------------- exposes SERVICE URL to consumers

  provides:

    - name: tinyjs_api

      properties:

        service_url: ${default-url}

# ----


NOTE: The YAML syntax is indentation-sensitive and does not allow usage of tabs. Make sure that you use spaces only.

 

Next, open the file tinyjs/server.js, and uncomment the line that establishes the connection to the HANA database. It should look like this:

 

// configure HANA

options = xsjs.extend(options, xsenv.getServices({ hana: {tag: "hana"} }));

 

Save all files, and run the Node.js module again (right-click tinyjs/ ">Run > Run as Node.js Application").

 

Testing the OData service

 

Since we didn't change the code of index.xsjs yet, you will see the same "It's a tiny JS World!" message again, but now we also have an OData service, which we can actually test using an OData URL:

 

In the browser tab, where the hello-world message is showing, replace the URL suffix /index.xsjs with

 

/euro.xsodata/euro?$format=json

 

If all works as expected, you will see the output (based on the manual entries we made above), as follows:

Image may be NSFW.
Clik here to view.
image020.png

 

 

Using the OData service with SAP UI5

 

The above URL test tells us that the OData service is up and running. Let’s now write a small UI5 application that uses the same OData service programmatically.

 

Double-click to again open the existing tinyui/resources/index.html file, replace its content with the following UI5 code, and save:

 

<!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>

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

  var oTable = new sap.ui.table.Table({ title: "European Countries" });

  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>

 

What does this app do? We define a model (oModel), bound to /euro.xsodata. Then, we create a table with a single column, bound to the name field of the entity /euro. The table is initialized and displayed in an HTML context.

 

We need to one additional requirement in order to run a UI5 application on XS Advanced, and that is to set up a destination for the XS Advanced "approuter", which handles cross-references to other URLs. Here we have a cross-reference to the URL of the euro.xsodata OData service of the tinyjs module. Here are the two steps:

 

  1. In the mta.yaml MTA descriptor, find the tinyui module section and append the following:

# -- requires tinyjs service URL

  requires:

    - name: tinyjs_api

      group: destinations

      properties:

        name: tinyjs_be

        url:  ~{service_url}

    2. Open the file tinyui/xs-app.json (you can right-click "Beautify" it in the editor) and add the following entry to the "routes" array (inside the square brackets):

 

{"source": "^/euro.xsodata/.*$", "destination": "tinyjs_be"}

 

We now defined a dependency between the tinyui and tinyjs modules, and specified a destination route to the OData service. Save both files and runtinyui/ again from the toolbar or by right-clicking the folder tinyui/ "> Run > Run as > Web Application".

 

After a while, the following table will appear in another tab of your browser:

Image may be NSFW.
Clik here to view.
image021.png

 

Summary of part 3

 

We learned how to use the Web IDE and its HANA-specific tools to build a HANA-based client-server application, with a UI module that access the database via OData. In the next two parts of this tutorial (Add SAP HANA business logic and Add business logic with Node.js) we will add some business logic to our application.

 

Other parts of this TinyWorld tutorial:

 

Part 1:   A TinyWorld Tutorial - Introduction


The basic totorial

Part 2:   Get started with the SAP Web IDE for SAP HANA

Part 3:   Create a SAP HANA based client-server application

Part 4:   Add SAP HANA business logic

Part 5:   Add business logic with Node.js


Advanced topics

Part 6:   Create Node.js unit tests

Part 7:   Under the hood

Part 8:   Source control

Part 9:   Application life cycle

Part 10:Add authentication

Part 11:Add authorization

 

 



Developing with XS Advanced: Add SAP HANA business logic


TinyWorld - Part 4


 

Add SAP HANA business logic

 

Image may be NSFW.
Clik here to view.
image001.png

 

Hello again!


In part 3 of the TinyWorld tutorial (Create a SAP HANA based client-server application) we established the baseline of our application. Now, we take our first steps of filling it in with some meaningful code, starting with native SAP HANA code (also called stored procedures).


The Web IDE supports the development of SAP HANA stored procedures in the form of .hdbprocedure and .hdbfunction files. The language used by SAP HANA is called SQLScript.

 

 

Adding a stored procedure

To illustrate the use of stored procedures, we will create a new .hdbprocedure file to insert a new country to the database, but only if the country does not already exist, and the continent is valid.

 

Right-click the tinydb/src/ folder, and create a "New > Procedure". Call it createCountry.  Add the following text to the file, and save it.

PROCEDURE "tinyworld.tinydb::createCountry" (

  IN im_country NVARCHAR(100), im_continent NVARCHAR(100),

  OUT ex_error NVARCHAR(100))

  LANGUAGE SQLSCRIPT SQL

  SECURITY INVOKER AS

  --READS SQL DATA AS

BEGIN

 

declare noc integer;

select count(*) into noc

  from "tinyworld.tinydb::tinyf.world"

  where "continent" = im_continent;

 

if :noc = 0 then

  ex_error := 'ERROR: Continent ' || :im_continent || ' does not exist!';

else

  select count(*) into noc

     from "tinyworld.tinydb::tinyf.country"

     where "name" = im_country;

  if :noc > 0 then

     ex_error := 'ERROR: Country ' || :im_country || ' already exists!';

  else

     insert into "tinyworld.tinydb::tinyf.country"

           values (im_country, im_continent);

  end if;

end if;

 

END;

 

Now, build the tinydb module again. After it is successfully built switch to another browser tab or window to load the RTT, where we will unit test and debug our procedure.

 

 

Unit testing the stored procedure

 

In the RTT, you can find the new deployed procedure under the HDI container used by the tinydb module. It should be located under "Catalog > <your user name>... > Procedures". If you cannot find it check that the build was successful, and refresh the tree with the context menu “Refresh”.

 

When you select the procedure, a viewer opens on the definition. Right-click "> Invoke Procedure with UI". Enter Spain for IM_COUNTRY and Europe for IM_CONTINENT in the wizard. Then, run the procedure by pressing in the toolbar. Try also with some non-existing continent.

 

 

Debugging the stored procedure

 

Before we can debug the procedure, we must activate the debugger by connecting it to the corresponding HDI container. Open the debug settings from the toolbar:

Image may be NSFW.
Clik here to view.
image022.png

 

 

Select your HDI container in the "Service Name" field, and press the "Toggle Connection" button.

 

Image may be NSFW.
Clik here to view.
image023.png

 

 

Click "Apply" and then close the dialog.

 

Once we have the debugger connected to the right service, we can add breakpoints in the code by clicking on the left of the desired line number.

 

Run the application again, as we did before using the context menu "Invoke Procedure with UI".

 

  Image may be NSFW.
Clik here to view.
image024.png

 

And you can debug your code now, by examining the call stack, the values of parameters and other values. You can follow execution step by step with the "Step over" button, or resume execution until the next breakpoint with the “Resume” button.

 

Note: debugging of hdbfunctions is not supported yet.

 


Summary of part 4

We added native SAP HANA procedures to our TinyWorld application. In the next part of this TinyWorld application (Add business logic with Node.js), we will use Node.js to add more business logic to our application.


Other parts of this TinyWorld tutorial:

 

Part 1:Introduction to the TinyWorld application


The basic totorial

Part 2:   Get started with the SAP Web IDE for SAP HANA

Part 3:   Create a SAP HANA based client-server application

Part 4:   Add SAP HANA business logic

Part 5:   Add business logic with Node.js


Advanced topics

Part 6:   Create Node.js unit tests

Part 7:   Under the hood

Part 8:   Source control

Part 9:   Application life cycle

Part 10:Add authentication

Part 11:Add authorization

Developing with XS Advanced: Add business logic with Node.js


TinyWorld - Part 5


Add business logic with Node.js

 

Image may be NSFW.
Clik here to view.
image001.png

 

Hello again!


The Web IDE supports the development of Node.js server side applications, as well as Node.js applications that use the "xsjs" compatibility layer – a Node.js extension library that supports most of the functionality of the XS Classic JavaScript language.

 

XSJS support is accomplished by including several SAP-provided Node.js modules, and the easiest way to do this is by checking the "XSJS" checkbox when creating a new Node.js module in your project, which is what we did in part 2 (Get started with the SAP Web IDE for SAP HANA) of this tutorial.

 

 

 

Adding a Node.js application

 

In part 3 (Create a SAP HANA based client-server application), we used OData to read from the database. While OData supports write/modify/delete actions to tables, most applications use application logic to validate the input values first. One way to do this, is to write a Node.js module that receives inputs over a REST interface, and writes the (validated) data into the database, as follows.

 

Right-click the tinyjs/lib/ folder, and create a "> New > Folder". Call it country. Right-click country "> New > File", and call it country.xsjs.  Add the following text to the file, and save it.

 

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 result.EX_ERROR;}

else { return output; }

}

 

var country = {

  name: $.request.parameters.get("name"),

  partof: $.request.parameters.get("continent")

};

// validate the inputs here!

 

var output = saveCountry(country);

 

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

$.response.setBody(output);

 

What does the app do? It reads the values of two "GET" parameters, name and continent respectively, passes them to a function that calls the SQLScript procedure we previously created to write these values to the country table, and emits a confirmation message. The same could of course also be done via a plain SQL INSERT statement.

 

NOTE:  we intentionally misuse the HTPP GET method to access a service for creating DB entries, in order to simplify the tutorial; productive applications should always use update methods (POST, PUT, DELETE) for database modification. We will address this issue in part 9 (Application life cycle) of the tutorial.

 

Now, run the tinyjs/ module again. This module now provides two entry points. Since we didn't change the index.xsjs app, it will again show the hello message, as we saw in in part 2 (Get started with the SAP Web IDE for SAP HANA). But now we also have a new service, which we can access by appending the following text to the <host><port> part of the URL (in other words, replace /index.xsjs):

 

/country/country.xsjs?name=China&continent=Asia

/country/country.xsjs?name=Albania&continent=Europe

/country/country.xsjs?name=Sweden&continent=Europe

You will see the confirmation that the values were written, in JSON format, e.g.

Image may be NSFW.
Clik here to view.
image025.png

 

Using the Node.js debugger

 

Right-click tinyjs/ "> Run > Run Configurations …", and click the "+" to add a new Node.js application configuration. Name it debug mode, and check the Debug "Enabled" checkbox:

 

 

Image may be NSFW.
Clik here to view.
image026.png

 

At this point, you should be able to click "Save and Run", to rerun the application in debug mode.

 

To open (and close) the debugger control pane, click the debug tool on the right toolbar:

 

Image may be NSFW.
Clik here to view.
image027.png

 

Now set a breakpoint on line 21, where saveCountry is about to be called: click on the left of the line number:

  Image may be NSFW.
Clik here to view.
image028.png

 

We can now test our code, by switching to another browser tab, and just like before, append the following to the <host><port> of the URL:

/country/country.xsjs?name=Andora&continent=Europe

 

You may briefly see a "tinyworld/tinyjs is suspended" popup, indicating that the app is now suspended on the breakpoint we just set. That is as it should be.

 

Switching back to the Web IDE, you can see the debugger stopped on line 21:

Image may be NSFW.
Clik here to view.
image030.png

 

 

And you can debug your code now, by examining the call stack, the values of parameters and other values. For instance, click on the "Step into" button:

  Image may be NSFW.
Clik here to view.
image031.png

 

And a few times on the "Step over" button:

  Image may be NSFW.
Clik here to view.
image032.png

 

To see the values of the local variables in saveCountry:

 

Image may be NSFW.
Clik here to view.
image033.png

 

Click the "Resume" button to complete execution. NOTE that if you take a long time during debugging, the calling browser may have timed out, and will not wait for the response text, but the operation will still have completed.

 

Summary of part 5

 

In part 5 of this tutorial we learned how to use Node.js and its XSJS compatibility layer to build SAP HANA-based business logic a, complementing the in-database capabilities, provided by calculation views, SQLScript procedures and more.

 

We completed the basic tutorial. Congratulations!

 

We are now ready 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. As before, we strongly recommend that you follow the advanced topics of this tutorial in the following order:

 

Part 6:   Create Node.js unit tests

Part 7:   Under the hood

Part 8:   Source control

Part 9:   Application life cycle

Part 10:Add authentication

Part 11:Add authorization


Wishing you success!


Developing with XS Advanced: Create Node.js unit tests


TinyWorld - Part 6

Create Node.js unit tests

 

Image may be NSFW.
Clik here to view.
image001.png

 

Welcome back!


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). This is the first of our "advanced" topic blogs.

 

SAP HANA XS Classic supported a Jasmine-like unit test pattern called XSUnit. In this part of the tutorial, we will see how to use XSUnit to develop unit tests for our Node.js module.

 

You may have noticed that when we created a new Node.js module with XSJS support in the Web IDE, the template also created a test/ folder with an initial unit-test file called sampleTest.xsjslib.

 

Create a new Node.js Test Run Configuration for your tinyjs module via "Run > Run Configurations… ", call it for instance test, leave the default test file pattern, and click “Save and Run”.

 

Image may be NSFW.
Clik here to view.
image034.png
 

 

This will run your Node.js module in XSJS test mode and find the previously edited sampleTest.xsjslib file because it matches the test file pattern. The Node.js Test Execution pane will appear on the right of the Web IDE and display a result like below. Obviously, that test is not doing much yet (toggle Show Code Coverage:

 

Image may be NSFW.
Clik here to view.
image035.png

Now replace the function it("not ok"…) with something meaningful, like expecting some calculator to correctly add up one and one:

 

it("add simple", function() {

   $.import("calc", "calculator");

   var calc = $.calc.calculator;

   var sum = calc.add(1, 1);

   expect(sum).toBe(2);

});

 

This will of course not run because the function add from calc/calculator.xsjslib is not yet defined. So let’s create that file and fill it with the following contents:

 

function add(a, b) {

   return a+b;

}

 

 

The next test run should look much better. As you can see by the green background in calculator.xsjslib, the newly added business logic was indeed covered by our test:

Image may be NSFW.
Clik here to view.
image036.png

 

You can keep adding new tests as additional it functions or new test suites by adding new describe functions in the same or other *Test.xsjslib files in the predefined test/ folder.

 

Summary of part 6

Here we learned how to use the "Jasmine" framework to add tests to Node.js modules.

 

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:

 

Part 7:   Under the hood

Part 8:   Source control

Part 9:   Application life cycle

Part 10:Add authentication

Part 11:Add authorization

Developing with XS Advanced: Under the hood

TinyWorld - Part 7

Under the hood

 

Image may be NSFW.
Clik here to view.
image001.png

 

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 MTA project

 

The following illustration shows the structure of the fully expanded TinyWorld project (a few hidden "system files" are intentionally not shown):

  

Image may be NSFW.
Clik here to view.
image037.png

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)
type: nodejs

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
type: html5

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

 

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:

Image may be NSFW.
Clik here to view.
image038.png

 

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:

 

Image may be NSFW.
Clik here to view.
image039.png

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.

 


Dependencies

 

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 logicaldependencies 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 variabletinyjs_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 propertytinyjs_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 tinyjsmodule.

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!

 

 

Matching CDS conventions

 

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]

 

 

Summary of part 7

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


Developing with XS Advanced: Source control



TinyWorld - Part 8

Source Control

 

Image may be NSFW.
Clik here to view.
image001.png

 

Welcome back!


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.


Source control is used to manage multiple versions of your application, and is also the most common way to collaborate with other team developers on the same project. Improved source control was one of the most common requirements from SAP HANA developers in the past.

 

The SAP Web IDE for SAP ANA integrates with Git, the most popular source control system today, via a graphical user interface. With this interface, you can perform all the common Git operations (clone, commit, etc.).

 

To collaborate with other team members, you can use a corporate Git server or a public repository service, like GitHub. In fact, this tutorial will use a GitHub repository to demonstrate the use of source control.

 

Note: The current release of the Web IDE does not yet support the creation and initialization of a Git repository directly from the Web IDE. The instructions here therefore perform a small detour. In a future release you will be able to perform actions that correspond to "git init" and "git remote add" Git commands, directly from the Web IDE.

 

This blog assumes that you have performed the steps in the "Basic TinyWorld tutorial". If not, go back to the Introduction to the TinyWorld application for more information.

 

 

Create a repository

 

Start by navigating to https://github.com. There, create a new Git repository, call it tinyworld, and remember its URL. Make sure the new repository has at least one commit. On GitHub you can achieve it by selecting the "Initialize this repository with a README" option in the repository creation page:

 

   Image may be NSFW.
Clik here to view.
image040.png

Then, from the Web IDE, download and save your project code as a zip file to your workstation, as follows:  right click on the tinyworld project folder " > Export":

  Image may be NSFW.
Clik here to view.
image041.png

 

 

Once safely exported, right click, and delete the entire project folder in the Web IDE. Not to worry: we are going to recreate it by "cloning" it from the Git repository we just created. From the top menu, click "File > Git > Clone Repository". The wizard requires the repository URL and the authentication of the Github repository we just created.

Image may be NSFW.
Clik here to view.
image042.png
 

 

This operation results in a new tinyworld project folder, but of course it is empty. So next, right-click on the new tinyworld folder and "> Import -> From File System".  In the dialog box browse for the project zip file you exported and saved before. Make sure that the "Import to" field contains only the top most folder (/tinyworld), and click OK.

 

Image may be NSFW.
Clik here to view.
image043.png
 

 

 

Then click OK in the Import Form and then OK again to confirm the overriding of existing files. After the import operation is completed, you will see your tinyworld project in your workspace again:

Image may be NSFW.
Clik here to view.
image044.png
 

 

Note the "decoration" icons displayed next to each file/folder. These provide their Git status. For instance, a green dot indicates a committed file. A red asterisk marks a modified file that has not yet been staged. See the reference manual for more detail.

 

You can also see the Git status project in the Git pane on the right of your window:

 

Image may be NSFW.
Clik here to view.
image045.png

 

To complete the process we will push the changes to the remote repository on Github. For that:

 

  • Select the "Stage All" checkbox in the Git pane

 

  • Add a "Commit Description"

 

  • Click on "Commit and Push"

Image may be NSFW.
Clik here to view.
image046.png
 


Note: Never discard the special system files and always include the changes in these files in your commits.

 

Now your team members can also clone the project to their Web IDE and you can share your work by pushing and fetching the changes from the Git repository. You can activate the relevant Git commands either from context menu (right click on project folder "> Git") or from the Git pane:

 

Image may be NSFW.
Clik here to view.
image047.png

 

Summary of part 8

This part of the TinyWorld tutorial described how to share your code with other members of your team, using the Git source control solution. More information on Git can be found in the Web IDE developer documentation, as well as on the Internet.

 

You can continue to explore additional advanced parts of this TinyWorld tutorial, covering things like adding authentication and authorization control to our application, and how to manage the life cycle of our application, from development to deployment:

 

 

Part 9:   Application life cycle

Part 10:Add authentication

Part 11:Add authorization

HANA Schema User and Role Security

Welcome again to my series of blogs on Users/ Roles / Security. In this blog, I am going to showcase how to create users and roles

(read only and read & write) and how to assign these roles to a user.

 

Firstwe need to have a SCHEMA where we can assign these roles to certain users. The owner of the schema or someone with owner privileges of the schema should be able to accomplish this task.


I started by going to the documentation and ran the statement below a few times (this works but there is an easier and more manageable way to accomplish the task) please go to Secondly for a better way



GRANT [DELETE|UPDATE|INSERT] ON SCHEMA MYSCHEMA TO SOMEUSER WITH GRANT OPTION;



Secondly, we will need to create the roles and assign   a) read access to the schema  and   b) read/write access to the schema.


This is the READ ONLY Role

 

Image may be NSFW.
Clik here to view.
1.jpg

 


This is the READ/WRITE Role

 

Image may be NSFW.
Clik here to view.
2.jpg

 

 

Thirdly, we need to create the users (if not existent) and assign such roles to their Granted Roles tab

Image may be NSFW.
Clik here to view.
3.jpg

 

 

Finally, we will test these scenarios for the READ ONLY User

 

Image may be NSFW.
Clik here to view.
4.jpg

 

 

 

 

 

 

and now the same tests with the Read/Write user (and role)

 

 

Image may be NSFW.
Clik here to view.
5.jpg

 

Image may be NSFW.
Clik here to view.
6.jpg

 

and verify that it works ( Rows affected: 1)

 

 

 

 

 

Thank you again for reading this blog. This is all for my user security blog.

 

Please share your experiences and/or questions.

Developing with XS Advanced: Application life cycle


TinyWorld - Part 9

Application life cycle

 

Image may be NSFW.
Clik here to view.
image001.png

 

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-linetool, 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.

Image may be NSFW.
Clik here to view.
image038.png

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.

 

Image may be NSFW.
Clik here to view.
image049.png

 

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").

 

  Image may be NSFW.
Clik here to view.
image050.png

 

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)andpaste 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 ofthetinyworld 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.

 

Image may be NSFW.
Clik here to view.
image051.png

 

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


Image may be NSFW.
Clik here to view.
image053.png

 


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 thexs appscommand, you will see that the memory configurations were applied:

  Image may be NSFW.
Clik here to view.
image054.png

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



Developing with XS Advanced: Add authentication


TinyWorld - Part 10

Add authentication

 

Image may be NSFW.
Clik here to view.
image001.png

 

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 "authentication", the process of verifying the user's identity.

 

Up till now we have allowed anonymous access for our TinyWorld application. We now introduce authentication to our application. Authentication forces users to log on and identify themselves, before they can use the application.

 

Authentication and authorization (discussed in the next part of this tutorial, Add authorization) are managed using the XS Advanced UAA service. XS UAA is an OAuth authorization service with support for HANA and SAML2 authentication. For more details refer to the SAP HANA Developer Guide for HANA XS Advanced.

 

To enable authentication we need to do four things:

 

  1. Enable authentication for tinyjs
  2. Enable authentication for tinyui
  3. Add CSRF support to tinyui
  4. Provision the UAA service, to be used by both modules.

 

1. Enable authentication for the tinyjs module


Open the file tinyjs/server.js and uncomment the following line which was commented out by default.

 

options = xsjs.extend(options, xsenv.getServices({ uaa: {tag: "xsuaa"} }));

 

        Then, comment the following line to disable anonymous access (or change true to false)

 

var options = xsjs.extend({

//   anonymous: true, // remove to authenticate calls

   redirectUrl: "/index.xsjs"

});

Note: Once authentication is switched on for tinyjs, no direct access to it at runtime will be possible anymore. The reason is that the Node.js application will require a valid JWT token (JSON Web Token) in every request. Such token is acquired by the approuter (as part of our tinyui) when the user logs on, but it is not returned to the browser. Hence every request must always be routed via the approuter which forwards the JWT token to Node.js.

 

Following part 2 of this tutorial, an appropriate route is already defined in the xs-app.json file, so no additional handling is required.

 

2. Enable authentication for the HTML5 module


Configure the tinyui module to use authentication: open tinyui/xs-app.json, and change the "authenticationMethod" attribute to "route" (with quotes), like this

"authenticationMethod": "route",

 

As a result the authentication method will be defined in the route itself. By default this is xsuaa, which is the right value for us. Authentication method xsuaa means that the UAA service will handle the authentication (the user is redirected to the UAA's login form).

 

 

3. Add CSRF support


Once we switch on the authentication for the HTML5 module, the XS Advanced runtime will require any HTTP update request (PUT, POST, DELETE) to present a valid CSRF token. This is a standard security technique to prevent cross-site forgery. The following code will fetch the CSRF token when the application is first loaded and add it automatically to the HTTP header of each update request. Append the following code to the end of the tinyui/resources/Util.js file that we created in the previous part , part 9, of this tutorial (Application life cycle).

 

$(function() {

  // one time fetch of CSRF token

  $.ajax({

    type: "GET",

    url: "/",

    headers: {"X-Csrf-Token": "Fetch"},

    success: function(res, status, xhr) {

      var sHeaderCsrfToken = "X-Csrf-Token";

      var sCsrfToken = xhr.getResponseHeader(sHeaderCsrfToken);

      // for POST, PUT, and DELETE requests, add the CSRF token to the header

      $(document).ajaxSend(function(event, jqxhr, settings) {

        if (settings.type==="POST" || settings.type==="PUT" || settings.type==="DELETE") {

          jqxhr.setRequestHeader(sHeaderCsrfToken, sCsrfToken);

        }

      });

    }

  });

});



4. Provision the UAA service


In order to bind our application modules to the UAA service at run time, we first need to define a new UAA service. Add the following section to the resources section of the mta.yaml file:

 

- name: tiny_uaa

  type: com.sap.xs.uaa


Next, we define the dependency of the tinyjs and tinyui modules to this resource. When these modules are run they will be automatically bound to the tiny_uaa service. Add the following line to the requires section of both modules in the mta.yaml file:

 

- name: tiny_uaa                     

 

In addition we want the authentication token acquired at runtime by the tinyui module to be automatically forwarded to the tinyjs module, so a seamless flow is achieved. Add forwardAuthToken: true to the destinations property of the tinyui module in the mta.yaml file, like this:

 

- name: tinyui

  type: html5

  path: ./tinyui

  requires:

  - name: tiny_uaa

  - name: tinyjs_api

    group: destinations         

    properties:

       name: tinyjs_be

       url: ~{service_url}

       forwardAuthToken: true

 

 

To provision the UAA service, you currently need to manually execute the following XS Advanced command:

 

xs create-service xsuaa devuser tiny_uaa

 

Note: (in the future this step will be automatically performed by the Web IDE, based on the information in the mta.yaml file).

 

The changes to enable authentication are now completed. In order for the changes to take effect, rerun the tinyjs module and then the tinyui module. To test authentication, open the TinyWorld application using a different browser or using an incognito session (so the token you acquired as a user of the Web IDE will not be reused). You will be redirected to the XS login page, requesting username and password.

 

Summary of part 10

This part of the TinyWorld tutorial described how you can add authentication to your application. And what about authorization? That is the topic of the next part in our tutorial:

 


Part 11:Add authorization

Developing with XS Advanced: Add authorization

TinyWorld - Part 11

Add authorization

 

Image may be NSFW.
Clik here to view.
image001.png

 

Hello again!


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).


Our next challenge (and yes, this is not an easy task...) is to enhance the application with authorization checking code.

 

We will introduce two categories of users: those that can only view the country information, and those that are authorized to add new countries.

 

The XS Advanced security concept is based on scopes.


Scopes are functional authorization units in the context of an application, e.g. the permission to create a new country could be encapsulated by a scope called CreateCountry. Scopes can be assigned to roles which in turn can be assigned to users. Application can also define a role-template which simplifies the process of creating new roles for administrators.

 

Enabling authorization includes the following steps:

 

  1. Define scopes and role-templates in xs-security.json
  2. Recreate the UAA service with xs-security.json
  3. Add authorization checks to the application tinyui and tinyjs
  4. Create roles, role collections from templates and assign them to users

 

1. Create the xs-security.json file

 

The xs-security.json file is a configuration file that defines the scopes used by the application and role-templates that consolidate the scopes into functional roles.

Below is a simple sample xs-security.json for our TinyWorld application. It defines one scope to only view data, and another to also create data, and corresponding role-templates: tinyworldView and tinyworldCreate.

 

{

"xsappname": "tinyworld",

"scopes": [ { "name": "$XSAPPNAME.view", "description": "View data" },

              { "name": "$XSAPPNAME.create", "description": "Create data"}

            ],

 

"role-templates": [ { "name": "tinyworldView",

"description": "Role for viewing data",

"scope-references": [ "$XSAPPNAME.view" ] },

                      { "name": "tinyworldCreate",

                        "description": "Role for creating data",

"scope-references": [ "$XSAPPNAME.create","$XSAPPNAME.view" ] }

                    ]

}

Create an xs-security.json file in the root folder of your project, copy past the above sample and save.

 

We must also update the tiny_uaa resource, defined in the mta.yaml file, to use the the xs-security.json file.


To do that, add the lines marked in yellow below to the tiny_uaa definition in the mta.yaml file.

 

- name: tiny_uaa                         

  type: com.sap.xs.uaa

  parameters:

    path: ./xs-security.json

 

NOTE: since the Web IDE does not provision the UAA service automatically yet, the importance of maintaining this additional entry in the mta.yaml file is for the sake of completeness and to enable packaging and deployment of the application using the XS deploy command at a later stage. 


 

2. Provision the UAA service with xs-security.json


Next we need to update our tiny_uaa service with the new authorization configuration defined in the xs-security.json file. To do that you first need to download the xs-security.json file from your project in Web IDE to a folder accessible from your command line tool. Then, we will delete the service (which we provisioned in part 10 of this tutorial (Add authentication) for testing authentication) and recreate it with the new security definitions.

 

Run the following xs commands:

 

xs delete-service tiny_uaa

xs create-service xsuaa devuser tiny_uaa -c ./xs-security.json     

 

Note: In the future, this situation will be automatically detected by the tools, and you will not need to do this manually.


Note: deleting the service will unbind it from all applications. As a result our TinyWorld application now became unusable, which we will soon fix.

 

Note: when creating the UAA service we used the service plan devuser. This service plan is specially designed to be used at development time. It enables multiple developers to create UAA service instances with the same application name in their xs-security.json file.

 

XS Advanced requires application names to be unique. To resolve this, the UAA service broker adds a suffix to the application name to make every application unique per user e.g. tinyworld!u1 (however a user cannot use the same application name more than once).


This allows multiple developer to work on the same application in isolated environments without worrying about naming conflicts. 

 

 

3. Add authorization checks to the application

 

To enable authorization in App Router based applications (such as tinyui), we need to specify the scope a user must be assigned to in order to access resources of specific route. The assignment of scopes to routes is done in the xs-app.json file, located under the tinyui/ folder.

 

In order to impose authorization check on any request to our application, we need to add additional general route (which is the default behavior hence we didn’t need it up till now), and assign the right scope to it.

 

Add the following to xs-app.json, (note– the order of the entries in the route list is important, make sure you enter them in the order described below)

 

  1. To the /euro.xsodata/ route add  "scope": " $ XS Advanced PPNAME.view"
    (this will enforce the authorization check even if the OData service is accessed directly without the UI)
  2. To the xsjs route add "scope": "$ XS Advanced PPNAME.create"
  3. Add a new general route with the scope assignment

 

{

  "source": "^/(.*)$",

  "localDir" : "resources",

  "scope" : "$XSAPPNAME.view"

}

 

Following the above changes your xs-app.json file should look like this (marked in yellow are the new lines)

{

"welcomeFile": "index.html",

"authenticationMethod": "route",

"routes": [{

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

       "destination": "tinyjs_be",

       "authenticationType": "xsuaa",

       "scope": "$XSAPPNAME.view"

}, {

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

       "destination": "tinyjs_be",

       "scope": "$XSAPPNAME.create"    

}, {

       "source": "^/(.*)$",

       "localDir" : "resources",

       "scope" : "$XSAPPNAME.view"

   }]

}

From now on, users must be granted with the scope tinyworld.view to view the content of the TinyWorld application.

 

For the changes to take effect, stop and rerun thetinyjsandtinyuimodules. Once you rerun the modules, the application will become inaccessible since your user is not assigned to the required role collection yet. Role assignment will be done in the next step.

 

4. Create roles

 

Next you need to create actual roles from the role-template using the Application Role Builder, which is part of the XS Advanced Administration tools.

To use XS Advanced Administration tools you must be assigned with the appropriate authorizations. For now (SPS11) we will use the HANA Web-based Development Workbench, as follows:

 

Login to the HANA Web-based Development Workbench using user with appropriate privileges. The tool can be found in the following URL: http://<host>:<80><HANA instance>/sap/hana/ide/security  (see the note belowfor more information about required authorizations).

 

Double click the needed user and navigate to the Application Role Collection tab, add the role collection XS_AUTHORIZATION_ADMIN and save.

 

Image may be NSFW.
Clik here to view.
image055.png

Next you need to create actual roles from the role-template using the Application Role Builder, which is part of the XS Advanced Administration tools. The actual URL is installation dependent; to find out the URL, you can run the following command:

xs app xsa-admin

 

Use the URL to open the XS Advanced Administration tools in your browser:

Image may be NSFW.
Clik here to view.
image056.png
 

 

Click on Application Role Builder. On the left pane click the tinyworld application (the application name corresponds to the XS Advanced ppname attribute in the xs-security.json file).

 

You can see that default role instances were already created from the two role-templates with the same names. We use these convenient defaults in this tutorial.

 

Role instances themselves cannot be assigned to user, only role collections. Role collections are aggregations of roles needed to perform a specific task (by humans). In order to separate the View authorizations from the Create authorizations we need to create two different collections.

 

To create the role collections, navigate to the Role Collection maintenance screen by clicking the navigation button on the top-left corner of the screen.

 

Image may be NSFW.
Clik here to view.
image058.png

 

In the left pane there is a list of existing role collections. Press the small plus button at the bottom of the screen to add a new collection.

 

  • Enter name TinyViewRC
  • Press the + (Add Application Role) to add roles to the collection. A popup is displayed
    • Select application name – tinyworld
    • Select Template Name – tinyworldView
    • Select Application Role – tinyworldView

 

Press OK and then save the collection.

 

Repeat these steps to create an additional role collection TinyCreateRC. Select the corresponding template and role for Create.

 

 

Assign role collections to application user


The last authorization step is to assign the role collections to application users so end users will be able to use tinyworld. To do that we will use the Security application of HANA Web-based Development Workbench.

 

Expand the "Users" node and double click the user you would like to assign the roles to. Click on the "Application Role Collections" tab, add the TinyViewRC collection and Save.

 

Image may be NSFW.
Clik here to view.
image061.png

 

Congratulations, the authorization check is now in place. To test your recent changes you must login again to your application (which will create a new security token containing the new scopes assigned to your user). Since there is no logout option in our simple application you have to restart your browser, or open a new incognito session.

 

NOTE: The following authorizations are needed in order to assign role collections.

 

  1. First, in order to grant roles and/or use the security application of HANA Web-based Development Workbench, you must have the SAP HANA role sap.hana.xs.ide.roles::SecurityAdmin. It can be granted using HANA Studio or using SQL.

  2. To be able to assign role collection to users, you must be granted with useradmin and role admin privileges. These privileges can be assigned using HANA Web-based Development Workbench itself, using the "System Privileges" tab:

  Image may be NSFW.
Clik here to view.
image062.png

Or by running the following SQL commands

 

grant user admin to <user name>

grant role admin to <user name>

 
 

 

Summary of part 11

This part of the TinyWorld tutorial described how you can add authorization to your application. Currently, this is the last part of our TinyWorld tutorial. I hoped you enjoyed this series. Please keep checking back for more information about developing for SAP HANA and XS Advanced with the SAP Web IDE.

Combine all the HANA goodies in a showcase – the HCP trial landscape is the perfect platform for this

Part 2: Refine processing of tweets with text Analysis and Fuzzy Search, clustering and building web services and setting HANA Cloud Connector


Here I am with the second part of the blog. As we look at the first part of the blog we have done some basic installations, created a Tweets table, set up the tunnel to HANA Database and crawled the tweets. In this part of the blog we will perform text analysis, use fuzzy search, clustering (from Predictive Analysis Library / PAL), build web services using HANA native development, setup authorizations, SAP HANA Cloud Connector and Configurations.

 

Besides the possibility to persist data in both row and column stores, SAP HANA also provides numerous libraries to query or manipulate data such as predictive analysis, text mining, geospatial and graph functionality and so on. I will be using geospatial in part 3.


Performing Text Analysis


Mapping Business Needs to Text Analysis

Image may be NSFW.
Clik here to view.
text analysis.jpg

SAP HANA Text Analysis has market-leading, out-of-the-box predefined entity types that are packaged as part of the platform. Looking at a sentence, clause, paragraph, or document, the technology can identify the "who", "what", "where", "when" and "how much" and classify it accordingly.

 

To know more about Text analysis please click here.


Let’s focus on performing some sentiment analysis using HANA. To create a text index on tweets execute the following code in the SQL editor in eclipse:


-- CREATE TEXT ANALYSIS INDEX ON TWEETS


CREATE FULLTEXT INDEX "tweets" ON "Tweets"("text")

            CONFIGURATION 'EXTRACTION_CORE_VOICEOFCUSTOMER'

            LANGUAGE COLUMN "lang"

            LANGUAGE DETECTION ('EN','FR','DE','ES','ZH')

            TEXT ANALYSIS ON

            ;


Now $TA_tweets index is created under your schema (NEO_xxxxx) in tables folder, right click on $TA_tweets index and open data preview to see some important columns like TA_RULE, TA_TOKEN, TA_TYPE. In this index we got the ability to identify the strong positive, weak positive, strong negative and weak negative sentiments.


Image may be NSFW.
Clik here to view.
sentiment.PNG

Similarly let us create a tweeters view with influence and stance scores by executing the SQL script “setupView.sql” file in the SQL window in eclipse from downloaded SmartApp->scripts->setupView.sql folder (in part 1). Refresh on the views list of schema to see the “tweeters” view. Right click on it, then “open data preview” to see the influence and stance of people.

 

To get more insights on Predictive Analysis Library (PAL) please see the documentation.


Fuzzy Search


It is a type of search that will find matches even when users misspell words or enter in only partial words for the search.

Let us see how it works – execute the following sql statements in the sql editor in eclipse by replacing NEO_XXX with your schema and in the place of ‘SAP’ give your product or company name that you wish to search.


SELECT SCORE() AS score, * FROM NEO_XXXXX."$TA_tweets"

                  WHERE

                      CONTAINS(TA_TOKEN, 'SAP', FUZZY(0.5))

             

                  ORDERBY score DESC;


The output of fuzzy search contains many related entries. Based on the fuzzy search factor (which is 0.5 in this case), it will also consider the similar words. In this case "SAPNL", "sapnl" "SAPAG"etc.


Image may be NSFW.
Clik here to view.
fuzzy search.PNG


Clustering


To perform clustering go to the scripts folder in the downloaded SmartApp, then copy the predictive.sql to sql window in eclipse.

We need to do some changes in the code i.e. replace “NEO_” with your schema name “NEO_XXXXXX”. Execute “create stored procedure” by selecting the code snippet in the sql window to create the tweeters cluster procedure. Refresh the catalog now and you will find another new schema which is _SYS_AFL -> Procedures -> NEO_XXXX_TWEETERS_CLUSTER.


Then, first create parameters tables, output table and then views for ODATA by selecting the code snippet in the sql console respectively.


Similarly to do clustering we have to run the consecutive “runtime” code.


Execute the following statements individually to see the results like user, clusterNumber, distance, stance and influence etc.


SELECT * FROM "Tweets";

SELECT * FROM "$TA_tweets";

SELECT * FROM PAL_RESULTS;

SELECT * FROM PAL_CENTERS;

SELECT * FROM "TweetersClustered";

SELECT * FROM "Clusters";


Click on Views under your schema (NEO_xxxx), then select and right click on Tweeters clustered view and open data preview and have a look on analysis as shown below:

Image may be NSFW.
Clik here to view.
clustered.PNG

TweetersClustered view with the Raw data


Image may be NSFW.
Clik here to view.
cluster graph.PNG

TweetersClustered view with the Analysis


Build web services


Let us navigate to HCP (HANA Cloud Platform) cockpit, initially we created a HANA instance called as “dev”. Click on the Development tools link in HANA XS Applications, it will authenticate you and then it opens the HANA Web-based Development Workbench. Here we can develop our projects for a web service that will appear on the web.

 

To know more about HANA web based development work bench please click here .


In HANA web based development work bench let us create an application by right clicking on dev (content->pxxxxtrial->dev) and in the popup select template as ‘Empty application’ and in package enter “pxxxxtrial.dev.SmartApp”, then click on create. Now we can see the SmartApp project with xsaccess, xsapp, index.html files.


Image may be NSFW.
Clik here to view.
workbench.PNG


Setup authorizations for the application


Delete the index.html file that was created by default during application creation. Open the downloaded SmartApp->services-> user.hdbrole, xsprivileges files and globally replace on neo_ and pxxx with your schema name (NEO_xxxx) and pnumber (pxxxx) then save. Drag and drop the user.hdbrole and xsprivileges files to the Multi-file Drop zone in development workbench. We will get an error message because we got other stuff to do before the application can be finished. Refresh the project in order to see the files in the development workbench and click on save.


Similarly open the xsaccess file from downloaded SmartApp->services and globally replace on ‘neo_’ and ‘pxxx’ with your schema name(NEO_xxxx) and pnumber(pxxxx) respectively. Remove the comment line in the file, then drag and drop to the Multi-file Drop zone in development workbench and refresh the application, then save it.


We need to execute the following statement in SQL editor in eclipse in order to authorize the user by replacing pxxx with your p-number. 

 

CALL HCP.HCP_GRANT_ROLE_TO_USER('pxxxtrial.dev.smartapp::user','pxxx');

 

Setup access to tables and views via the OData protocol: to do that open services.xsodata file from downloaded SmartApp->services and globally replace on ‘NE0_’ with your schemaname (NEO_xxxx) then save it drag and drop the services.xsodata file to the Multi-file Drop zone in the development workbench and refresh the application. Then, activate the OData file.


Image may be NSFW.
Clik here to view.
xsodata.PNG

Now will set up server side processing using JavaScript (XSJS).


Open services.xsjs file from downloaded SmartApp->services. Globally replace on ‘neo_’ and ‘pxxx’ with your schemaname (NEO_xxxx) and p-number (pxxxx) respectively. Drag and drop the services.xsjs file to the Multi-file Drop zone in development workbench and refresh the application. Then save it.


Note: If you want to know about debugging the application please click here .


Authentication setup proxy


The Destination that does the basic authentication, hence the proxy will handle authentications and access to the Hana trial instance. Then sends the results back to the UI.


Note: This proxy will be used only for the trial developer version but is not necessary to run in production environment since the backend system can be accessed directly.


Now find the tool for the proxy that is hanatrial-auth-proxy (written in node.js). Firstly, let me thank Mr.Gregor Wolf for this amazing tool for HCP trial version. Please click here for the tool. Shift+Right click on the downloaded folder, open in the command window. Install the node.js modules using command “npm install”.


Image may be NSFW.
Clik here to view.
npm install.PNG

In the hanatrial-auth-proxy ->examples->config.js we need to replace the host where our application runs (For example, s11hanaxs.hanatrial.ondemand.com). Save it and go back to the command prompt, now use the command "node examples/server-basic-auth.js", then we will find HANA Cloud Trial Authentication Proxy for HANA XS Services ready.


Image may be NSFW.
Clik here to view.
auth-proxy.PNG

Open a new window in your browser (I am using chrome), type ‘localhost:7891/pxxxxtrial/dev/SmartApp/services.xsodata/$metadata’  hit enter and you will be prompted to login, use your pnumber (pxxxx) as username and put in the password that you use to login to the HCP cockpit, then click on enter.  You will be authenticated to your SAP HANA instance using several tools, and now we get the results back. So, effectively we are able to access using the local webserver i.e proxy.

 

Image may be NSFW.
Clik here to view.
xsodata results.PNG

 

Setup SAP HANA Cloud Connector


Install Hana cloud connector https://tools.hana.ondemand.com/#cloud either developer or productive version. If you want to know more about the installation process go to the documentation. On windows, double click on the downloaded msi file, it may ask for Microsoft Visual Studio to install - click yes and download it and run from Microsoft. Then install the msi file while installing let the port be default (8443).


After installation to start and stop the server go to the start menu in windows, you will notice that some new links have appeared for the cloud connector. Open the browser, go to https://localhost:8443. If the page below is showing up the reason is that the certificate hasn’t actually been signed yet, so just click on ‘Proceed to localhost’.


Image may be NSFW.
Clik here to view.
cloud connector.PNG

For login we have a default username as “Administrator” and password as “manage” that will get you signed in for the first time. Later you need to change the password. Choose Master (Primary installation) and next change the password.


Now set up the initial configuration as follows

Image may be NSFW.
Clik here to view.
setup.PNG

If you are working behind a firewall then you need to provide Proxy settings, otherwise this is not necessary. Click on apply, then it is directed to the administration console where we can see that the HANA cloud connector is connected but no active resources are available. So, we need to set resources.


Go to access control and click on Add..(Add System Mapping) and insert the details as shown below:


Image may be NSFW.
Clik here to view.
system-mapping1.PNG

Select the protocol for communication as HTTP:

Image may be NSFW.
Clik here to view.
system-mapping2.PNG

Give internal host and internal port as shown below:

Image may be NSFW.
Clik here to view.
mapping 3.PNG

Give the virtual name as hanaxs.virtual and virtual port as 7891.

Image may be NSFW.
Clik here to view.
mapping4.PNG

Make sure the check-box is marked to check availability of internal host and hit on finish.

Image may be NSFW.
Clik here to view.
mapping5.PNG

Now we can see that a mapping has been created for us: just click on it.


Add a resource by clicking on “Add…” in Resources Accessible on your local host. Give your pnumbertrial (pxxxtrial) as url path and Access Policy as ‘Path and all sub-paths’. Save it and notice that the url path must be checked and its state is green.


We have a node application that is running on localhost on port 8888, to make this available from the web and HTML5 app we need to configure it in the HANA cloud connector.


Go to "Access control" on the left side of the page and click on ‘Add..’(Add System Mapping) and insert the details as shown below:


Select Back-end Type as Non-SAP System:


Image may be NSFW.
Clik here to view.
mapping-nodejs1.PNG

Select protocol for communication as HTTP:

Image may be NSFW.
Clik here to view.
system-mapping2.PNG


Add internalhost and internal port as shown below:

Image may be NSFW.
Clik here to view.
mapping-nodejs2.PNG

 

Add Virtual Host and Virtual Port as shown below:

Image may be NSFW.
Clik here to view.
mapping-nodejs3.PNG

 

Make sure the check-box is marked to check availability of internal host and hit on finish.

Image may be NSFW.
Clik here to view.
mapping-nodejs4.PNG


Mapping is created, just click on it and Add Resource by adding “do” as url path (because it’s the high level resource for this application) and Access Policy as ‘Path and all sub-paths’, then Save it. Now we have in total two mappings.


Then we need to define the Destinations that will talk and reference to the mappings in the cloud connector.  So go to the downloaded SmartApp folder-> destinations->hanaxs, then replace the user with your username (pxxxx) and save it.


Go to the SAP HANA Cloud Platform Cockpit, select destinations and click on Import from file then select downloaded SmartApp folder-> destinations->hanaxs and we can see the settings have been taken from the file which seems to be as follows


Image may be NSFW.
Clik here to view.
Capture6.PNG


Replace the user with your pnumber(pxxxx), enter the password and save. Now we can see the destination has been configured.


Similarly for nodejs application select import from file then select SmartApp folder-> destinations->nodejs and we can see the settings have be taken from the file which seems to be as follows

Image may be NSFW.
Clik here to view.
Capture7.PNG


Just save it, no changes is required. So, now in total two destinations are defined.


Thanks for reading. Hope you enjoyed the blog Image may be NSFW.
Clik here to view.

 

 

Next Steps

In the next part of blog we will move ahead to build some attractive web-based UI (User Interface) using SAP UI5 and will perform some customizations using analytic tools.


HANA Row level security

Welcome back and thank you for reading this blog. this is a continuation of the user security series.

 

on my previous blog, I explained how to set up the user security for read only as well as for read and write on a user. In this blog, I will explain how analytic privileges (AP) work to showcase the row level security.

 

Notice that APs can only be applied to views and not to tables

 

In order to complete this exercise, we will need:

  1. One table (to expose via a view) , and another table to control the security
  2. A calculation view (so we can apply the AP - row level security)
  3. a stored procedure (to retrieve the relationship of a user against the data)
  4. an AP (to specify the view(s) and also the conditions we need to filter the view rows by)
  5. The user we created before on blog 1 (so we can apply the AP to)

 

My struggles during this exercise were due to the authorization roles I did not have but I worked with my admin to get some of the required roles and even also a system privilege that helped me understand this exercise better. I think this was of huge value because I was able to look at some logs and quickly look at what I needed. I also read the SAP HANA Administration Guide in order to understand the differences between Roles, Privileges (system/object/analytic and package (which I ended up not using this last one ))

 

here is what the table T1 for the exercise looks like (calc view will have the same output - see the positive test below)

 

Image may be NSFW.
Clik here to view.
1.jpg

 

here is the stored procedure for our security. This procedure reads from my Users table and uses the SESSION_USER to return the Role_ID (an integer I need to match against my T1 table above. initially, I had used CURRENT_USER which did not return the correct value so make sure you understand the difference between CURRENT_USER and SESSION_USER. also, make sure you use the SQL SECURITY DEFINER mode instead of the INVOKER mode

 


Image may be NSFW.
Clik here to view.
2.jpg

 

As mentioned before we can only apply the Analytic Privileges to a database view (in my case a calculation view)

Image may be NSFW.
Clik here to view.
3.jpg

 

When creating an AP, first select the Reference Model and find the view you need. (remember to use a view as the table's will not work on this step)

 

 

 

 

Image may be NSFW.
Clik here to view.
4.jpg

 

 

Associated Attributes Restrictions - this section is to specify which columns will contain a restriction. I selected column "ID" from my view.

 

Assign Restriction - this is where my row level security comes into play. I have selected the Repository Stored Procedure which will give me the security I need. Other options are Fixed (hardcoded value) and Catalog Procedure

 

Image may be NSFW.
Clik here to view.
5.jpg

 

 

Once you have created the stored procedure and the analytic privilege, now go to the security folder on the system tab > open the Users folder > select a user > assign Analytic Privilege to a user. moreover, the user has to have the SELECT privilege for the _SYS_BI and _SYS_BIC schemas. The user has to also have EXECUTE privileges on the REPOSITORY_REST catalog object (someone with admin privileges has to assign this)

 

Image may be NSFW.
Clik here to view.
6.jpg

 

Once the privileges are assigned to the user and also the AP is in place, the rest should be easier to do testing of the AP.

 

so on the first run of the table there were 7 records, now that the AP has been assigned, there should be less records due to the row security added to this user.

 

Image may be NSFW.
Clik here to view.
7.jpg

 

 

Now, if I run the view with the user who created it and no AP (higher access) I should be able to see more data. This is the same output as selecting from the table but as I mentioned originally, a table cannot contain analytic privileges.

Image may be NSFW.
Clik here to view.
8.jpg

 

 

My learnings here were

1) to understand the difference between the INVOKER (caller of the procedure) and the DEFINER ( owner of the db object)

2) Understand the different privileges as the apply to SYSTEM / Objects / Packages, etc. and

3) the Analytic Privilege step on how the view, its columns, and the stored procedure all work together (very neatly).

 

 

Thank you again for reading this blog and please share your experiences or questions. In case you are wondering on what is next ?? I will be taking a deeper step on the data security on my next blog - stay tuned!

SAP HANA SPS 11: New Developer Features; SAP Web IDE for SAP HANA

This blog is part of the larger series on all new developer features in SAP HANA SPS 11: SAP HANA SPS 11: New Developer Features

 

We are happy to announce that the final piece of the new developer experience in SAP HANA SPS 11 has shipped: SAP Web IDE for SAP HANA is now available for download from the Service Marketplace and installation onto your HANA SPS 11 systems. SAP Web IDE for SAP HANA provides a comprehensive web-based end-to-end development experience for creating SAP HANA native applications:

  • Development of SAP HANA content and models
  • UI development with SAPUI5
  • Node.js or XSJS business code
  • Git integration

Therefore it provides a complete workflow for all of your new HANA Deployment Infrastructure (HDI) and XS advanced model (XSA) based development.

 

SAP Web IDE for SAP HANA comprises capabilities of SAP HANA Studio and SAP HANA Web-based Development Workbench. It represents the long term replacement tool for both of these previous offerings. It consolidates technologies, follows industry trends, and leverages industry standards where possible, while retaining a competitive innovation focus of SAP’s current offering.

 

For more information on how to obtain and install the SAP Web IDE for SAP HANA, and for full documentation, see http://scn.sap.com/docs/DOC-71432.

 

 

We also have the TinyWorld tutorial to help you learn this new development environment:

The entire TinyWorld tutorial is structured as follows:

 

Part 1: Introduction to the TinyWorld application


The basic tutorial

Part 2:   Get started with the SAP Web IDE for SAP HANA

Part 3:   Create a SAP HANA based client-server application

Part 4:   Add SAP HANA business logic

Part 5:   Add business logic with Node.js


Advanced topics

Part 6:   Create Node.js unit tests

Part 7:   Under the hood

Part 8:   Source control

Part 9:   Application life cycle

Part 10:Add authentication

Part 11:Add authorization


Appendix: Getting the source code

 

More sections will be added over time, so keep checking back.

 

We also have several eLearning Videos that showcase the SAP Web IDE for SAP HANA. What we have done is taken the TechEd 2015 Hands-on workshop, DEV602, which was originally designed for using the HANA command line and external editors and updated it to instead use the SAP Web IDE for SAP HANA.

 

DEV602 WebIDE Ex1 - HTML5 Module Hello World

In this first exercise, we will connect to the remote system, run the new project wizard, and then create an HTML5 module to serve as the application endpoint and proxy all of our services and client-side content. At the end of this exercise you will be able to connect to your server via web browser and see a Hello World message.


DEV602 WebIDE Ex2 - Database Development

In this exercise, we will continue to develop our overall application. Applications in the HANA/XS Advanced world, are often made up of multiple modules at design time which deploy to separate micro-services or database container content. We created client side UI application content in the first exercise using the HTML5 module. In this exercise we will create database artifacts, such as database table and stored procedures, using the HDB (HANA Database) module. We will then see how we build these database artifacts using the new container-based, schema-less HDI (HANA Deployment Infrastructure) concepts.


DEV602 WebIDE Ex2.2 - Calculation View Editing

This video demonstrates the steps to create a Graphical Calculation view in the new SAP Web IDE for SAP HANA


DEV602 WebIDE Ex3 - Node.js Module; XSJS and XSODATA

For this exercise we will now build the XSJS and XSODATA services used to expose our data model to the user interface. Although XS Advanced runs on node.js, SAP has added modules to node.js to provide XSJS and XSODATA backward compatibility. Therefore you can use the same programming model and much of the same APIs from XS, classic even within this new environment.

 

DEV602 WebIDE Ex4 - HTML5 Module; SAPUI5 application

For this exercise we will build a proper SAPUI5 user interface that consumes both the XSJS and XSODATA services from our Node.js module.


DEV602 WebIDE Ex5.1 - Node.js; modules and express

In exercise 3 we created a Node.js module, but didn’t really do much Node.js specific programming.  We only were using Node.js to run XSJS and XSODATA services. The support for XSJS and XSODATA is an important feature for XS Advanced. It not only allows backward compatible support for much of your existing development; but it provides a simplified programming model as an alternative to the non-block I/O event driven programming model normally used by Node.js.

 

But we certainly aren’t limited to only the functionality provided by XSJS and XSODATA.  We have access to the full programming model of Node.js as well. In this exercise we will learn how to extend our existing Node.js module in the SAP Web IDE for SAP HANA.

 

You will learn about how to create and use reusable code in the form of node.js modules. You will use packages.json to define dependencies to these modules which make the installation of them quite easy. You will use one of the most popular modules – express; which helps with the setup the handling of the request and response object. You will use express to handle multiple HTTP handlers in the same service by using routes.


DEV602 WebIDE Ex5.2 - HANA database access from Node.js

In this video we will explore the modules and techniques for accessing the HANA database from Node.js


DEV602 WebIDE Ex5.3 - Asynchronous Non-Blocking I/O

In this exercise, you will learn about the fundaments of the asynchronous nature of Node.js. We will so see how this asynchronous capability allows for non-blocking input and output. This technique is one of the basic things that makes node.js development different from other JavaScript development and also creates one of the reasons for its growing popularity. We will see how these techniques are applied to common operations like HTTP web service calls or even SAP HANA database access.


DEV602 WebIDE Ex5.4 - Text Bundles

In this exercise we will also see how to create language translatable text strings and HANA database queries from Node.js.


DEV602 WebIDE Ex5.5 - Web Sockets

Our final exercise part in this section will demonstrate the ease at which you can tap into the powerful web sockets capabilities of node.js. We will use web sockets to build a simple chat application. Any message sent from the SAPUI5 client side application will be propagated by the server to all listening clients.

 

The source code for the above videos can be found here: https://github.com/I809764/DEV602

Viewing all 676 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>