第一章 服务器端javascript XSJS
按照我们以往开发应用的经验,有客户端开发和服务器端开发。客户端开发在HANA XS应用开发里可以使用SAPUI5,一个完全运行在客户端的JS框架。那么我们也需要开发服务器端逻辑。HANA有SQLScript,但是它没法完全承担起服务器端开发的任务,不然O记也不需要JAVA,所有的应用都用PL/SQL好了。HANA XS应用的服务器端开发语言,依然是javascript。SAP选择了Mozilla SpiderMonkey https://developer.mozilla.org/en/docs/SpiderMonkey 作为服务器端JS的虚拟机。不知道为什么没有选择google的V8。SAP选择SJ作为服务器端编程语言,我觉得主要考虑还是因为它够轻量级。因为本身XS Engine就是一个轻量级的应用服务器,当然也要有一个足够轻量级的编程语言。
HANA XS的服务器端JS API参考手册在http://help.sap.com/hana/jsapi/index.html HANA XS的JS API的底层实现是由C/C++实现然后以JS API的方式暴露,似的开发人员能够用JS这种易用的语言调用。它能够与HANA XS引擎交互、直接访问HANA DB、处理HTTP请求等。
第二章 创建XSJS服务
本章只是让大家体验一下服务器端JS,有一个感性的认识。从HANA Studio,有一个创建选项:XS Javascript source file,这就是创建XS服务器端JS。
本章的示例代码为:
我们可以看到,与当年写JAVA Servlet入门程序是很相像的,在服务器端解析http request请求,执行操作,然后构建http response文件。HANA XS JS的API是以美元符号作为前缀的。激活之后就可以打开浏览器运行测试了。
第三章 扩展XSJS服务
本章在上一章基础上演示了一个更复杂一点的XSJS代码。主要的功能是在计算乘法的基础上可以下载excel文件。示例代码如下:
$.import("sap.hana.democontent.epm.services", "messages"); var MESSAGES = $.sap.hana.democontent.epm.services.messages; function performMultiply(){ var body = ''; var num1 = $.request.parameters.get('num1'); var num2 = $.request.parameters.get('num2'); var answer; answer = num1 * num2; body = answer.toString(); $.response.setBody(body); $.response.status = $.net.http.OK; } function downloadExcel() { var body = ''; try { var query ='SELECT TOP 25000 \"PurchaseOrderId\", \"PartnerId\", \"CompanyName\", \"CreatedByLoginName\", \"CreatedAt\", \"GrossAmount\" ' + 'FROM \"sap.hana.democontent.epm.data::purchaseOrderHeaderExt\" 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" + // PurchaseOrder 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', 'attachment; filename=Excel.xls'); $.response.headers.set('access-control-allow-origin', '*'); $.response.status = $.net.http.OK; } var aCmd = $.request.parameters.get('cmd'); switch (aCmd) { case "multiply": performMultiply(); break; case "Excel": downloadExcel(); break; default: $.response.status = $.net.http.INTERNAL_SERVER_ERROR; $.response.setBody(MESSAGES.getMessage('SEPM_ADMIN', '002', aCmd)); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | sap.ui.jsview("sapui5.xsjstest", { getControllerName : function() { return "sapui5.xsjstest"; }, createContent : function(oController) { var multiplyPanel = new sap.ui.commons.Panel().setText("XS Service Test - Multiplication"); multiplyPanel.setAreaDesign sap.ui.commons.enums.AreaDesign.Fill); multiplyPanel.setBorderDesign sap.ui.commons.enums.BorderDesign.Box); var layoutNew = new sap.ui.commons.layout.MatrixLayout({width:"auto"}); multiplyPanel.addContent(layoutNew); var oVal1 = new sap.ui.commons.TextField("val1",{tooltip: "Value #1", editable:true}); var oVal2 = new sap.ui.commons.TextField("val2",{tooltip: "Value #2", editable:true}); var oResult = new sap.ui.commons.TextView("result",{tooltip: "Results"}); var oEqual = new sap.ui.commons.TextView("equal",{tooltip: "Equals", text: " = "}); var oMult = new sap.ui.commons.TextView("mult",{tooltip: "Multiply by", text: " * "}); //Attach a controller event handler to Value 1 Input Field oVal1.attachEvent("liveChange", function(oEvent){ oController.onLiveChangeV1(oEvent,oVal2); }); //Attach a controller event handler to Value 2 Input Field oVal2.attachEvent("liveChange", function(oEvent){ oController.onLiveChangeV2(oEvent,oVal1); }); layoutNew.createRow(oVal1, oMult, oVal2, oEqual, oResult ); return multiplyPanel; } }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | onLiveChangeV1: function(oEvent,oVal2){ //To-Do: Insert Service Call to XSJS Service var aUrl = '../../../services/Example1.xsjs?cmd=multiply'+ '&num1='+escape(oEvent.getParameters().liveValue)+ '&num2='+escape(oVal2.getValue()); jQuery.ajax({ url: aUrl, method: 'GET', dataType: 'json', success: this.onCompleteMultiply, error: this.onErrorCall }); }, onLiveChangeV2: function(oEvent,oVal1){ //To-Do: Insert Service Call to XSJS Service var aUrl = '../../../services/Example1.xsjs?cmd=multiply'+ '&num1='+escape(oVal1.getValue())+ '&num2='+escape(oEvent.getParameters().liveValue); jQuery.ajax({ url: aUrl, method: 'GET', dataType: 'json', success: this.onCompleteMultiply, error: this.onErrorCall }); }, onCompleteMultiply: function(myTxt){ var oResult = sap.ui.getCore().byId("result"); if(myTxt==undefined){ oResult.setText(0); } else{ jQuery.sap.require("sap.ui.core.format.NumberFormat"); var oNumberFormat = sap.ui.core.format.NumberFormat.getIntegerInstance({ maxFractionDigits: 12, minFractionDigits: 0, groupingEnabled: true }); oResult.setText(oNumberFormat.format(myTxt)); } }, onErrorCall: function(jqXHR, textStatus, errorThrown){ sap.ui.commons.MessageBox.show(jqXHR.responseText, "ERROR", "Service Call Error" ); return; } |
第五章 调试XSJS
之后,当我们在eclipse里启动debug的时候会弹出窗口,让我们选择要debug的session,这个时候选择你在上一步获得的session即可。