cancel
Showing results for 
Search instead for 
Did you mean: 

How to access a BTP destination within SAPUI5 when executing AJAX call

renejurmann
Participant
0 Kudos
8,092

Hi experts,

we try to create a SAPUI5 app which should access a backend service on clicking a specific button.

The SAPUI5 app is created using the BTP managed app router. Basically it is consuming a OData service to display a worklist. For the OData service we have created a destination in BTP cockpit and everything works fine.

But now we try to implement another button which should call another backend service using jQuery AJAX. As this service requires authentication (and the URL differs depending on DEV, TEST and PROD) we created a destination for this as well. This destination looks as follows in BTP cockpit:

As our SAPUI5 is uses the managed app router we added an according route to the xs-app.json:

{<br>    "routes": [<br>		...<br>        {<br>            "source": "^/srv/(.*)$",<br>            "target": "/v1/$1",<br>            "destination": "XXXXXXXX-srv",<br>            "authenticationType": "xsuaa",<br>            "csrfProtection": false<br>        },<br>		...<br>    ]<br>}

Within the SAPUI5 controller we have now a function defined which is triggered on a button press:

onButtonPress: function (oEvent) {<br>	var oData = {};<br>	jQuery.ajax({<br>		type: "POST",<br>		url: "/srv/createPdf",<br>		dataType: "json",<br>		body: oData,<br>		headers: {<br>			"Content-Type": "application/json",<br>		},<br>		success: function (oReturn, textStatus, jqXHR) {<br>			//do something<br>		},<br>		error: function (error) {<br>			console.error(error);<br>		}<br>	});<br>}

Unfortunately, when we try to execute this we see a 403 in the developer tools. Then we analyzed the URLs in the network tab within the browser developer tools a bit more. Here we found some interesting difference between the URL structure used for calling the OData service and for the AJAX request.

OData URL:

https://<btp-tenant>.launchpad.cfapps.<btp-region>.hana.ondemand.com/<managed-app-router-id>.<html5-...
  

AJAX Call URL:

https://<btp-tenant>.launchpad.cfapps.<btp-region>.hana.ondemand.com/<obackend-service-url>;

The AJAX Call misses the app router path including the html 5 ID. When we hard code this (by copying the path information from the OData call) we can access the backend service successfully. But we must not hard code this as the managed app router ID differs on DEV, TEST and PROD and the version is recalculated with every deploy.

So, the question is how can we access this information within the SAPUI5 controller to have the AJAX call working. Or what do we need to setup to access a destination for a jQuery AJAX call?

regards

René

Accepted Solutions (1)

Accepted Solutions (1)

gregorw
SAP Mentor
SAP Mentor

You have to use a relative path srv/ or ./srv/. And if you run in Portal or Launchpad check out Calling Service using AJAX in Fiori Elements Extension doesn't work in Launchpad.

renejurmann
Participant

Hi Gregor,

thanks for the link to the other question. With this information I rebuild the logic within the controller as below. Now everything is working fine.

onButtonPress: function (oEvent) {
var oData = {<some data>};
var sModelUrlPath = this.getOwnerComponent().getManifestEntry("/sap.app/dataSources/mainService/uri");
var sModelServiceUrl = this.getView().getModel().sServiceUrl;
var sAppRouterUrl = sModelServiceUrl.substr(0, sModelServiceUrl.length - sModelUrlPath.length);
jQuery.ajax({
type: "POST",
url: sAppRouterUrl + "/srv/createPdf",
dataType: "json",
body: oData,
headers: {
"Content-Type": "application/json",
},
success: function (oReturn, textStatus, jqXHR) {
//do something
},
error: function (error) {
console.error(error);
}
});
}

regards

René

Answers (4)

Answers (4)

rolfhoven
Explorer
0 Kudos

Nope:

Why is it working from BAS and not from Cloud Foundry ?

matthias_kainz
Explorer
0 Kudos

Hello,

did you solve the problem?

Matthias

rolfhoven
Explorer
0 Kudos

My controller for view1 looks like this: ( and works perfect from BAS, but not from Cloud Foundry )

return Controller.extend("yr2.yr2.controller.View1", { onInit: function () {
var that = this;
var sModelUrlPath = this.getOwnerComponent().getManifestEntry("/sap.app/dataSources/mainService/uri");
//var sModelServiceUrl = this.getView().getModel().sServiceUrl; //var sAppRouterUrl = sModelServiceUrl.substr(0, sModelServiceUrl.length - sModelUrlPath.length);
//Mandal //var url1 = 'https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=58.02682&lon=7.45347'; var url1 = '/' + sModelUrlPath + '?lat=58.02682&lon=7.45347';
var aData = jQuery.ajax({ type: "GET", contentType: "application/json", url: url1, dataType: "json", crossDomain: true, async: true, headers: { accept: 'application/json', contentType: 'application/json', cache: false, 'X-CSRF-Token': 'Fetch' }, success: function(data, textStatus, jqXHR) {
renejurmann
Participant
0 Kudos

As you try to call this in the onInit method of the controller, the model is not yet linked with the view. So, this.getView().getModel() will return "undefined" and you get an exception trying to read the sServiceUrl

In order to get the model you would need to change the code as follows:

this.getOwnerComponent().getModel().sServiceUrl

rolfhoven
Explorer
0 Kudos

The name is empty:

renejurmann
Participant
0 Kudos

When do you try to connect to the model? If you do this in the onInit method, the model is probably not yet linked with the view. (See Assigning the Model to the UI)

You could try to get the URL as follows:

this.getOwnerComponent().getModel().sServiceUrl

rolfhoven
Explorer
0 Kudos

I have the same problem, calling a "free weather service" API: Weather for Mandal

My "Freestyle Tile" works from BAS, but not from Cloud Foundry Launchpad.I added these 2 lines to my controller:

var sModelUrlPath = this.getOwnerComponent().getManifestEntry("/sap.app/dataSources/mainService/uri"); MessageBox.show(sModelUrlPath);

Giving this result:

/weatherapi/locationforecast/2.0/compact/ "Launchpad

/weatherapi/locationforecast/2.0/compact/ "Standalone

This line is not working:

var sModelServiceUrl = this.getView().getModel().sServiceUrl;

My destination looks like this:

Please suggest what is wrong ?

Best regards,

Rolf

renejurmann
Participant
0 Kudos

Hi Rolf,

your data source "mainService" should be linked to a model in your manifest.json. What name has this model - is it empty (just "") or has it a name?

"sap.ui5": {
"models": {
"": {
"dataSource": "mainService",
"preload": true,
"settings": {}
}
}
}

If the name of the model is not empty you would need to call the model like this:

var sModelServiceUrl = this.getView().getModel("<name>").sServiceUrl;