SAPUI5: How to set service url parameters in runtime? - sapui5

I have an OData service which is made in manifest.json
In some services I need to pass some url parameters like ?$expand=XYZ
SO the question is how can I set serviceUrlParams in the run time and not inside of the manifest.json while the OData model has been created by component class.

There seems to be a misunderstanding that parameters such as $expand belong to the serviceUrlParams. No, we need to distinguish between
Metadata URL parameters: metadataUrlParams in model definition. Those parameters will be only attached to the $metadata request which is at the model instantiation.
Service URL parameters: serviceUrlParams in model definition. Those parameters will be attached to all requests.
Data URL parameters:
parameters in binding definition (usually in the view) as mentioned here, or
urlParameters in model APIs such as read as mentioned here.
For $expand, data request parameter is what you have to define in each binding definition whereever it's needed. Then, the respective data will be loaded on-demand.
API Reference: ui5.sap.com/#/api/sap.ui.model.odata.v2.ODataModel
Documentation: ui5.sap.com/#/topic/6c47b2b39db9404582994070ec3d57a2

Hope this will helps.
var oModel = sap.ui.getCore().getModel();
oModel.read("/entityset?$expand=" + dynamicValue,mParameters);

for expand url data use the second parameter of the read function.
oDataModel.read("/yourEntitySet", {
success:jQuery.proxy(this._yourSuccessCallback, this),
urlParameters: {
"$expand": "YourExpandData"
},
error: jQuery.proxy(this._yourErrorCallback, this)
});

Related

Does JSONModel have $top and $skip like OData?

In my app I'm reading data from a JSON file and creating a model from it like this
var myModel = new sap.ui.model.JSONMOdel("pathToJson");
I have 300 values but I only want to read 50, is there a way to do that. I know I can use $top and $skip to select a specific set of values using OData. The API provides the function myModel.loadData() which contains a parameter oParameters but I don't know what I can pass in. Does anyone know if this possible?
The JSON model is a client-side model. This means that all the data is loaded at once with a single request. In the standard implementation, it has no methods for reading paged JSON contents (with top / skip or any other name you might give them).
You have said that you have a JSON file that you are loading. So such a paging does not even make sense from a technical point of view. This is because you cannot (easily) load a portion of a static file with client-only code (especially JSON, which is not valid if you are reading a fragment of it).
If you actually just want to store a segment of the file in the model, you can simply read the whole file with jQuery.ajax and then slice the array.
If you actually have a RESTful web service, then the paging mechanism should be part of this service (e..g it should have some path or query parameters for specifying the paging parameters). This service should return a valid JSON document for each call. On the client side, you can use such a service with the help of some functions (e.g. in the controller):
onInit: function () {
this.setModel(new JSONModel([])); // initially an emty array
},
//call this method when you want to read a page
onReadDataPage: function (iTop, iSkip) {
// use jQuery.ajax or jQuery.get to read a "page" of data; e.g.
jQuery.ajax({
url: "your service path",
data: {
top: iTop,
skip: iSkip || 0
},
success: this.onDataReceived.bind(this)
});
},
onDataReceived: function (aData) {
var oModel = this.getModel();
oModel.setData(oModel.getData().concat(aData);
}
If you want to use this in combination with a List with the growing feature, then you will need to create a new type of model - which is not trivial.

How to access invoke response object variable in following steps of assembly

the assembly of my API Connect API contains two invokes. The first is calling an internal routing API to get some routing information. The response of this routing API should not be passed to the second invoke.
If I do not configure a 'response object variable' in the invoke of the routing API, the original request body is overwritten and the second API gets the result from the routing API as request body. And if I specify a 'response object variable' in the routing invoke, I can not access the content (json) of this variable in the following steps.
How can I solve this issue?
Thx 4 help.
Rather than relying on reading the request object, you can read from your configured 'response object variable' later on in the flow. For instance, if your first invoke has a response object variable set to 'resp1', you can access the JSON payload using '$(resp1.body)' later on in the flow. Using this technique will allow you to store the response of each invoke in a separate object, avoiding the overwriting issue. These response object variables can be read just like any other context variable in the flow.
For more info, check out these links in the Knowledge Center:
Invoke Policy: https://www.ibm.com/support/knowledgecenter/en/SSMNED_5.0.0/com.ibm.apic.toolkit.doc/rapim_ref_ootb_policyinvoke.html
Context Variables:
https://www.ibm.com/support/knowledgecenter/SSMNED_5.0.0/com.ibm.apic.toolkit.doc/capim_context_references.html
I don't understand this part:
[...] "And if I specify a 'response object variable' in the routing
invoke, I can not access the content (json) of this variable in the
following steps." [...]
Why can't you access the content of this variable in the following steps?
Save copy of the request...
... that you received. What I'd do is always save a copy of the data received in the invoke to a processed variable instead of the (raw) original request.
In your GatewayScript try something like this:
let objRequest = apim.getvariable("request");
let body = null;
Here I recommend you to change the body (if json) to a standard js object
if(objRequest && objRequest.hasOwnProperty("body")){
try{
body = JSON.parse(objRequest.body);
}catch(e){
body = objRequest.body;
}
}
Remember to stringify the complete object before saving it as global variable. Is the only way to store it (because you can only store a string value in this kind of variables)
apim.setvariable("objRequest", JSON.stringify(objRequest));
Retrieve copy of the request...
...that you have saved in global variables you can get it from any other GatewayScript that you want this way:
let objRequest = JSON.parse(apim.getvariable("objRequest"));
Be careful not to assign an existent name to the apim.setvariable(name, value) because if you use "request" as name instead of "objRequest" (or other), you'll be replacing the original request element, and we don't want that to happen.
If you need to set or retrieve the status.code...
...you can do it with:
let statusCode = objRequest.body.status.code;

UI5 - OData (Response) Object Normalization

I'm looking for a method in the library to convert an OData response object into a normalized js object that can be sent into another ODataModel.create function. An OData "object" would be an OData REST response containing 'd', the '__meta', the 'results', etc.
I have a working solution with custom methods in a Utilities module but I'm not too sure about its resilience to all possible OData rules.
It isn't necessary to have the d, __meta and results section in a valid OData body:
The d potion is optional. You may also just form your body as a regular object such as:
{
Id: 12345,
Name: 'This is a valid OData body'
}
The __metadata section is optional as well and may be left out.
The results section is something you will receive when you query an Entity Set. If you query a single Entity (by providing its key), this section is left out as there will only be one result. You can't use the results section when you want to submit entities to the OData service, as every submission is supposed to happen in a separate operations.
With that, your normalisation/processing code could be very simple and look like:
jQuery.each(odata.results, function(idx, value) {
var body = value.d ? value.d : value;
delete body.__metadata;
// Do something with the body, e.g.:
ODataModel.create("/AwesomeEntity", body);
});
I hope this makes life easier? Full OData v2 JSON specs are available here:
http://www.odata.org/documentation/odata-version-2-0/json-format/

How to get the URI of a resource in Grails?

A very basic question. I want to provide URIs for some objects in my application. For example, a resource is available at:
http://localhost:8080/myapp/user/1
However, I'd like to serialize such a User object. This serialization should contain the public URI of the object itself. So for example, the model has a new method serializeToSomething, which would serialize:
id: 1
username: JohnDoe
email: johndoe#example.com
publicURI: http://localhost:8080/myapp/user/1
How can I let the model instance know of its URL?
Some notes:
This has to happen within the scope of the model, controller or service, and not within the view. Also I don't want to hardcode this.
See related question Can I use grails tag outside of GSP?
Basically you can use g.createLink in a controller or service, and it will return a string. So you can do something like:
def uri = g.createLink(controller: 'user', action: 'show', id: user.id, absolute: true)
Personally I ended up serializing 3 things: controller name, action name (typically "show") and id. Then I used these three in g.createLink when displaying deserialized objects in a View.
Sure, this won't work if you need deserialized object for external usage.
You can get the url in a controller using
request.forwardURI
A similar question has been asked before

Zend framework routing params

I have several routes defined in my application.
When route A is matched and I assemble an URL using route B without resetting, it does not include the current request parameters.
Is there an easy way to include all the request parameters when assembling an URL via a different route than the current route?
I did have a look at Zend_Controller_Router_Rewrite->useRequestParametersAsGlobal, but this will (obviously) also include the request parameters when reset = true
You could try the following.
$oldParams = $this->_getAllParamas();
unset($oldParams['module']);
unset($oldParams['controller']);
unset($oldParams['action']);
Pass
array_merge(array('new'=>'param'),$oldParams)
to your URL view helper.