Simple Exercise on OData and SAP UI5 Application for the basic CRUD Operation
Contents
1. Introduction
2. Creation of OData Service
2.1 Creation of OData Service
2.1.1 Pre-requisites
2.1.2 Creation of Data Model
2.1.3 Generate Run time Objects
2.1.4 Service Implementation.
2.1.5 Registration of Service.
3.Consumption of OData Service SAP UI5 application.
3.1 Consuming OData Service for CRUD operation using UI5 Application.
3.1.1 Pre-requisites
3.1.2 Creation of SAP UI5 Application.
3.1.3 Create a Dashboard for Employee details display.
3.1.4 Pop-up window for Data Modify.
3.1.5 Create button for Data Creation.
4.Source code used.
List of Abbreviations/Acronyms
Term |
Explanation |
DPC |
Data Provider Class |
MPC |
Model Provider Class |
CRUD |
Create, Read, Update, Delete |
1. Introduction
In the demo we are going to see an example on SAP UI5 application for CRUD operation using SAP UI5 and OData Operations. This demo can be split in to two main divisions.
- Creation of OData Service
- Consuming an OData Service using SAP UI5 application.
2. Creation of OData Service
We are going to create an OData service for the custom Employee Details with the basic operations Create, Read, Delete and Update (CRUD).
2.1 Creation of OData Service
In this example we are going to see the creation of OData service using the SAP Gateway Service Builder(SEGW). The OData Service can also be built by various ways available and we took the Gateway Service Builder approach here. In this example, the OData has been deployed in the embedded deployment model where the single system acts as both Gateway and Backend system.
The below mentioned are the steps are used to create the OData service.
- Pre-requisite
- Creation of Data Model
- Generate Runtime Objects
- Registration of Service
- Service Implementation
2.1.1 Pre-requisites
In the pre-requisite, we are going to create a transparent table which is going to act as a back end table and function module for the Create, Read, Update and Delete (CRUD) operation to be used in this OData creation.
1. Creation of Table, we will create a Z table with basic employee details. Once the table is created, please create some entries. Later, these entries will be displayed in the UI dashboard.
2. Create Function Modules for Create, Read, Update and Delete operation.
Important Note: Create the Function Module as Remote-Enabled Function Module.
- Function Module for Create Operation
- Function Module for Read Operation
- Function Module for Update Operation
- Function Module for Delete Operation
2.1.2 Creation of Data Model
The Data model is used to describe the OData Services which contains Entity, Properties, and EntitySet and so on.
In this example, we are going to build a OData service using SAP Gateway Service Builder (SEGW)
1. Go to Transaction Code: SEGW, which will land you in the Gateway Service Builder.
2. Create a Project
3. Once the Project is created, create Entity and EntitySet by the Import option available
4. Give the Entity, Structure and the EntitySet create option as below. We are going to use the already created employee table structure here.
5. Select all the Data source parameters and press Next.
6. Press Finish to complete the Data Model creation.
Note: There are number of ways to define the Data Model and we have chosen the import->DDIC structure option here.
7. The Entity and EntitySet are created now, and we can see the entity type has been created with reference to the given ABAP Structure.
8. Once it is added, we have the properties created now as below. Choose Empid as a Key here, the key also can be defined at the step 6 by marking the key field as “Is Key”.
2.1.3 Generate Run time Objects
1. Once all the above activities are completed, generate the run time objects by pressing the Ctrl+F3 button. This will pop up the below window with all the option to generate the run time objects.
2. Once this activity is complete, we have the objects generated as below.
This will generate the Data Provider Class, widely we call it as DPC and Model Provider Class and this we call it as MPC class.
DPC=> Business Logic for CRUD operation goes here.
MPC=>Data Model Class, where we can see the data model defined.
2.1.4 Service Implementation
In this section, we are going to generate the Business logic using the RFC Function Module we have created earlier for the CRUD Operations. Instead of using RFC Function Module, we can also use Business Object Repository. Also you can use your own custom logic in the DPC_EXT classes for the data operations.
1. Go to Service Implementation, select the Create Operation and go to Map to Data Source.
2. Select the Function Module for Create Option as below and press Continue
3. Then the below window will be open with the Data Source Parameter and the Data Mapping has to be done as follows. Also we have an option “Propose Mapping”, which does the data mapping automatically.
Create
Drag and drop the Data Source Parameter as shown below for the Mapping Operation.
Similarly, we have defined the mapping for Delete, GetEntity, GetEntitySet and Update operation using the Function Modules we have already created.
Delete
GetEntity
We have added one more Property, Empid to fetchthe records from the backend based on the Key.
GetEntitySet
We have added one more Property, Empid to fetch the records from the backend based on the Key.
Update
Once the mapping is completed, generate run time objects ( Ctrl+F3 ) and go to your Data Provider Class(DPC) to find the ABAP coding has been generated automatically.
Once the above all activities are completed, we have to register the OData service to consume them.
2.1.5 Registration of Service
1. Go to gateway and select the Gateway service. You will find the OData service is yet to be registered as the Registration status traffic light button is grey.
2. Select the Service and press the Register button to complete the Registration of the OData service and press yes to continue.
3. Select the package assignment as local object and continue the process.
4. On press of continue will register the OData Service. You can also add the service using the Transaction code: /IWFND/MAINT_SERVICE.
5. Select the Gateway Client and this will launch you in the SAP Netweaver Gateway Client. This can also be accessed separately using the T-code : /IWFND/GW_CLIENT. Execute the uri: /sap/opu/odata/sap/ZMM_EMP_SRV/$metadata to test the OData service.
By this successful response, the OData service has been built and it is working fine. Further we will see, how can we consume the OData service using SAP UI5 application in the next chapter.
Metadata Uri: http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/$metadata : OData Service Metadata document can be accessed here.
Entity Set : http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet : The Employee records can be accessed here.
Replace the tags <host name>, <port no> with your server and port details.
3. Consumption of OData Service using SAP UI5 application
In this example, we will create a SAPUI5 application for Employee and we will see the see how the OData service can be consumed for the basic CRUD operation. Whereas the below are the CRUD methods and their equivalent HTTP methods in the OData service.
3.1 Consuming OData Service for CRUD Operation using SAP UI5 Application
In this example, we are going to create a UI5 application by which we can consume the already created OData service for the basic CRUD operation.
This app contains the following details:
- Pre-requisite
- Creation of SAP UI5 Application
- Create a Dashboard to display Employee Details
- Popup window for Data modify operation
- Create button for Data creation
3.1.1 Pre-requisites
We need an Eclipse IDE with version Kepler, Luna or any other latest version with the SAP UI5 plugin to develop the SAP UI5 application. If you want to know how the SAP UI5 development plugins can be added to eclipse, click here.
3.1.2 Creation of SAP UI5 Application
Create a New SAP UI5 project by the below path in the menu bar
1. Go to Menu bar : File->New->Other->SAP UI5 Application development(Application Project) and then press next.
2. Give the project name, with the option to create a Initial view. The view can be created separately as well.
3. Provide the view name and choose the Paradigm as JavaScript and press Finish.
4. By this, we have created an empty SAPUI5 project called “EmpCRUD” with view “EmpDetails” as below.
3.1.3 Create a Dashboard for Employee details display
1. Create a dashboard with the Table contains fields as Employee Id, Name, Address and Designation. Assign the same to the Page and return the page. (EmpDetails.view.js)
2. You can execute and view the dashboard the option “Web App Preview” as below. Also you can use the option “Run on Server”, but you need to install Tomcat / any other web server for the same.
3. Then it appears in the Eclipse as below. Further you can copy and paste the url in the chrome browser. You can use any browser, but I have used chrome as the debugging in bit easy.
4. In the browser, it appears as below. An empty Dashboard is built now.
5. Now the Dashboard is built, we will see how the data can be populated here. Go to “EmpDetails.controller.js” and in the onInit function, write the coding as below to fetch the data from server. This will do a OData call to fetch the data from the server in JSON format. This data further has to be bind to the table we built already. Replace the tags <Server Name>, <Port No> with your respective server details.
ZMM_EMP_SRV: Name of the OData Service, we already built.
EmployeeSet: Name of the entity set name for employees.
6. The data binding happens as below.
Run the app again in the “Web App Preview” to see the data displayed in the dashboard as below. When prompted for login credentials to your backend server, provide your User id/Password credentials to continue.
7. When you run/execute the application, it may not run due to ‘Access-Control-Allow-Origin’ issue. To overcome this issue, we have an option available with chrome browser.
- Make sure you close out all instances of Google Chrome including ending all its processes in the Windows Task Manager.
- Right-Click on your Google Chrome Icon, Go to the Target: and add the command “–disable-web-security”, apply the settings as below.
- This should allow you to overcome the ‘Access-Control-Allow-Origin’ issue and the application should run in the chrome browser.
8.When executed again, the employee data appears in the chrome browser as below.
By this READ (GET) operation is complete. Further we will see the remaining operations below.
3.1.4 Pop-up window for Data Modify
1. We will create a popup window with text areas for Employee Id, Emp Name, Address and Designation with three buttons Update, Delete and Cancel for the modify operations. Go to View.js and add the coding as below.
2. We have the dialog box or the pop-up window created now. Further we will see how we can make use of the dialog box for the modify operation.
On the press of employee details, we will open a dialog box where we will show the employee details and it can be modified or deleted. We will read the employee details from the selected item and will populate the dialog box. The key, “Employee id” we will disable for edit.
3. Once it is done, re -run the application to see a dialog window pop-up on a selection of the item. The selected record details are shown now. But the buttons “Update”, ”Delete” and “Cancel” actions are yet to be defined.
4. Go to the controller.js. where you can define the action of the Update button.
5. GET in the OData call is used to fetch the X-CSRF token. Once the token is fetched, it act as an authentication to do the further update(PUT) operation.
Note: You need a CSRF token to be fetched to perform the Modify/Insert operation. To know more about the CSRF token click here.
Re-run the application to test the update operation. I have updated the address and pressed update button.
6. On the success, we will reload the main page with the newly updated details.
7. On the press of Ok button, the page will be re-loaded with the newly updated details.
The update operation is complete. We will further see the Delete operation details.
8. Go to the controller.js. where we can define the action of the Delete button.
9. GET in the OData call is used to fetch the X-CSRF token. Once the token is fetched, it act as an authentication to do the further delete(DELETE) operation.
Note: You need a CSRF token to be fetched to perform the Modify/Insert operation. To know more about the CSRF token click here.
Re-run the application to test the delete operation. I have selected a record and pressed delete button.
10. On the success, we will reload the main page with the deleted details.
11. On the press of Ok button, the page will be re-loaded with the modified details.
12. The Delete operation is complete. On the press of the cancel button we will close the dialog box by adding the below in the controller.js
3.1.5 Create button for Data Creation
1. We will place a button “Create New Employee” in the dashboard and by this we will see the creation of a new employee.
Go to view.js where we will create button Submit, Save. We will add the Save button to the Dialog box.
2. We will add the button Submit button to the main dashboard as below.
3. Further we will go to controller.js to do the action for the “Create New Employee”. We will use the same dialog box, we have already created for the modify operation. We will hide the “Save” button in the modify operation and while creation, we will hide the “Update”, “Delete” button.
4. Re-run the application to see the new button “Create New Employee” visible in the main page and on the press of the button, a dialog box with the employee details can be added.
5. While press on the save, nothing will happen as we are yet to write the function for the “Save” action.
Go to the controller.js, where we can define the action for the “Save” button.
6. GET in the OData call is used to fetch the X-CSRF token. Once the token is fetched, it act as an authentication to do the further Create(POST) operation.
Note: You need a CSRF token to be fetched to perform the Modify/Insert operation. To know more about the CSRF token click here.
Re-run the application to test the Create operation.
7. On the success, we will reload the main page with the newly created details.
8. On the press of Ok button, the page has been re-loaded with the newly created details.
The Create operation is complete. By then we have completed all the basic CRUD operations.
4. Source code used
The source code used in this project is also given as a reference here.
Index.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv=“X-UA-Compatible” content=“IE=edge”>
<meta http-equiv=‘Content-Type’ content=‘text/html;charset=UTF-8’/>
<script src=“resources/sap-ui-core.js”
id=“sap-ui-bootstrap”
data-sap-ui-libs=“sap.m”
data-sap-ui-theme=“sap_bluecrystal”>
</script>
<!– only load the mobile lib “sap.m” and the “sap_bluecrystal” theme –>
<script>
sap.ui.localResources(“empcrud”);
var app = new sap.m.App({initialPage:“idEmpDetails1”});
var page = sap.ui.view({id:“idEmpDetails1”, viewName:“empcrud.EmpDetails”, type:sap.ui.core.mvc.ViewType.JS});
app.addPage(page);
app.placeAt(“content”);
</script>
</head>
<body class=“sapUiBody” role=“application”>
<div id=“content”></div>
</body>
</html>
EmpDetails.view.js
sap.ui.jsview(“empcrud.EmpDetails”, {
/** Specifies the Controller belonging to this View.
* In the case that it is not implemented, or that “null” is returned, this View does not have a Controller.
* @memberOf empcrud.EmpDetails
*/
getControllerName : function() {
return “empcrud.EmpDetails”;
},
/** Is initially called once after the Controller has been instantiated. It is the place where the UI is constructed.
* Since the Controller is given to this method, its event handlers can be attached right away.
* @memberOf empcrud.EmpDetails
*/
createContent : function(oController) {
var oPage = new sap.m.Page({
title: “Employee Details”,
});
var oBtnUpd = new sap.m.Button(“Update”, {
text: “Update”,
tap: [ oController.Update, oController ]
});
var oBtnDel = new sap.m.Button(“Delete”, {
text: “Delete”,
tap: [ oController.Delete, oController ]
});
var oBtnCan = new sap.m.Button(“Cancel”, {
text: “Cancel”,
tap: [ oController.Cancel, oController ]
});
var oBtnSub = new sap.m.Button(“Submit”, {
text: “Create New Employee”,
press: oController.NewEntry,
});
var oBtnSav = new sap.m.Button(“Save”, {
text: “Save”,
tap: [ oController.Save, oController ]
});
// Dialog box / pop-up window for Add/Modify Employee Data
var oDialog = new sap.m.Dialog(“Dialog”,{
title:“Add/Modify Employee”,
modal: true,
contentWidth:“1em”,
content:[
new sap.m.Label({text:“Enter Emp Id(must be a number)”}),
new sap.m.Input({
maxLength: 20,
id: “Id”
}),
new sap.m.Label({text:“Enter Name”}),
new sap.m.Input({
maxLength: 20,
id: “Name”
}),
new sap.m.Label({text:“Enter Address”}),
new sap.m.Input({
maxLength: 20,
id: “Address”
}),
new sap.m.Label({text:“Enter Designation”}),
new sap.m.Input({
maxLength: 20,
id: “Role”
}),oBtnUpd, oBtnDel, oBtnCan, oBtnSav
]
});
// Table or Dashboard to show the Employee Data
var oTable = new sap.m.Table({
id: “Employees”,
itemPress : [ oController.ItemPress,oController ],
columns: [
new sap.m.Column({
width: “1em”,
header: new sap.m.Label({
text: “Emp ID” }) }),
new sap.m.Column({
width: “1em”,
header: new sap.m.Label({
text: “Name” })
}),
new sap.m.Column({
width: “1em”,
header: new sap.m.Label({
text: “Address”
})
}),
new sap.m.Column({
width: “1em”,
header: new sap.m.Label({
text: “Designation”
})
})
]
});
// Template to map the data to the respective column
var template = new sap.m.ColumnListItem({
id: “first_template”,
type: “Navigation”,
visible: true,
cells: [
new sap.m.Label(“ID”, {
text: “{Empid}”
}),
new sap.m.Label({
text: “{Empname}”
}),
new sap.m.Label({
text: “{Empadd}”
}),
new sap.m.Label({
text: “{Empdes}”
})
]
});
var oFilters = null;
oTable.bindItems( “/results”,template, null, oFilters);
oPage.addContent(oTable);
oPage.addContent(oBtnSub);
return oPage;
}
});
EmpDetails.controller.js
sap.ui.controller(“empcrud.EmpDetails”, {
/**
* Called when a controller is instantiated and its View controls (if available) are already created.
* Can be used to modify the View before it is displayed, to bind event handlers and do other one–time initialization.
* @memberOf empcrud.EmpDetails
*/
onInit: function() {
var sServiceUrl = “http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV”;
var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl,true);
var oJsonModel = new sap.ui.model.json.JSONModel();
oModel.read(“/EmployeeSet?”,null,null,true,function(oData,repsonse){
oJsonModel.setData(oData);
});
sap.ui.getCore().setModel(oJsonModel);
},
/**
* Similar to onAfterRendering, but this hook is invoked before the controller’s View is re–rendered
* (NOT before the first rendering! onInit() is used for that one!).
* @memberOf empcrud.EmpDetails
*/
// onBeforeRendering: function() {
//
// },
/**
* 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.
* This hook is the same one that SAPUI5 controls get after being rendered.
* @memberOf empcrud.EmpDetails
*/
// onAfterRendering: function() {
//
// },
/**
* Called when the Controller is destroyed. Use this one to free resources and finalize activities.
* @memberOf empcrud.EmpDetails
*/
// onExit: function() {
//
// }
ItemPress: function(evt) {
sap.ui.getCore().byId(“Dialog”).open();
sap.ui.getCore().byId(“Update”).setVisible(true);
sap.ui.getCore().byId(“Delete”).setVisible(true);
var oSelectedItem = evt.getParameter(“listItem”);
var sID = oSelectedItem.getBindingContext().getProperty(“Empid”);
var sName = oSelectedItem.getBindingContext().getProperty(“Empname”);
var sAddr = oSelectedItem.getBindingContext().getProperty(“Empadd”);
var sRole = oSelectedItem.getBindingContext().getProperty(“Empdes”);
sap.ui.getCore().byId(“Id”).setValue(sID);
sap.ui.getCore().byId(“Name”).setValue(sName);
sap.ui.getCore().byId(“Address”).setValue(sAddr);
sap.ui.getCore().byId(“Role”).setValue(sRole);
sap.ui.getCore().byId(“Id”).setEnabled(false);
},
NewEntry: function() {
sap.ui.getCore().byId(“Dialog”).open();
sap.ui.getCore().byId(“Save”).setVisible(true);
sap.ui.getCore().byId(“Update”).setVisible(false);
sap.ui.getCore().byId(“Delete”).setVisible(false);
sap.ui.getCore().byId(“Id”).setValue(“”);
sap.ui.getCore().byId(“Name”).setValue(“”);
sap.ui.getCore().byId(“Address”).setValue(“”);
sap.ui.getCore().byId(“Role”).setValue(“”);
sap.ui.getCore().byId(“Id”).setEnabled(true);
},
Save: function() {
var oEntry = {};
oEntry.Empid= sap.ui.getCore().byId(“Id”).getValue();
oEntry.Empname= sap.ui.getCore().byId(“Name”).getValue();
oEntry.Empadd= sap.ui.getCore().byId(“Address”).getValue();
oEntry.Empdes= sap.ui.getCore().byId(“Role”).getValue();
OData.request({
requestUri : “http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet”,
method : “GET”,
headers : {
“X-Requested-With” : “XMLHttpRequest”,
“Content-Type” : “application/atom+xml”,
“DataServiceVersion” : “2.0”,
“X-CSRF-Token” : “Fetch”
}
},
function(data, response) {
header_xcsrf_token = response.headers[‘x-csrf-token’];
var oHeaders = {
“x-csrf-token” : header_xcsrf_token,
‘Accept’ : ‘application/json’,
};
OData.request({
requestUri : “http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet”,
method : “POST”,
headers : oHeaders,
data:oEntry
},
function(data,request) {
alert(“Employee Created Successfully”);
location.reload(true);
}, function(err) {
alert(“Employee Creation Failed”);
});
}, function(err) {
var request = err.request;
var response = err.response;
alert(“Error in Get — Request “ + request + ” Response “ + response);
});
},
Update: function() {
var oEntry = {};
oEntry.Empid= sap.ui.getCore().byId(“Id”).getValue();
oEntry.Empname= sap.ui.getCore().byId(“Name”).getValue();
oEntry.Empadd= sap.ui.getCore().byId(“Address”).getValue();
oEntry.Empdes= sap.ui.getCore().byId(“Role”).getValue();
OData.request({
requestUri : “http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet”,
method : “GET”,
headers : {
“X-Requested-With” : “XMLHttpRequest”,
“Content-Type” : “application/atom+xml”,
“DataServiceVersion” : “2.0”,
“X-CSRF-Token” : “Fetch”
}
},
function(data, response) {
header_xcsrf_token = response.headers[‘x-csrf-token’];
var oHeaders = {
“x-csrf-token” : header_xcsrf_token,
‘Accept’ : ‘application/json’,
};
OData.request({
requestUri : “http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet(‘”+oEntry.Empid+“‘)”,
method : “PUT”,
headers : oHeaders,
data:oEntry
},
function(data,request) {
alert(“Update Success”);
location.reload(true);
}, function(err) {
alert(“Update Failed”);
});
}, function(err) {
var request = err.request;
var response = err.response;
alert(“Error in Get — Request “ + request + ” Response “ + response);
});
},
// Delete Action
Delete: function() {
var oEntry = {};
oEntry.Empid= sap.ui.getCore().byId(“Id”).getValue();
OData.request({
requestUri : “http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet(‘” + oEntry.Empid + “‘)”,
method : “GET”,
headers : {
“X-Requested-With” : “XMLHttpRequest”,
“Content-Type” : “application/atom+xml”,
“DataServiceVersion” : “2.0”,
“X-CSRF-Token” : “Fetch”
}
},
function(data, response) {
header_xcsrf_token = response.headers[‘x-csrf-token’];
var oHeaders = {
“x-csrf-token” : header_xcsrf_token,
‘Accept’ : ‘application/json’,
};
OData.request({
requestUri : “http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet(‘”+oEntry.Empid+“‘)”,
method : “DELETE”,
headers : oHeaders,
data:oEntry
},
function(data,request) {
alert(“Delete Success”);
location.reload(true);
}, function(err) {
alert(“Delete Failed”);
});
}, function(err) {
var request = err.request;
var response = err.response;
alert(“Error in Get — Request “ + request + ” Response “ + response);
});
},
// Cancel Action
Cancel:function() {
sap.ui.getCore().byId(“Dialog”).close();
}
})
Excellent post !
Good reference!
Would it be possible to share the whole thing as a Git project?
Thx.
Thank you for your comment on this!..
Here you go..
The project has been shared in gitHub :https://github.com/
Repository Name: empCRUD
SSH: git@github.com:meeranmd/empCRUD.git
Https: https://github.com/meeranmd/empCRUD.git
Hope this helps..
Thanks & Regards,
Mohamed Meeran
Hi Mohamed,
thank you for sharing your project on GitHub. Do you know the SAPlink project? It would allow you also to share most of the ABAP objects (Function Group, DB Table, Domains, Data Elements).
Best regards
Gregor
Hey Mohammed may you please explain where the ZMM_EMP_TT export value in the ZMM_EMP_GET function module is coming from.
Thank you 🙂
Hey ! Follow this
se11 -> Data Type -> ZMM_EMP_TT -> Create
In the tab that follow's Line Type : ZMM_EMP
Save and activate it !
Then in the function module , In export tab , declare et_emp and its type would be ZMM_EMP_TT 🙂
go to se11–>Data Type-->ZMM_EMP_TT –>Table Type(3rd Radio Button)–> give short text –>Line Type”ZMM_EMP”–> Save & Activate
Great tutorial!
Would it be possible to add XML Views implementation? Since I cannot figure out how to set the itemPress event for sap.m.Table control properly.
Thx
Hi Yang Wang,
Thank you for your comment on this.
Hope this link will be useful to sort out your issue.
Thanks & Regards,
Mohamed Meeran
Hi,
thank you for the effort, but I'm struggling with the tutorial at the moment.
A suggestion
I'm no ABAP dev, and trying to create an oData service myself. It would be nice to extend the ABAP parts, for example where is the ZMM_EMP_TT export value in the ZMM_EMP_GET function module coming from. I had to solve that with a colleague, where we created an ABAP dictionary object. But it's not self describing.
And I'm completely stuck at the "Map to Data Source." part. After accepting the choice I make, I get a message that the data source is not existing. I completed all the other parts as described before. Any advice from your side?
Kind regards,
Michael
Regarding the data source is not existing, do you made you Function Module remote-enabled?
I did not, thank you, that should be a step in the right direction.
I'm trying to make it so, but I'm getting a message that reference parameters are not allowed with RFC, I'll have to fix that next.
Edit:
Solution, in the Import and Export tab, tick all the checkboxes in the column "Pass Value".
Hi Michael,
Thank you for your comment on this.
Answers for your queries as below.
1. Function Modules and Table Types are not detailed enough: As Fn.Modules and Table types are already a much discussed topic and there are number of references available and also I was afraid detailing them will grow the size of this topic and it will be lengthy and boring. Hope you understand.
2. Map to Data Source not working: Function Modules to be Remote enabled - This was the reason, it was not working. It was already mentioned in the document as Note. Thanks for highlighting this, I have made bold them now.
Hope you have already sorted out the issues 1 and 2 and you are through. Please do let me know if you are still facing any other issues.
Thanks & Regards,
Mohamed Meeran
Hey Michael may you please explain where the ZMM_EMP_TT export value in the ZMM_EMP_GET function module is coming from.
Thank you 🙂
I'm sorry Reginald, I did the excercise more than a year ago and since then I didn't work on OData services. As said in my comment from then, you should ask someone how an ABAP dictionary object could be helpful here.
Hi Reginald,
You could create the custom table type using SE11 data dictionary transaction which would be your reference structure.
Please create Line type with all your required fields and mention the same in the new Table type.
As mentioned above you may get lot of reference material in SCN for creating these objects .
go to se11–>Data Type-->ZMM_EMP_TT –>Table Type(3rd Radio Button)–> give short text –>Line Type”ZMM_EMP”–> Save & Activate
Hi Meeran,
This document is very informative and a good start-up guide . Thank you so much for sharing.
Great effort.
Best Regards,
Manvitha
Hi Mohamed,
I'm wondering why you're not using the create and update methods provided by the SAPUI5 OData Model? You're constructing the HTTP requests on your own. Was there any specific reason for that?
Best regards
Gregor
Hi Meeran,
Great post !!!
Hi Meeran,
Good post. But I have some issues.
I got stuck up at Step 1.3 "Create a Dashboard for Employee details display" itself.
When i debug in Chrome it shows the 404 error as below : Uncaught Error: failed to load 'empcrud/EmpDetails.view.js' from ./empcrud/EmpDetails.view.js: SyntaxError: Illegal return statement.
Can you suggest where am I wrong?
Thanks Ricky
Superb document. Highly appreciate your work 🙂
Really very usefull information 🙂 .
I need to clarify some of my doubts here . in Webdynpro appliication we have assitence class where i will load all the master data of pernr in global attributes . Like this Here i can user Global calssed instead of refering RFC ? .
For example when the person log on into application itself i can load all of his master details such as name , emp group , loaction , company code, work schedule , .. so in front end i can add validation without hitting the DB again . How i can bring that scenario in UI5 application . i would like to know all applicable OO-ABAP futures in SAPUI5.
It was Really useful once again thanks for sharing these documents.
I really have one doubt,
1. How many server need to be maintained for SAP Fiori.
my assumption is one server need to be configured for ODATA and the other one is
for Fiori Launch pad.
could you please correct me if I am wrong.
Regards,
Gnanu
You need a front end server, where the Launchpad code as well as the UI5 application code are stored, and the OData services are defined. And this one is connected to your back-end system. Therefore when you build on an existing installation, you need a new front-end server. That's the best practice as far as I know.
Hi,
Very nice blog it helped in creating a new UI5 application from Creation of FM to OData service and UI5 front end as well. I deployed the application in Enterprise Portal as well.
Thanks a lot.
Wonderful Post!!!
Hi..
I don't see Gateway line in Service Maintenance, which is shown in step 1 of Topic 2.1.5 Registration of Service. Pls help !!
Regards Abhishek
Got it.. Created Gateway Alias..
Quick Starter Configuration Guide - SAP Gateway
Superb excellent document. Explained each and every thing!!. 😘
Good Read! You haven't left anything to explain here.
Keep Up with this!
Cheers,
-NK
Awesome post Mohamed Meeran..
Keep it up.. 🙂
Best Regards,
Pavan G
Nice post ..really very helpful..
Regards,
Praveer.
Very helpful. Thanks for sharing.
Regards,
Raghu Prasad
nice post and helpful,
thanks for the post
i have one doubt Mohamed Meeran..
can u please explain me one line of code
in the
oninit : function()
omodel.read("/employeeset?",null,null,true,function(oData,response){
oJsonmodel.setData(oData);
});
oJsomModel.setData(odata);// from wer u r setting this odata to the jsonmodel
Regards,
Deepak
Hi Deepak,
Cheers,
Pavel
thanks for the reply and
you cleared my doubt
Pavel Duchac
best regards,
Deepak
hii sir while creating
Excellent Illustration and guide for performing the Crud operation from SAPUI5 application .
Great Job , thanks you
I was able to follow complete the exercise with Different tables and service .
Hi Experts,
i was tying to create the same way.
but in step 2.1.5 i was stuck.I couldnt able to find the service maintanance object under service maintanace.please help to clarify.
2.1.5 Registration of Service
1. Go to gateway and select the Gateway service. You will find the OData service is yet to be registered as the Registration status traffic light button is grey.
bt its not coming in my exercise.
Regards
Ashwin
You need to add the service manually. Click on 'Add Service'.
You need to maintained SAP Getway Settings first. Path: SPRO->SAP Gateway->SAP Geteway Service Enablement->Connection Settings to SAP Gateway -> SAP Gateway Settings. then you can see the ADD Services bution active in SEGW. please try ~
It never asks me for username , password . But gives an error (unauthorized) ? What should I do
Hi,
Consume OData Service with following structure in controller.js
var username = "developer";
var password = "Dev@123"
requesturi = "http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/<entity name>,true,"username","password",headers";
Like above example you can replace your username & password in variables & pass it through service.
Thanks!
Hi,
For Chrome after version no.49, you can not solve the 'unauthorized' or 'same-origin-policy-in-chrome' problems by adding the command “–disable-web-security”, because the strict security restrictions of Chrome.
So, you can solve this problems by the following steps:
There is a blog writen by Chinese, or you can refer this link disable-same-origin-policy-in-chrome.
Enjoy it~
Excellent Post
Excellent post.. I got some confidence by seeing this post, that even me(with out knowledge in web technologies) can learn SAP UI5 front and back end development.
But I got struck at one point. I have followed same, but data is not being displayed initially when I ran the index.html as web app preview. I am getting page but data is not being fetch. When i try to create new employee, when I click on save, I am experiencing error.. Please help me out with the reasons for it, If any one could give me possible error reasons for data not being displayed in page...
Thank you.
Please open a question here and provide details.
Hi Jagadeesh,
Checkpoints:
1. Run your Odata Services on browser with URL "http://<host name>:<port no>/sap/opu/odata/sap/ZMM_EMP_SRV/<entity name>". If its showing data on browser it means Odata service is fine.
2. Check your code for Data binding in controller.js
3. Execute your project on Google Chrome & debug your code using F12..
Thanks!
Hi Experts,
I have one doubt. I am currently working on creation of new entries in a table.
The process showing above regarding creation is, we can create entries as single row of data at a time. Can we create bulk entries at a time? i.e i want to pass n number of rows at a single time instead of submitting every time. Can we pass set of rows as like internal table to Odata. Actually i want to add multiple line items, i am working on scheduling agreement VA31 custom app. I got struct at this point, don't know how to pass data as internal table to Odata. Please help me on this.
Unless you are asking for clarification/correction of some part of the Document, please create a new Discussion marked as a Question. The Comments section of a Blog (or Document) is not the right vehicle for asking questions as the results are not easily searchable. Once your issue is solved, a Discussion with the solution (and marked with Correct Answer) makes the results visible to others experiencing a similar problem. If a blog or document is related, put in a link. Read the Getting Started documents (link at the top right) including the Rules of Engagement.
NOTE: Getting the link is easy enough for both the author and Blog. Simply MouseOver the item, Right Click, and select Copy Shortcut. Paste it into your Discussion. You can also click on the url after pasting. Click on the A to expand the options and select T (on the right) to Auto-Title the url.
Thanks, Mike (Moderator)
SAP Technology RIG
Hi Experts,
In this example, Meeran used odata.request and passing some parameters(request uri,method,headers) etc.. But, i have seen a code used by my colleague as shown below. Could any one tell what are the differences between these two ? Is there any advantage if we use below code ? Which one is recommended way ?
var oResultModel = new sap.ui.model.odata.ODataModel("http:XXXXXXXXXXXXXX/sap/opu/odata/sap/ZMRS_UI5_PROJECT_UPDATE_SRV/", false);
oResultModel.create("/HeaderSet",requestData,{success: function(oData,oResponse){
sap.ui.commons.MessageBox.show("Selected Materials are Ordered Succussfully",
sap.ui.commons.MessageBox.Icon.SUCCESS,"Success",
[sap.ui.commons.MessageBox.Action.OK],
function(oEvent)
{
if(oEvent=="OK")
{
matController.refreshMatTable();
}
else
{
//
}
});
}, error: function(error){
var parser = new DOMParser();
var data = error.response.body;
var dom = parser.parseFromString(data, "text/xml");
messageDataLoop = dom.getElementsByTagName('message');
messageDataList =[];
alert(messageDataLoop[0].childNodes[0].nodeValue);
}, async: true});
}
Hi Mohamed
Really helpful post!! Thank you so much.
I have question, hope you could help. When I tried to write function for update in view controller, it showed "OData" is not defined, do you have any ideas about this issue?
I used SAP Web IDE but not eclipse.
As below is my code in view controller, hope it will not bother you too much.
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function(Controller) {
"use strict";
return Controller.extend("EMP_DATA.controller.View1", {
onInit : function () {
/**
* Get Model in Component.js
* Define and get View
* Set OData Model in view
*/
// ************* Code Start *************
var oModel = this.getOwnerComponent().getModel();
var oView = this.getView();
oView.setModel(oModel);
// ************* Code End *************
},
_getDialog : function (){
// Create Dialog Lazily
if (!this._oDialog){
// Create Dialog via fragment factory
this._oDialog = sap.ui.xmlfragment("EMP_DATA.view.UpdateDialog");
// Connect dialog to view
this.getView().addDependent(this._oDialog);
}
return this._oDialog;
},
ItemPress: function (evt){
// Open Dialog
this._getDialog().open();
// Get Value from table
var oSelectItem = evt.getParameter("listItem");
var sID = oSelectItem.getBindingContext().getProperty("EmpId");
var sName = oSelectItem.getBindingContext().getProperty("EmpName");
var sAddr = oSelectItem.getBindingContext().getProperty("EmpAdd");
var sRole = oSelectItem.getBindingContext().getProperty("EmpDes");
sap.ui.getCore().byId("Id").setValue(sID);
sap.ui.getCore().byId("Name").setValue(sName);
sap.ui.getCore().byId("Address").setValue(sAddr);
sap.ui.getCore().byId("Role").setValue(sRole);
sap.ui.getCore().byId("Id").setEnabled(false);
// Warning Message
// jQuery.sap.require("sap.m.MessageBox");
// sap.m.MessageBox.alert("Trigger On Press Event!!");
},
Update: function (){
var oEntry = {};
oEntry.EmpId = sap.ui.getCore().byId("Id").getValue();
oEntry.EmpName = sap.ui.getCore().byId("Name").getValue();
oEntry.EmpAdd = sap.ui.getCore().byId("Address").getValue();
oEntry.EmpDes = sap.ui.getCore().byId("Role").getValue();
OData.request({
requestUrl : "/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet",
method : "GET",
headers : {
"X-Requested-With" : "XMLHttpRequest",
"Content-Type" : "application/atom+xml",
"DataServiceVersion" : "2.0",
"X-CSRF-Token" : "Fetch"
}
},
function(data, response){
header_xcsrf_token = response.headers['x-csrf-token'];
var oHeaders = {
"x-csrf-token" : header_xcsrf_token,
'Accept' : 'application/json',
};
OData.request({
requestUrl : "/sap/opu/odata/sap/ZMM_EMP_SRV/EmployeeSet('"+oEntry.EmpId+"')",
method : "PUT",
header : oHeaders,
data: oEntry
},
function(data, request){
alert("Update Success");
location.reload(true);
}, function (err){
alert("Update Failed");
});
}, function (err){
var request = err.request;
var response = err.response;
alert("Error in Get -- Request" + request + "Response" + response);
});
}
});
});
Scott,
Unless you are asking for clarification/correction of some part of the Blog, please create a new Question. The Comments section of a Blog is not the right vehicle for asking questions as the results are not easily searchable. Once your issue is solved, a Discussion with the solution (and marked with Correct Answer) makes the results visible to others experiencing a similar problem. If a blog is related, put in a link. Read the Getting Started documents including the Rules of Engagement.
NOTE: Getting the link is easy enough for both the author and Blog. Simply MouseOver the item, Right Click, and select Copy Shortcut. Paste it into your Question.
Thanks, Mike (Moderator)
SAP Technology RIG
Hi Mike,
This link has all the steps, all the application is developed and completed? How to create TITLE and add to the group? Information needed for Target mapping and to add new tile.
Hi Scott, Do you solve it? I am geting the same error
Hi Rubens,
Sorry for the late reply. The issue has been solved. Because the above mentioned OData Object is outdated. You could refer below SAP help for the detail information about how to make CRUD in SAP UI5.
https://help.sap.com/saphelp_nw74/helpdata/en/91/f2a6ac6f4d1014b6dd926db0e91070/frameset.htm
I have the same question. There is no class named OData in the API https://sapui5.hana.ondemand.com/#docs/api/symbols/sap.ui.html . Also nowhere in the code a variable OData is defined. What is this object?
Hi ,
this is very good document or beginners,
i have problem with creation of ui5 application in eclipse in this example
getControllerName : function() {
return "empcrud.EmpDetails";
},
createcontent : function(oController){
var oPage = new sap.m.page({
title: "Employee Details",
});
//Table or dashboard to show the employee data
var otable = new sap.m.table({
id:"employees",
itempress : [ oController.itempress,oController ],
columns: [
new sap.m.column({
width: "1em",
header: new sap.m.label({
text: "Emp ID" }) }),
new sap.m.column({
width: "1em",
header: new sap.m.label({
text: "Name" }) }),
new sap.m.column({
width: "1em",
header: new sap.m.label({
text: "Address" }) }),
new sap.m.column({
width: "1em",
header: new sap.m.label({
text: "Designation"
})
})
]
});
after writing the above code i am not getting any out put just showing the bluecrystel screen in out put i am new to ui5 . please give me way how to do .
You've decalred a var for oPage and oTable but you're not returning anything. You need to add oTable to oPage then return oPage at the end of your code.
oPage.addContent(oTable);
return oPage;
Hi Mohamed Meeran ,
Thank you for the detailed blog. It helped me to understand the concepts very clearly. When I am following steps to recreate the scenario. I am getting error while executing on Chrome browser. It showing the error message "Response for preflight has invalid HTTP status code 401" , It seems to be authorization error. Any idea how I can fix it?
Please check the error log on the web page.
Thanks,
Harish
I am beginner in this FIORI stuff..
Followed all the steps from this blog and uloaded in FIORI ecc system , I see BSP is created there..
Just wondering how to add this app in FIORI launch pad (Creating Tile and Target mapping etc), can some expert provide me these steps?
Hi Harish Munigala,
You can disable web security in chrome browser by running the follow in windows run command
chrome.exe --user-data-dir="c:/temp/chromedev" --disable-web-security
Regards,
Rafael
Hi Rafael,
I have faced the same problem what @Harish Munigala was faced. I followed the above steps what you suggested(chrome.exe –user-data-dir=”c:/temp/chromedev” –disable-web-security)..now i am getting the expected output.
Thank you so much for your post.
Regards,
Ramesh.
If this still doesn’t work then you can upload your web application and test it there. Follow this blog to upload your application.
https://pravin517.wordpress.com/2018/02/06/deploy-a-ui5-application-to-as-abap-using-report-ui5-ui5_repository_load/
Following shows, it doesn’t execute in the ADT but after upload the application runs using the BSP application.
Dear Former Member
Excellent Post.
i was following each and every step.
i got struct in EmployeeSet URL ,when i execute the url im SAP Gateway Client i am getting the below response , please help me to solve.
Check your implementation, for this blog, check if your function modules work and you can debug and see if it stops at your break-point.
Hi,
Thanks for the above exercise.
I am getting error in GET method.
message: "Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://<host name>:<port no>/sap/opu/odata/sap/Z_DEMO_CRUD_SRV/$metadata'.
Can you suggest me for this?