Professional Documents
Culture Documents
XS-BASED DEVELOPMENT
DEV160
Exercises / Solutions
Thomas Jung / SAP Labs, LLC.
Yuval Morad / SAP Labs ISR
Diego Rapela / SAP SE
DEV160
Table of Contents
Getting Help .........................................................................................................................3
Source code solutions ..........................................................................................................3
Exercise 1 Setup of a Project ................................................................................................ 4
Exercise 1 Solution................................................................................................................5
Exercise 1.1: Create a connection to the HANA server ....................................................... 5
Exercise 1.2: Create group package and initial project contents ....................................... 10
Exercise 1.3: Create a Repository Workspace ................................................................... 14
Exercise 1.4: Check out the project in HANA Studio .......................................................... 15
Exercise 1.5: Grant the Developer Role ............................................................................. 17
Exercise 1.6: Creating and running a Hello World HTML page from our Project ............... 19
Exercise 2 Creating Database Objects via the Repository .................................................. 23
Exercise 2 Solution..............................................................................................................24
Exercise 2.1: Creating the hdbdd development artifact ...................................................... 24
Exercise 2.2: Defining reusable types and structures ........................................................ 27
Exercise 2.3: Defining database tables and views ............................................................. 28
Exercise 3 Services ..............................................................................................................35
Exercise 3 Solution..............................................................................................................36
Exercise 3.1: Creating a Hello World XSJS Service .......................................................... 36
Exercise 3.2: Creating an XSJS Service with custom output format .................................. 39
Exercise 3.3: Creating a Simple OData Service ................................................................. 43
Exercise 3.4: Creating an OData Service with an Entity Relationship................................ 48
Exercise 3.5: Creating an OData Service with Create Operation and XSJS Exit ............... 51
Exercise 4 User Interface ....................................................................................................55
Exercise 4 Solution..............................................................................................................56
Exercise 4.1: Consume a Basic OData Service within UI5 binding the service to a Table 56
Exercise 4.2: Use oData Metadata to dynamically create the columns.............................. 60
Exercise 4.3: Use oData Metadata with SAP Annotation OData4SAP .............................. 62
Exercise 4.4: Create a Fiori Launchpad Site ...................................................................... 65
DEV160
BEFORE YOU START
System Host: lt5081.wdf.sap.corp
System Instance Number: 10
Desktop User: student
System User ID: DEV160_<group number>. Your group number will
be given to you by the session instructor. For example if the group
number is 001, then your user id would be DEV160_001
System Password: Welcome14
Getting Help
If you need addition help resources beyond this document, we would suggest the following
content:
DEV160
Objective
In this exercise, you will learn the basics of creating a workspace and creating an XS project which
you will use for the remainder of this workshop.
Exercise Description
Create a system connection in SAP HANA Studio
Create a workspace which is linked to the HANA Server
Create a project which is linked to the workspace
Create a schema
Create access control files
Create a role
Create a HelloWorld.html file to test your setup
DEV160
EXERCISE 1 SOLUTION
Exercise 1.1: Create a connection to the HANA server
Explanation
Screenshot
DEV160
DEV160
DEV160
DEV160
DEV160
Exercise 1.2: Create group package and initial project contents
Explanation
Screenshot
10
DEV160
11
DEV160
12
DEV160
9) Check Require
Authentication.
Check Create Schema and
input a Schema named
HANA_DEV160_<Group
Number>. For this
example this would be
HANA_DEV160_000.
Also Select Create
Developer Role. Name
your Role developer.
Check Create Eclipse
Project and make the
project name
DEV160_<Group
Number>.
Check Create index.html
file.
Press Create.
13
DEV160
Exercise 1.3: Create a Repository Workspace
Explanation
Screenshot
14
DEV160
Exercise 1.4: Check out the project in HANA Studio
Explanation
Screenshot
2) Press Next
15
DEV160
16
DEV160
Exercise 1.5: Grant the Developer Role
Explanation
Screenshot
17
DEV160
18
DEV160
Exercise 1.6: Creating and running a Hello World HTML page from our Project
Explanation
Screenshot
19
DEV160
20
DEV160
21
DEV160
22
DEV160
Exercise Description
We created a schema to hold all of our database objects in Exercise 1.Next we will use the
development object (new as of SPS6) hdbdd which utilizes the CDS syntax to define reusable
types, structures, tables and views.
For example:
Create a HDBDD object
Use CDS Syntax to define types, structures and tables
23
DEV160
EXERCISE 2 SOLUTION
Exercise 2.1: Creating the hdbdd development artifact
Explanation
Screenshot
24
DEV160
25
DEV160
26
DEV160
Exercise 2.2: Defining reusable types and structures
Explanation
Screenshot
type
type
type
type
type
type
BusinessKey : String(10);
SDate : LocalDate;
CurrencyT : String(5);
AmountT : Decimal(15,2);
QuantityT : Decimal(13,3);
UnitT: String(3);
Type HistoryT
CREATEDBY
CREATEDAT
CHANGEDBY
CHANGEDAT
};
27
{
:
:
:
:
BusinessKey;
SDate;
BusinessKey;
SDate;
DEV160
Exercise 2.3: Defining database tables and views
Explanation
Screenshot
@Catalog.tableType : #COLUMN
Entity Header {
key PURCHASEORDERID: BusinessKey;
HISTORY: HistoryT;
NOTEID: BusinessKey null;
PARTNER: BusinessKey;
CURRENCY: CurrencyT;
GROSSAMOUNT: AmountT;
Note: if you dont want to
NETAMOUNT: AmountT;
type this code, we
recommend that you cut
TAXAMOUNT: AmountT;
and paste it from this web
LIFECYCLESTATUS: StatusT;
address
APPROVALSTATUS: StatusT;
http://lt5081.wdf.sap.corp:8
CONFIRMSTATUS: StatusT;
010/workshop/admin/ui/ex
erciseMaster/?workshop=d
ORDERINGSTATUS: StatusT;
ev160&sub=DB_3
INVOICINGSTATUS: StatusT;
};
@Catalog.tableType : #COLUMN
Entity Item {
key HEADER: Association [1] to Header
Note: if you dont want to
{PURCHASEORDERID};
type this code, we
recommend that you cut
key PURCHASEORDERITEM: BusinessKey;
and paste it from this web
PRODUCT: BusinessKey;
address
NOTEID: BusinessKey null;
http://lt5081.wdf.sap.corp:
CURRENCY: CurrencyT;
8010/workshop/admin/ui/e
GROSSAMOUNT: AmountT;
xerciseMaster/?workshop
=dev160&sub=DB_4
NETAMOUNT: AmountT;
TAXAMOUNT: AmountT;
QUANTITY: QuantityT;
QUANTITYUNIT: UnitT;
DELIVERYDATE: SDate;
};
28
DEV160
};
4) Here is the complete
source code for your
hdbdd file.
DELIVERYDATE as "DeliveryDate1"
namespace dev160.exercises.g<group_number>.data;
@Schema: 'HANA_DEV160_<Group_number>'
context PurchaseOrder {
type
type
type
type
type
type
type
BusinessKey : String(10);
SDate : LocalDate;
CurrencyT : String(5);
AmountT : Decimal(15,2);
QuantityT : Decimal(13,3);
UnitT: String(3);
StatusT: String(1);
Type HistoryT {
CREATEDBY : BusinessKey;
CREATEDAT : SDate;
CHANGEDBY : BusinessKey;
CHANGEDAT : SDate;
};
@Catalog.tableType : #COLUMN
Entity Header {
key PURCHASEORDERID: BusinessKey;
HISTORY: HistoryT;
NOTEID: BusinessKey null;
PARTNER: BusinessKey;
CURRENCY: CurrencyT;
GROSSAMOUNT: AmountT;
NETAMOUNT: AmountT;
TAXAMOUNT: AmountT;
LIFECYCLESTATUS: StatusT;
APPROVALSTATUS: StatusT;
CONFIRMSTATUS: StatusT;
ORDERINGSTATUS: StatusT;
INVOICINGSTATUS: StatusT;
};
@Catalog.tableType : #COLUMN
Entity Item {
key HEADER: Association [1] to Header
{PURCHASEORDERID};
key PURCHASEORDERITEM: BusinessKey;
PRODUCT: BusinessKey;
NOTEID: BusinessKey null;
CURRENCY: CurrencyT;
GROSSAMOUNT: AmountT;
29
DEV160
};
NETAMOUNT: AmountT;
TAXAMOUNT: AmountT;
QUANTITY: QuantityT;
QUANTITYUNIT: UnitT;
DELIVERYDATE: SDate;
30
DEV160
31
DEV160
32
DEV160
33
DEV160
34
DEV160
EXERCISE 3 SERVICES
Objective
XSJS or Server Side JavaScript is used to create custom services and is the main imperative and
control flow logic layer in HANA Native Applications. In this exercise we will create simple XSJS
Services, access the database and format data with XSJS services.
The XSEngine contains a special tool for the creation of OData Services without needing to perform
server side coding. To create an OData service from an existing HANA table or view, you need only
define an XSODATA service definition file.
Exercise Description
35
DEV160
EXERCISE 3 SOLUTION
Exercise 3.1: Creating a Hello World XSJS Service
Explanation
Screenshot
36
DEV160
37
DEV160
38
DEV160
Exercise 3.2: Creating an XSJS Service with custom output format
Explanation
Screenshot
$.import("sap.hana.democontent.epmNext.services",
"messages");
function downloadExcel() {
var body = '';
var MESSAGES =
$.sap.hana.democontent.epmNext.services.messages;
39
DEV160
try {
ID
MESSAGES.getMessage('SEPM_POWRK', '003') +
"\t" + // Partner ID
MESSAGES.getMessage('SEPM_POWRK', '001') +
"\t" + // Company Name
MESSAGES.getMessage('SEPM_POWRK', '004') +
"\t" + // Employee
// Responsible
MESSAGES.getMessage('SEPM_POWRK', '005') +
"\t" + // Created At
MESSAGES.getMessage('SEPM_POWRK', '006') +
"\n"; // Gross Amount
while (rs.next()) {
body += rs.getNString(1) + "\t" +
rs.getNString(2) + "\t"
+ rs.getNString(3) + "\t"
+ rs.getNString(4) + "\t"
+ rs.getDate(5) + "\t" +
rs.getDecimal(6) + "\n";
}
} catch (e) {
$.response.status =
$.net.http.INTERNAL_SERVER_ERROR;
$.response.setBody(e.message);
return;
}
$.response.setBody(body);
$.response.contentType = 'application/vnd.msexcel; charset=utf-16le';
$.response.headers.set('Content-Disposition',
40
DEV160
'attachment; filename=Excel.xls');
$.response.status = $.net.http.OK;
}
4) This block is actually the
entry point to the service
handler but must appear
after all referenced
functions. Here we can
query the request URL and
determine which action to
take. This way a single
XSJS file might have
multiple services or query
parameters. We will look
for the URL parameter
called cmd to decide which
path to take. These are
just examples, as you have
complete control over the
definition of all URL
parameters and how they
are handled by the service
41
DEV160
http://lt5081.wdf.sap.corp:8
010/dev160/exercises/g000/
services/exercise.xsjs?cmd
=Excel
42
DEV160
Exercise 3.3: Creating a Simple OData Service
Explanation
Screenshot
43
DEV160
4) We want to define an
OData service to expose
the business partner table.
The syntax of the
XSODATA service is
relative easy for this use
case. We need only define
a namespace (your
package path), the name
of the HANA Table we will
base the service from (
sap.hana.democontent.e
pmNext.data::EPM.Maste
rData.BusinessPartner)
and the name of the OData
entity (BusinessPartners).
Therefore the content of
the XSODATA file would
be.
Note: if you dont want to
type this code, we
recommend that you cut
and paste it from this web
address
http://lt5081.wdf.sap.corp:8
010/workshop/admin/ui/exe
rciseMaster/?workshop=de
v160&sub=OD_1
44
DEV160
45
DEV160
DEV160
services/businessPartners.x
sodata/BusinessPartners?$t
op=3&$skip=5
47
DEV160
Exercise 3.4: Creating an OData Service with an Entity Relationship
Explanation
Screenshot
2) Returning to HANA
Studio, you should now
create a new OData
service named
purchaseOrders.xsodat
a and extend it to
include the
sap.hana.democontent.
epmNext.data::EPM.Pu
rchase.Header and
sap.hana.democontent.
epmNext.data::EPM.Pu
rchase.Item tables.
Next create a
navigation 1:many
association.
The new content of the
definition file should
look like this:
Note: if you dont want
to type this code, we
recommend that you cut
and paste it from this
web address
http://lt5081.wdf.sap.cor
p:8010/workshop/admin
/ui/exerciseMaster/?wor
kshop=dev160&sub=O
D_2
Save and Activate the
service.
48
DEV160
49
DEV160
6) Associations can be an
excellent way to load
child elements on
demand; however there
is also an option to
expand the children
details in place so that
all levels can be
retrieved with one
request.
Test the service again
using the same steps
as in the previous
section of this exercise.
This time add
$expand=POItem to the
end of the URL.
You will then see that
all the items are
embedded within each
header record.
Full URL:
http://lt5081.wdf.sap.cor
p:8010/dev160/exercise
s/g000/services/purcha
seOrders.xsodata/POH
eader/?$format=json&$
expand=POItem
50
DEV160
Exercise 3.5: Creating an OData Service with Create Operation and XSJS Exit
Explanation
Screenshot
$.import("sap.hana.democontent.epmNext.services",
"session");
var SESSIONINFO =
$.sap.hana.democontent.epmNext.services.session;
51
DEV160
/**
@param {connection} Connection - The SQL connection
used in the OData request
@param {beforeTableName} String - The name of a
temporary table with the single entry before the
operation (UPDATE and DELETE events only)
@param {afterTableName} String -The name of a
temporary table with the single entry after the
operation (CREATE and UPDATE events only)
*/
function usersCreate(param){
let after = param.afterTableName;
//Get Input New Record Values
var pStmt =
param.connection.prepareStatement('select * from "' +
after + '"');
var User =
SESSIONINFO.recordSetToJSON(pStmt.executeQuery(),
'Details');
pStmt.close();
//Validate Email
if(!validateEmail(User.Details[0].E_MAIL)){
throw 'Invalid email for ' +
User.Details[0].FIRSTNAME +
' No Way! E-Mail must be valid and ' +
User.Details[0].E_MAIL + ' has problems';
}
//Get Next Personnel Number
pStmt =
param.connection.prepareStatement('select
"sap.hana.democontent.epmNext.data::purchaseOrderId".
NEXTVAL from dummy');
var rs = pStmt.executeQuery();
var PersNo = '';
while (rs.next()) {
PersNo = rs.getString(1);
}
pStmt.close();
Table
52
DEV160
pStmt =
param.connection.prepareStatement('insert into
SAP_HANA_EPM_NEXT."sap.hana.democontent.epmNext.data:
:EPM.User.Details" values(?,?,?,?)' );
}else{
pStmt =
param.connection.prepareStatement('TRUNCATE TABLE "'
+ after + '" ' );
pStmt.executeUpdate();
pStmt.close();
pStmt =
param.connection.prepareStatement('insert into "' +
after + '" values(?,?,?,?)' );
}
pStmt.setString(1, PersNo);
pStmt.setString(2,
User.Details[0].FIRSTNAME);
pStmt.setString(3, User.Details[0].LASTNAME);
pStmt.setString(4,
User.Details[0].E_MAIL);
pStmt.executeUpdate();
pStmt.close();
}
}
function validateEmail(email) {
var re =
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*
)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[09]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zAZ]{2,}))$/;
return re.test(email);
}
53
DEV160
54
DEV160
In this exercise the services have already been created for you. You will focus on how to consume and
interact with these services from the SAPUI5 user interface technology. We will also see how to create
a Fiori Launchpad page using the UI Integration Services framework in HANA.
Exercise Description
Consume a Basic OData Service within UI5 binding the service to a Table
Use the OData Meta Data to dynamically create the UI5 Table Columns
Uses OData Meta Data with OData4SAP annotation to create table columns with descriptions from
the backend views
Create a Fiori Launchpad Site
55
DEV160
EXERCISE 4 SOLUTION
Exercise 4.1: Consume a Basic OData Service within UI5 binding the service to a Table
Explanation
Screenshot
56
DEV160
57
DEV160
___________________________
http://lt5081.wdf.sap.corp:8
010/workshop/admin/ui/exer
ciseMaster/?workshop=dev
160&sub=OUI_2
___________________________
http://lt5081.wdf.sap.corp:8
010/workshop/admin/ui/exer
ciseMaster/?workshop=dev
160&sub=OUI_3
58
DEV160
59
DEV160
Exercise 4.2: Use oData Metadata to dynamically create the columns.
Explanation
Screenshot
60
DEV160
61
DEV160
Exercise 4.3: Use oData Metadata with SAP Annotation OData4SAP
Explanation
Screenshot
62
DEV160
63
DEV160
64
DEV160
Exercise 4.4: Create a Fiori Launchpad Site
Explanation
Screenshot
65
DEV160
66
DEV160
67
DEV160
68
DEV160
69
DEV160
70
DEV160
71
DEV160
72
DEV160
73