SAP HANA NATIVE DEVELOPMENT – 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 |
2
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:
• The Online Help at http://help.sap.com/hana/SAP_HANA_Developer_Guide_en.pdf
• The integrated help within SAP HANA Studio (content identical to the above mentioned online help)
• SAPUI5 SDK (installed on your HANA Server)
http://lt5081.wdf.sap.corp:8010/sap/ui5/1/sdk/index.html#content/Overview.html
Source code solutions
All source code solutions and templates for all exercises in this document can be found in the following webpage.
http://lt5081.wdf.sap.corp:8010/workshop/admin/ui/exerciseMaster/?workshop=dev160
In some cases it might be a little easier to copy and paste the coding instead of typing it all manually. If copying/pasting, I would suggest that you make sure to understand what is being copied/pasted before moving on.
Open the browser and enter the following URL to access the solutions web page. You can access the source code for each exercise by clicking on the appropriate exercise in the navigation bar.
http://lt5081.wdf.sap.corp:8010/workshop/admin/ui/exerciseMaster/?workshop=dev160
Please Note: you will need your username and password to access this site.
3
DEV160
EXERCISE 1 – SETUP OF A PROJECT
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
4
DEV160
EXERCISE 1 – SOLUTION
Exercise 1.1: Create a connection to the HANA server
5
DEV160
|
3) |
Expand “General”, and choose “Web Browser”. Then click “Search”. |
|
|
4) |
Expand C: and select “Program Files(x86). Click “Ok”. |
|
6
DEV160
|
5) |
Select “Chrome” from the |
|
|
list, and click “Apply”, then |
||
|
“Ok”. |
||
|
6) |
Make sure you are in the SAP HANA Development |
|
|
perspective by clicking on the button. |
||
|
. |
||
|
7) |
Click on the “Systems” view. Right click in the white space below this tab and choose “Add |
|
|
System…”. |
7
DEV160
8
DEV160
9
DEV160
Exercise 1.2: Create group package and initial project contents
|
Explanation |
Screenshot |
|
|
1) |
We also have some browser based tools and wizards that can be used along with the HANA Studio to speed up development. We will use the HANA Application Lifecycle Management tool to setup our initial project structure. Open Google Chrome from the Desktop |
|
|
2) |
Input URL for your HANA system |
|
|
http://lt5081.wdf.sap.corp:8 |
||
|
010 |
||
|
Then the path to the HANA Lifecycle Management tool (/sap/hana/xs/lm/). |
||
|
The full URL for this system is: |
||
|
http://lt5081.wdf.sap.corp:8 |
||
|
010/sap/hana/xs/lm/ |
||
|
3) |
Input the same user name and password you used to logon to the HANA System via the Studio |
|
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. |
||
|
10) You should receive a series of messages that access objects, a schema, an Eclipse project and a role have all been created. |
|
|
|
PLEASE NOTE: You will not see these objects which were just created in the package hierarchy. The HALM tool only displays packages, not their content. You will see this content in subsequent steps. |
||
|
You now have the start of a basic project, including a Schema and the local developer role with access to it all. |
||
13
DEV160
Exercise 1.3: Create a Repository Workspace
|
Explanation |
Screenshot |
|
|
We can now return to the SAP HANA Studio. |
We can now return to the SAP HANA Studio. |
|
|
1) |
Switch to the “SAP HANA Repositories” view. Click the icon for “Create Repository Workspace”. |
|
|
2) |
Select the system entry you created previously. Keep all other fields at their default values and choose Finish |
|
|
3) |
You should now see the new workspace in the SAP HANA Repositories view. |
|
|
PLEASE NOTE: Your User ID will be different than those displayed in subsequent screen shots. |
||
14
DEV160
Exercise 1.4: Check out the project in HANA Studio
15
DEV160
16
DEV160
Exercise 1.5: Grant the Developer Role
|
Explanation |
Screenshot |
|||
|
1) |
The application creation wizard also created a local developer role which will give your user access to create objects in this new schema. We need only grant this role to your user. Open the SQL Console by right mouse clicking on the SAP HANA System Library node in your project and choosing SQL Console |
|
||
|
2) |
You will need to call a SQLScript Procedure to perform the grant. This procedure will run as SYS_REPO and therefore can grant the role to your user (note: Access to |
|
||
|
execute this procedure should be extremely limited since it gives anyone who |
||||
|
has it great power). |
The |
|||
|
Procedure you need to call |
||||
|
is GRANT_ACTIVATED_ROL E which has two input parameters – ROLENAME create in the wizard and your USERNAME. |
||||
|
Note: if you don’t 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/exer |
||||
|
ciseMaster/?workshop=dev |
||||
|
160&sub=ST_3 |
||||
|
Press the green execute button. |
||||
17
DEV160
18
DEV160
Exercise 1.6: Creating and running a Hello World HTML page from our Project
|
Explanation |
Screenshot |
|
|
1) |
Finally we want to add a simple hello world html file to our application in order to test the security and setup of our project. We could do this manually from the HANA Studio project or use the index.html created by the wizard, but this also an opportunity to try out the Browser Based IDE – the SAP HANA Web-based Development Workbench. |
|
|
2) |
Input URL for your HANA system |
|
|
http://lt5081.wdf.sap.corp:8 |
||
|
010 |
||
|
Then the path to the HANA Web Workbench (/sap/hana/xs/ide/editor/). |
||
|
Complete URL would be: |
||
|
http://lt5081.wdf.sap.corp:8 |
||
|
010/sap/hana/xs/ide/editor/ |
||
|
3) |
Input the same user name and password you used to logon to the HANA System via the Studio if prompted for authentication. |
|
|
If you had not closed your web browser from the previous work, then the authentication would still be active in the browser. |
||
19
DEV160
|
4) |
The Web Workbench has the same repository tree as we have access to in the HANA Studio. The difference here is that we don’t check out projects, but instead directly edit and save objects. Commit and Activate are both performed upon save. |
|
|
5) |
The Web Workbench also has some project wizards. Right mouse click on your group folder and choose Create Application |
|
|
6) |
In the Create Application from Template dialog, input a new folder named HelloWorld. |
|
|
Choose the template HANA UI5 Hello World. |
||
|
Then press Create. |
20
DEV160
|
7) |
Your group folder now contains a sub-folder named HelloWorld with a basic html example. |
|
8) |
Select the index.html file and then press the Run button in order to test it. |
|
9) |
The index.html file should open in a new browser window. |
|
This simple test tells us that your project, role and access control files are all setup properly. |
21
DEV160
10) If you return to the HANA Studio and your Project in the Project Explorer; you can right mouse click and choose Team ->Check Out
11) All the content created in the Web Workbench is now copied into our local project. This allows you to move between either development environments as you work.
12) You have completed the exercise!
You are now able to:
Create a connection to the HANA server in 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
22
DEV160
EXERCISE 2 – CREATING DATABASE OBJECTS VIA THE REPOSITORY
Objective
In the past, database objects could only be created via SQL directly in the database catalog. However this meant they couldn’t be transported via delivery units like all other repository objects. As part of HANA Native Development, we now have tools to create database objects via a repository representation which generates the catalog objects upon activation.
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
24
DEV160
|
2) |
In the New wizard, expand the SAP HANA folder, expand the “Database Development” folder and choose DDL Source File. Then press Next. |
|
|
3) |
Verify that the data folder is selected. Type the filename PurchaseOrder. The file extension hdbdd will be added automatically for you. Finally, press Finish. |
|
25
DEV160
|
4) |
The hdbdd file is opened in the editor with the correct namespace and context already entered for you. |
|
|
5) |
Next we need to tell the HDBDD file which schema all objects should be created within. Correct the @Schema line after the namespace but before the context and supply the name of the Schema you created in the previous exercise: |
|
|
HANA_DEV160_<Group |
||
|
Number>. For this example this would be |
||
|
HANA_DEV160_000. |
26
DEV160
Exercise 2.2: Defining reusable types and structures
|
Explanation |
Screenshot |
|
|
1) |
First we need to define some reusable elemental types. These will later be used to define the data type of individual columns in our tables. |
type BusinessKey : String (10); type SDate : LocalDate ; type CurrencyT : String(5); type AmountT : Decimal(15,2); type QuantityT : Decimal(13,3); type UnitT: String (3); type StatusT: String(1); |
|
Within the PurchaseOrder context, create element types for BusinessKey, SDate, CurrencyT, AmountT, QuantityT, UnitT, and StatusT. Note: if you don’t 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/ex |
||
|
erciseMaster/?workshop=d |
||
|
ev160&sub=DB_1 |
||
|
2) |
We can also create reusable structures with multiple fields. This is useful when the same sets of fields are repeated in multiple tables. Create a reusable structure for History – with CREATEDBY, CREATEDAT, CHANGEDBY, and CHANGEDAT fields. Note: if you don’t want to type this code, we recommend that you cut and paste it from this web address |
Type HistoryT { CREATEDBY : BusinessKey ; CREATEDAT : SDate ; CHANGEDBY : BusinessKey ; CHANGEDAT : SDate ; |
|
}; |
||
|
http://lt5081.wdf.sap.corp: |
||
|
8010/workshop/admin/ui/e |
||
|
xerciseMaster/?workshop |
||
|
=dev160&sub=DB_2 |
||
27
DEV160
Exercise 2.3: Defining database tables and views
|
Explanation |
Screenshot |
|
|
1) |
The syntax for creating Entities is similar to types. Entities will become database tables when activating the hdbdd file. Create a purchase order entity with these fields and types: |
@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; |
|
Note: if you don’t 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/ex |
||
|
erciseMaster/?workshop=d |
||
|
ev160&sub=DB_3 |
||
|
}; |
||
|
2) |
Repeat this process for the Item Entity. |
@Catalog.tableType : #COLUMN Entity Item { key HEADER: Association [1] to Header {PURCHASEORDERID}; key PURCHASEORDERITEM: BusinessKey ; PRODUCT: BusinessKey ; NOTEID: BusinessKey null; CURRENCY: CurrencyT ; GROSSAMOUNT: AmountT ; NETAMOUNT: AmountT; TAXAMOUNT: AmountT; QUANTITY: QuantityT; QUANTITYUNIT: UnitT ; DELIVERYDATE: SDate ; }; |
|
Note: if you don’t want to type this code, we recommend that you cut and paste it from this web address |
||
|
http://lt5081.wdf.sap.corp: |
||
|
8010/workshop/admin/ui/e |
||
|
xerciseMaster/?workshop |
||
|
=dev160&sub=DB_4 |
||
|
3) |
Next, add a view for the Item table. |
define view ItemView as SELECT from Item { HEADER.PURCHASEORDERID as "PurchaseOrderItemId", PURCHASEORDERITEM as "ItemPos", PRODUCT as "ProductID", CURRENCY as "CurrencyCode", GROSSAMOUNT as "Amount", NETAMOUNT as "NetAmount", TAXAMOUNT as "TaxAmount", QUANTITY as "Quantity", QUANTITYUNIT as "QuantityUnit", |
|
Note: if you don’t 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/ex |
||
|
erciseMaster/?workshop=d |
||
|
ev160&sub=DB_5 |
||
28
DEV160
DELIVERYDATE as "DeliveryDate1"
};
4)
Here is the complete source code for your hdbdd file.
namespace dev160.exercises.g<group_number>.data;
@Schema: 'HANA_DEV160_<Group_number>' context PurchaseOrder {
type BusinessKey : String (10); type SDate : LocalDate ; type CurrencyT : String(5); type AmountT : Decimal(15,2); type QuantityT : Decimal(13,3); type UnitT: String (3); type 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 ;
};
define view ItemView as SELECT from Item { HEADER.PURCHASEORDERID as "PurchaseOrderItemId", PURCHASEORDERITEM as "ItemPos", PRODUCT as "ProductID", CURRENCY as "CurrencyCode", GROSSAMOUNT as "Amount", NETAMOUNT as "NetAmount", TAXAMOUNT as "TaxAmount", QUANTITY as "Quantity", QUANTITYUNIT as "QuantityUnit", DELIVERYDATE as "DeliveryDate1"
};
};
5)
Save and activate your hdbdd file.
30
DEV160
31
DEV160
32
DEV160
|
10) The tables in this page will then display the newly inserted data in your header and item tables. |
|
|
11) You can return to the HANA Studio and browse the data from there as well by choosing Open Data Preview |
|
|
12) The same data from the web application is now displayed in the data preview tool of HANA Studio. |
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
• Create a Hello World XSJS Service
• Create an XSJS Service with database access and custom output format
• Create a Basic OData Service
• Create an OData Service with relationships
• Create an OData Service with Create/Update/Delete operations and XSJS exits
35
DEV160
EXERCISE 3 – SOLUTION
Exercise 3.1: Creating a Hello World XSJS Service
36
DEV160
37
DEV160
38
DEV160
Exercise 3.2: Creating an XSJS Service with custom output format
|
Explanation |
Screenshot |
|
|
1) |
Now we want to extend the concepts of the XSJS service from the first half of this exercise. We’ve already seen how we can use our own custom logic in an XSJS service. Next we want to see how we can use a custom output format. We will also see how we can perform SQL to use data from the database, but manipulate or format that returned data. The final result will be a service which reads the Business Partner data but returns it in a tab delimited format ready to open in Microsoft Excel. Using the same steps as before use the file wizard to create another xsjs service named exercise.xsjs. |
|
|
Note: if you don’t 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/exer |
||
|
ciseMaster/?workshop=dev |
||
|
160&sub=XSJS_2 |
||
|
We will explain it block by block in a moment. |
||
|
2) |
First we’ve added an import to a reusable library. We can create such libraries and share them between projects and services. This particular library helps lookup reusable language independent texts from the database. We will use it to fill in the column headers of our Excel export |
$.import("sap.hana.democontent.epmNext.services", |
|
"messages"); |
||
|
var MESSAGES = $.sap.hana.democontent.epmNext.services.messages; |
||
|
3) |
We add a new function to handle the data retrieval from the Business Partner Table and formatting into |
function downloadExcel() { var body = ''; |
39
DEV160
|
Text Tab Delimited. The XSJS server side logic contains various built-in APIs (referenced via the $ object). Here you see the usage of the trace object and the db (database) objects. We build the SQL Query and pass it to the database using syntax very similar to JDBC or ODBC. In reality, the XS engine communicates directly with the HANA Index server to retrieve this data Next you see that we can build a custom formatted string in order to get the text, tab-delimited output we want. Finally we can also set any response headers, which is necessary to control the Content-Disposition so the output acts like a file download from the browser. |
try { |
||
|
var query = 'SELECT TOP 25000 "PurchaseOrderId", "PartnerId", "CompanyName", "CreatedByLoginName", "CreatedAt", "GrossAmount" ' + 'FROM "sap.hana.democontent.epmNext.data::EPM.Purchase.Head erView" order by "PurchaseOrderId"'; $.trace.debug(query); var conn = $.db.getConnection(); var pstmt = conn.prepareStatement(query); var rs = pstmt.executeQuery(); |
|||
|
body = MESSAGES.getMessage('SEPM_POWRK', '002') + "\t" + // Purchase |
|||
|
// Order |
|||
|
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.ms- excel; 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 |
var aCmd = $.request.parameters.get('cmd'); switch (aCmd) { case "Excel": |
|
downloadExcel(); |
||
|
break; |
||
|
default: |
||
|
$.response.status = $.net.http.INTERNAL_SERVER_ERROR; $.response.setBody(MESSAGES.getMessage('SEPM_AD MIN', '002', aCmd)); |
||
|
} |
||
|
5) |
Save and Activate your service. |
|
|
6) |
Test the application in your browser using the Run As option as previously. |
|
|
When the application first launches you will receive an error because you didn’t give it the cmd parameter. Add ?cmd=Excel to the end of the URL. |
||
|
For example if your group number was 000 then the URL would be: |
||
41
DEV160
42
DEV160
Exercise 3.3: Creating a Simple OData Service
|
Explanation |
Screenshot |
||
|
1) |
Right mouse click on the services folder and choose New->Other. |
|
|
|
2) |
In the New wizard, expand the SAP HANA and then Application Development folders. Choose XS OData File and then press Next. |
|
|
43
DEV160
44
DEV160
|
5) |
Save and activate the file. |
|
|
6) |
Now run the service from Chrome. In the Studio, select the file and choose Run As ->XS Service. |
|
|
The service will open in your default browser (if not Chrome, you can cut and paste the URL and then reload in Chrome). |
||
|
Use your database user and password to authenticate for the service. |
||
|
7) |
The resulting document describes the service entities. We only had the one entity named BusinessPartners. |
|
45
DEV160
|
8) |
You can now adjust the URL slightly and add the /$metadata parameter to the end of it. |
|
|
For Example: |
||
|
http://lt5081.wdf.sap.corp:8 |
||
|
010 |
||
|
/dev160/exercises/g000/ser |
||
|
vices/businessPartners.xso |
||
|
data/$metadata |
||
|
You can see the field descriptions for all the attributes of the OData service. |
||
|
9) |
In order to view the data of the entity, you would append BusinessPartners to the end of the URL: |
|
|
For Example: |
||
|
http://lt5081.wdf.sap.corp:8 |
||
|
010/dev160/exercises/g000/ |
||
|
services/businessPartners.x |
||
|
sodata/BusinessPartners |
||
|
You are now able to see the data from the businessPartner table. |
||
|
10) You can also experiment with standard OData URL parameters like $top, $skip, or $filter. These options are interpreted and handled by the OData service of the XSEngine for you. You get complex service handling without any coding. For example the following URL would return only three business partner records and would skip the first five records. Such parameters are helpful when implementing server side scrolling, filtering, or sorting in table UI elements. |
|
|
|
For Example: |
||
|
http://lt5081.wdf.sap.corp:8 |
||
|
010/dev160/exercises/g000/ |
||
46
DEV160
|
services/businessPartners.x sodata/BusinessPartners?$t |
|
op=3&$skip=5 |
|
11) The direct test of the OData service within a browser is fine for development testing; but this is hardly how end users will interact with the service. The OData service is normally called from within a web page. We have a test web page which can dynamically call your service. It can be accessed at the URL: |
|
http://lt5081.wdf.sap.corp:8 |
|
010/dev160/solutions/ui/oda |
|
taTest.html |
|
The first tab lets you test this simple service. The other tabs will be used to test later parts of this exercise. Fill your Service Path and Entity name and press Execute Service to test your service. |
47
DEV160
Exercise 3.4: Creating an OData Service with an Entity Relationship
|
Explanation |
Screenshot |
||
|
1) |
The first example of this exercise was very simplistic because it only exposed one database table as a single entity. Often you need to also represent relationships between multiple entities. For example we might want to build an OData service which has both the Purchase Order Header and Items. For this we would build a 1:many relationship between the two entities. |
||
|
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 don’t 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
|
3) |
Test using the same steps as in the previous section of this exercise. |
|
|
For example if your group number was 000 then the URL would be: |
||
|
http://lt5081.wdf.sap.cor |
||
|
p:8010/dev160/exercise |
||
|
s/g000/services/purcha |
||
|
seOrders.xsodata |
||
|
Notice that the base service definition now has two entities |
||
|
4) |
The Header data now has a hyperlink relationship to the item entity |
|
|
5) |
Once again you can return to the test web page which can dynamically call your service. It can be accessed at the URL: |
|
|
http://lt5081.wdf.sap.cor |
||
|
p:8010/dev160/solution |
||
|
s/ui/odataTest.html |
||
|
The second tab (Multi- Entity Read) lets you test this multi-entity service. Fill your Service Path and Entity name and press Execute Service to test your service. Select a PO Header Record to load the correct items for the header. |
49
DEV160
50
DEV160
Exercise 3.5: Creating an OData Service with Create Operation and XSJS Exit
|
Explanation |
Screenshot |
||
|
1) |
Create another OData service named user.xsodata for table sap.hana.democontent. epmNext.data::EPM.Us er.Details. This time, also link the create operation to the Server Side JavaScript Library (XSJSLIB) sap.hana.democontent. epmNext.services::user sCreateMethod.xsjslib and the function usersCreate. This will be the exit code that performs validation before the insert of the new record. |
|
|
|
Note: if you don’t 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_4 |
|||
|
2) |
We are sharing the same Server Side JavaScript Function for creation, but here is the code of this Function for you to study. |
|
|
|
$.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(); |
|||
|
//Insert Record into DB Table and Temp Output |
|||
|
Table |
|||
|
for( var i = 0; i<2; i++){ var pStmt; |
|||
|
if(i<1){ |
|||
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}\.[0- |
|
|
9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA- |
|
|
Z]{2,}))$/; |
|
|
return re.test(email); |
|
|
} |
|
53
DEV160
54
DEV160
EXERCISE 4 – USER INTERFACE
Objective
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 |
|
|
1) |
Create a new folder in your project called ui. Then create a folder within ui called odataBasic. |
|
|
2) |
Within your odataBasic folder create a new file named index.html. Then create a sub-folder called odatabasic. Within this folder we will create our view and controller named – odataBasic.view.js and odataBasic.controller.js. |
|
|
3) |
To avoid having to do too much typing, we have prepared some template code for you which already has the index.html bootstrap code in it. |
|
|
Note: if you don’t 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/exer |
||
|
ciseMaster/?workshop=dev |
||
|
160&sub=OUI_1A |
||
56
DEV160
|
4) |
To avoid having to do too much typing, we have prepared the odataBasic.controller.js template code. In this example we won’t have any custom event handlers; therefore the controller is just the empty controller structure |
|
|
Note: if you don’t 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/exer |
||
|
ciseMaster/?workshop=dev |
||
|
160&sub=OUI_1B |
||
|
5) |
To avoid having to do too much typing, we have prepared some template code for you which already has the definition of the table UI element and the table columns, but none of the logic to consume the OData service. You can cut and paste this template code from this address into the createContent function of your odataBasic.view.js file: |
|
|
Note: if you don’t 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/exer |
||
|
ciseMaster/?workshop=dev |
||
|
160&sub=OUI_1 |
||
|
You should notice that there are two commented To-Do sections in this code which you just copied into the file. These are |
57
DEV160
|
the most important parts and will be completed in the next few steps. |
||
|
6) |
In the first To-Do location you should add the code to create a model object named oModel of type sap.ui.model.odata.ODataM odel. Use the provided service /sap/hana/democontent/ep mNext/services/businessPa rtners.xsodata/. If you need help writing this code please refer to the solution at: |
|
|
http://lt5081.wdf.sap.corp:8 |
||
|
010/workshop/admin/ui/exer |
||
|
ciseMaster/?workshop=dev |
||
|
160&sub=OUI_2 |
||
|
7) |
In the second To-Do location you should set the model named oModel to the table control named oTable. Create a sorter (type sap.ui.model.Sorter) which uses the column PartnerId. Bind the table to the entity BusinessPartners and add the sorter object to the binding. If you need help writing this code please refer to the solution at: |
|
|
http://lt5081.wdf.sap.corp:8 |
|
|
|
010/workshop/admin/ui/exer |
||
|
ciseMaster/?workshop=dev |
||
|
160&sub=OUI_3 |
58
DEV160
|
8) |
That’s all that is necessary to connect the Table UI element to the OData service. We get built in table sorting and filtering, as well as server side scrolling via the various built-in parameters of the OData service framework. |
|
|
Save and Activate your project. |
||
|
9) |
Test your application in a web browser using the Run As -> HTML option. |
|
|
The URL would be http://<hostname>:<port>/d |
||
|
ev160/exercises/g<group>/ |
||
|
ui/odataBasic/. For example if you were in group number 000 your URL would be: |
||
|
http://lt5081.wdf.sap.corp:8 |
||
|
010/dev160/exercises/g000/ |
||
|
ui/odataBasic/ |
||
|
Try the sort or filter ability on one of the columns to test out the built-in features of the OData Service. |
||
|
The sample solution is also available at |
||
|
http://lt5081.wdf.sap.corp:8 |
||
|
010/sap/hana/democontent/ |
||
|
epmNext/ui/odataBasic/ |
59
DEV160
Exercise 4.2: Use oData Metadata to dynamically create the columns.
60
DEV160
61
DEV160
Exercise 4.3: Use oData Metadata with SAP Annotation OData4SAP
|
Explanation |
Screenshot |
||
|
1) |
In the previous part of this exercise we loaded the column names dynamically. This was nice but could have been better if we could have used column descriptions. We can do this using the Annotation OData4SAP and if our source is a modeled view and not a table. |
|
|
|
Return to your Exercises project. Create a new XSODATA service in the services folder named businessPartnersExt.xso data. Use sap.hana.democontent.ep mNext.models::AT_BUYE R as the source of the service and add the annotation. |
|||
|
If you need help writing this code please refer to the solution at: |
|||
|
http://lt5081.wdf.sap.corp:8 |
|||
|
010/workshop/admin/ui/exer |
|||
|
ciseMaster/?workshop=dev |
|||
|
160&sub=OUI_A |
|||
|
Save and Activate your service. |
|||
|
2) |
Return to your view file in your odataBasic project. Change the model definition to point to your new service. |
|
|
62
DEV160
|
3) |
Remove the block of code from the last section oft he exercise which dynamically creates the columns. |
|
|
4) |
In the code block we inserted in the previous exercise to create the columns dynamically from the metadata, change label text logic to load from the extensions object. Check the name of the extension looking for label and then pull the value for that extension. |
|
|
If you need help writing this code please refer to the solution at: |
||
|
http://lt5081.wdf.sap.corp:8 |
||
|
010/workshop/admin/ui/exer |
||
|
ciseMaster/?workshop=dev |
||
|
160&sub=OUI_B |
||
|
5) |
Change the sorting column to “PartnerId“ |
|
|
Save and Activate your project. |
63
DEV160
64
DEV160
Exercise 4.4: Create a Fiori Launchpad Site
65
DEV160
|
3) |
Selected the newly inserted tile in order to configure it |
|
|
4) |
Supply the following basic information in the General area |
|
|
5) |
In the Dynamic Data area, provided the following service URL: |
|
|
/sap/hana/democontent/ep mNext/services/poWorklist.x sodata/PO_WORKLIST/$co unt?$filter=((LifecycleDesc |
||
|
%20eq%20%27New%27)) |
||
|
This is the URL to an XSODATA service for the Purchase Order worklist. It will retrieve the number of New Purchase Orders. |
66
DEV160
Also set the refresh interval to 5 seconds. This way the tile will live update every 5 seconds.
67
DEV160
68
DEV160
|
10) Add a group named Default |
|
|
11) Add a tile to this group. |
|
|
12) Use the value help to choose a catalog for your tile. |
69
DEV160
70
DEV160
|
15) Navigate back to the app site configuration. |
|
|
16) Save and activate the FioriLaunchPad.xsappsite. |
|
|
17) If you click the gear in the upper right corner of the xsappsite editor and choose Runtime Version; a browser window will open with the Launchpad in it. |
|
71
DEV160
|
18) You should see a luanchpad with your tile and the actual number of new purchase orders. Click on the tile and the PO Worklist app will open. |
|
|
19) In the PO Worklist, select one of the Purchase Orders with the Lifecycle Status of New and delete it. |
|
|
20) Within 5 seconds the live tile should now reflect the newly reduced number of Purchase Order items with the status New. |
72
DEV160
© 2015 SAP SE or an SAP affiliate company. All rights reserved. No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP SE or an SAP affiliate company. SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. Please see http://www.sap.com/corporate-en/legal/copyright/index.epx#trademark for additional trademark information and notices.
73
Lebih dari sekadar dokumen.
Temukan segala yang ditawarkan Scribd, termasuk buku dan buku audio dari penerbit-penerbit terkemuka.
Batalkan kapan saja.