Showing posts with label Eclipse. Show all posts
Showing posts with label Eclipse. Show all posts

2013-07-18

Develop an SAP UI5 Application

Overview

SAP has built a great library of controls for generating colorful, animated, snappy reports for the business.

Here’s a simple example of an SAP UI5 application built with Eclipse and published to an SAP BSP application. The report displays the results of an ‘Average Turn Time’ report in a pie chart. It offers inputs to filter the data to only Temporary changes or all changes and also lets the user adjust the date range.

image

Dependencies

SAP ERP software component UISAPUI5 (SAP UI5)

Eclipse (I’m using Version: 4.2.1)

SAP HTML5 SDK (I’m using version 1.12.1)

  • SAP core library (installed on a server)
  • client software (installed in Eclipse – helpful post)

JSON HTTP Handler

First I needed a way to convert the results from an SAP function module to JSON format to be consumed by the SAP UI5 components. I found a project on SAP SCN that converts function module results to JSON. I set it up in SICF.

https://cw.sdn.sap.com/cw/groups/json-adapter-for-abap-function-modules

clip_image002

I had to make one small change to use a different class for the actual JSON conversion.  In method SERIALIZE_ID of class ZCL_JSON_HANDLER, instead of calling the transformation, I’m using class CL_TREX_JSON_SERIALIZER.

   1: *          call transformation id options data_refs = 'embedded'
   2: *                                         initial_components = 'include'
   3: *                                 source (stab)
   4: *                                 result xml json_writer.
   5: *          o_string = cl_abap_codepage=>convert_from( json_writer->get_output( ) ).
   6:           CREATE OBJECT json_writer
   7:             EXPORTING
   8:               data = stab.
   9:           json_writer->serialize( ).
  10:           o_string = json_writer->get_data( ). 

SAP UI5 Application


In Eclipse, I created the SAP UI5 application zem_ui5_gcs01.  The application uses a very simple index.html.  However, be sure to include the additional library: sap.viz.



   1: <!DOCTYPE html>
   2: <html><head>
   3:     <meta http-equiv='X-UA-Compatible' content='IE=edge' />
   4:     <title>Average Turn Time</title>
   5:  
   6:     <script id='sap-ui-bootstrap' type='text/javascript'
   7:         src='http://[host-to-sap-ui5-core]/sapui5/resources/sap-ui-core-all.js'
   8:         data-sap-ui-theme='sap_goldreflection'
   9:         data-sap-ui-libs='sap.ui.commons, sap.viz'></script>
   1:  
   2:             
   3: <script>
   4:     sap.ui.localResources('avg_turn_time');
   5:     var view = sap.ui.view({
   6:         id: "main1",
   7:         viewName:"avg_turn_time.main",
   8:         type:sap.ui.core.mvc.ViewType.JS
   9:     });
  10:     view.placeAt('content');
</script>
  10:  
  11: </head>
  12: <body class='sapUiBody'>
  13:     <div id='content'></div>
  14: </body>
  15: </html>

It calls function module Z_E_RFC_GCS_AVG_TURN_TIME. This returns in the following format:


1:  {  
2: "et_actions": [
3: { "action":"00012", "display_order":"00002", "task":"Through Request",
4: "day_count":1, "record_count":99, "day_count_2":1, "record_count_2":99 },
5: { "action":"00046", "display_order":"00003", "task":"Through Analysis",
6: "day_count":1, "record_count":99, "day_count_2":0, "record_count_2":99 },
7: { "action":"00027", "display_order":"00004", "task":"Through Approval",
8: "day_count":2, "record_count":99, "day_count_2":1, "record_count_2":99 },
9: { "action":"00088", "display_order":"00005", "task":"Through Implementation",
10: "day_count":49, "record_count":91, "day_count_2":48, "record_count_2":91 },
11: { "action":"00000", "display_order":"00006", "task":"Through Archive",
12: "day_count":59, "record_count":91, "day_count_2":10, "record_count_2":91 }
13: ],
14: "e_record_count":100
15: }

The SAP UI5 javascript application contains just one view avg_turn_time/main.view.js, that contains the UI for the report.



   1: sap.ui.jsview("avg_turn_time.main", {
   2:  
   3:       getControllerName : function() {
   4:          return "avg_turn_time.main";
   5:       },
   6:  
   7:       createContent : function(oController) {
   8:           var controls = [];
   9:           
  10:           var btn1 = new sap.ui.commons.Button({
  11:               id: this.createId('btn1'),
  12:               text: 'press me', 
  13:               press: [ oController.button_press, oController ]
  14:           });
  15:                               
  16:           var lblTemp = new sap.ui.commons.Label(this.createId('lblTemp'), { 
  17:               text: "Temporary:" 
  18:           });
  19:           var cbTemp = new sap.ui.commons.CheckBox(this.createId('cbTemp'), { 
  20:               checked: true,
  21:               change: [ oController.checkbox_change, oController ]
  22:           });
  23:           
  24:           var lblDate = new sap.ui.commons.Label(this.createId('lblDate'), { 
  25:               text: "Date:"
  26:           });
  27:           var date1 = new sap.ui.commons.DatePicker(this.createId('date1'), { 
  28:               yyyymmdd: '20130101' ,
  29:               change: [ oController.date_change, oController ]
  30:           });
  31:           var date2 = new sap.ui.commons.DatePicker(this.createId('date2'), { 
  32:               yyyymmdd: '20130105',
  33:               change: [ oController.date_change, oController ]
  34:           });
  35:  
  36:           var dataset2 = new sap.viz.ui5.data.FlattenedDataset({
  37:              dimensions : [
  38:                { axis : 1, name : 'Task', value : '{task}' },
  39:              ],
  40:              measures : [
  41:                { name : 'Average', value : '{day_count_2}' }
  42:              ],
  43:              data : { path : '/et_actions'}
  44:           });
  45:           
  46:           var pie1 = new sap.viz.ui5.Pie(this.createId('pie1'), {
  47:               dataset: dataset2
  48:           });
  49:  
  50:           controls.push(
  51:                   lblTemp, cbTemp,
  52:                   lblDate, date1, date2,
  53:                   btn1,
  54:                   pie1
  55:                   );
  56:  
  57:  
  58:           return controls;
  59:       }
  60:  
  61: });

In the controller, we create a ‘refresh’ routine to call the web service with selected input parameters.



   1: sap.ui.controller("avg_turn_time.main", {
   2:  
   3:  
   4: /**
   5: * Called when a controller is instantiated and its View controls (if available) are already created.
   6: * Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
   7: */
   8:    onInit: function() {
   9:    },
  10:  
  11: /**
  12: * Similar to onAfterRendering, but this hook is invoked before the controller's View is re-rendered
  13: * (NOT before the first rendering! onInit() is used for that one!).
  14: */
  15:    onBeforeRendering: function() {
  16:    },
  17:  
  18: /**
  19: * Called when the View has been rendered (so its HTML is part of the document). Post-rendering manipulations of the HTML could be done here.
  20: * This hook is the same one that SAPUI5 controls get after being rendered.
  21: */
  22:    onAfterRendering: function() {
  23:        //var txt1 = this.byId('txt1');
  24:        //txt1.focus();
  25:        this.refresh(undefined);
  26:    },
  27:  
  28: /**
  29: * Called when the Controller is destroyed. Use this one to free resources and finalize activities.
  30: */
  31: //   onExit: function() {
  32: //
  33: //   }
  34:  
  35:     button_press: function(event) {
  36:         this.refresh(event);
  37:     },
  38:    
  39:     date_change: function(event) {
  40:         this.refresh(event);
  41:     },
  42:     
  43:     checkbox_change: function(event) {
  44:         this.refresh(event);
  45:     },
  46:     
  47:     refresh: function(event) {
  48:         sap.ui.getCore().setModel(undefined);
  49:         
  50:             var url = 'http://<sap-host>:<sap-port>/keg/rfc/Z_E_RFC_GCS_AVG_TURN_TIME/lc?I_TEMPLATE=00001';
  51:           
  52:             var cbTemp = this.byId('cbTemp');
  53:             if (cbTemp.getChecked() == true) {
  54:                 url += '&I_TEMPORARY_FLAG=X';
  55:             } 
  56:             
  57:             var date1 = this.byId('date1');
  58:             var date2 = this.byId('date2');
  59:             url += '&I_SEARCH_DATE=IBT' + date1.getYyyymmdd() + date2.getYyyymmdd();
  60:           
  61:           var oModel4 = new sap.ui.model.json.JSONModel(url);
  62:           sap.ui.getCore().setModel(oModel4);
  63:     }
  64: });

Create the SAP BSP Application


I understand that Eclipse has the ability to connect to the SAP host and generate the BSP application automatically.  Unfortunately, due to our system release, that feature is not available to my team. 


However, SAP has provided a very nice compromise.  Report /UI5/UI5_REPOSITORY_LOAD can be used to upload the Eclipse JavaScript application to SAP as a new BSP application.  Some items of note:



  • Our system has no default code page.  Use Cp1252.
  • Activate node /default_host/sap/bc/ui5_ui5 (and subnodes).
  • During the upload, nodes are generated in two places.  Make sure they are all activated prior to execution.


/default_host/sap/bc/ui5_ui5/sap/[z_bsp_name]

/default_host/sap/bc/bsp/sap/[z_bsp_name]

Now, you’ll have access to an application at the following location.



http://[sap-host]:[sap-port]/sap/bc/ui5_ui5/sap/zem_ui5_gcs01/index.html

The result is what you see above – a cool pie chart of average time through each stage of a process.  With some more coding in events of the pie chart control, I’m pretty sure we could build some fancy drill-down capabilities… haven’t explored that yet.


Enjoy!

2011-09-15

SAP TechEd 2011: Thursday

 

CD166 - ABAP in Eclipse in Action
Thursday 8:00 a.m.
Sweet.  Really nice demonstration on using Eclipse as an ABAP editor.  SAPgui runs inside the Eclipse IDE.  Developer can connect to multiple systems at once and is not limited by six sessions.  :)  Forward navigation is supported (Ctrl-click).  No native support for dictionary objects, but the embedded SAPgui is used instead.  Features: cool code completion, code locking, integration with Change Transport System, problems view, check/save/activate process.  This tool improves the efficiency of using a test-driven development methodology.

MOB117 - Consume SAP on Your Mobile Device in Under an Hour
Thursday 10:30 a.m.
This is the low-cost option for building mobile applications.  In this session we learned the basics of what was needed: no SAP NetWeaver Gateway, no Sybase Unwired Platform.  Just a simple SAP Web Application.  Tools used: jQuery and jQuery Mobile, DOM, JSON.  Web application uses JSON to call to SAP backend and build web page dynamically.  JSON is generated by SAP ICF handler class (find blog on SDN).  Consider looking for ABAP to JSON open source project.  HTML page uses includes from jQuery, JSON, and Phone Gap libraries.  HTML page makes a call to the ICF handler and uses JSONP to process the results into HTML.  jQuery Mobile takes the HTML results and formats it properly based on end device.  This method is fine for “getting it to work”.  This method is best suited for simple applications: display-only reports.  User management (as with the SUP) is not available.

I was #9 on the SAP TechEd Knowledge Quest Leader Board after lunch today.  Rock!

CD267 - Quality Tools Within ABAP Development
Thursday 2:15 p.m.
Learned about many tools available in ABAP development environment that help support quality testing. 
Static Code Checks – Code Inspector in SE80.  Create the Inspection to associate an object set (objects to check) with a check variant (checks to perform).  I also learned how to create a unit test class for ABAP classes.  Test Driven Development was identified as an important methodology to use.

EIM209 - SAP NetWeaver Enterprise Search in Non-SAP Systems
Thursday 4:30 p.m.
SAP NetWeaver Enterprise Search 7.2 connected to PLM, DMS and many other SAP products.  Also connected to many non-SAP systems.  Additionally, it appears that this team has implemented the PLM Web UI.  Security was implemented to restrict access to search results which would meet our FDA/ITAR restrictions.  I didn’t have opportunity to discuss the SAP-side (as this was a non-SAP lecture).  But I have contact information and think we should contact him for a discussion.

CD116 - Workflow Approvals Anywhere: It Saved You How Much?
Thursday 5:45 p.m.
Presenter described a solution in which a Workflow was used to catch new Purchase Order objects and send an email to the approver(s) with a key file.  When the approver clicks a link in the email, a new email is generated and sent (with the key) back to SAP.  Another SAP program catches the incoming email and approves the PO on behalf of the email recipient.  My thoughts: a similar process could potentially be used during a Change Order approval process.  Looks nice: they generated a rich HTML-based email; not just plain text.  Next they enhanced the process to include other SAP objects: hire requests, customer invoices, travel expense, etc.