Openui5: sap-language parameter is not added to sap.ui.model.odata.v2.ODataModel if model is extended

Created on 12 Jan 2021  路  27Comments  路  Source: SAP/openui5

OpenUI5 version: 1.85.0

Language url parameter is not added to the ODataModel if model is extended.
Steps to reproduce the problem:

  1. Create custom ODataModel by extending sap.ui.model.odata.v2.ODataModel (I believe that same issue appears for v4)
  2. Add model to the manifest.json

What is the expected result?
sap-language url parameter should be added

What happens instead?
sap-language url parameter is not added

Any other information? (attach screenshot if possible)
Reason for it is in sap.ui.core.Component line: 1545
image
sap-language should be added if the model is instance of ODataModel, however right now class check is strictly set to sap.ui.model.odata.v2.ODataModel and sap.ui.model.odata.v4.ODataModel models.

author action consulting wontfix

All 27 comments

Hi @iljapostnovs,

Thank you for sharing this finding. I've created an internal incident 2180022569. The status of the issue will be updated here in GitHub.

All the best,
Florian

Hi @iljapostnovs,
I had a look on the respective code lines and it's not so easy how it looks like at the first glance.
At this point, the models are not yet generated. So, no model instance is available to perform a "isA" to check for inheritance.
Our recommendation is to override your component implementation and add the needed code.
Best Regards,
Florian

Hi,

_createManifestModelConfigurations method is private, according to OOP principles you can't override private methods.

Parameters for the model could be set after model creation, it's line 2884 in sap.ui.core.Component:
image

Or actually it's not so easy, because metadata might be requested without language parameter anyway.

In this case the model class can be requested using sap.ui.requireSync right before setting the parameters, and then you can use isA. It looks like drawback because require should be async, but taking in mind requireSync is used anyway in _createManifestModels, it will impact nothing.

Hi,

_createManifestModelConfigurations method is private, according to OOP principles you can't override private methods.

Parameters for the model could be set after model creation, it's line 2884 in sap.ui.core.Component:
image

Hi @iljapostnovs, yes the method is private. But as of now, this would be the only option for you to achieve your scenario.

Or actually it's not so easy, because metadata might be requested without language parameter anyway.

In this case the model class can be requested using sap.ui.requireSync right before setting the parameters, and then you can use isA. It looks like drawback because require should be async, but taking in mind requireSync is used anyway in _createManifestModels, it will impact nothing.

Thanks a lot for your inputs. We'll discuss your points and report the outcome here 馃憤馃徑

Hi,
_createManifestModelConfigurations method is private, according to OOP principles you can't override private methods.
Parameters for the model could be set after model creation, it's line 2884 in sap.ui.core.Component:
image

Hi @iljapostnovs, yes the method is private. But as of now, this would be the only option for you to achieve your scenario.

Thanks, but I figured out another temporary way out:

sap.ui.define([
    "sap/ui/model/odata/v2/ODataModel"
], function (ODataModel) {
    "use strict";

    return ODataModel.extend("com.test.ODataModel", {
        constructor: function() {
            this._addSAPLanguageToUrlParameters(arguments);

            return ODataModel.prototype.constructor.apply(this, arguments);
        },

        _addSAPLanguageToUrlParameters: function(aArgs) {
            const oConfig = sap.ui.getCore().getConfiguration();
            const mSettings = aArgs[1];
            if (mSettings && typeof mSettings === "object") {
                mSettings.metadataUrlParams = mSettings.metadataUrlParams || {
                    "sap-language": oConfig.getSAPParam("sap-language")
                };
            }
        }
    });
});

Waiting forward getting rid of this :)

Hi @iljapostnovs,
thanks a lot for providing the code snippet also for other developers. We had a deeper look at your requirement and we definitely prefer your solution.
Requiring the models in the component synchronously is not good because there are applications not using ODataModels at all.
While using the approach in your latest code snippet you'll be fine also for future releases.
Thanks a lot for opening this issue and don't hesitate to open further ones in future. We're looking forward to any feature request or idea by the community.
All the best and take care,
Florian

Hi @iljapostnovs,
thanks a lot for providing the code snippet also for other developers. We had a deeper look at your requirement and we definitely prefer your solution.
Requiring the models in the component synchronously is not good because there are applications not using ODataModels at all.
While using the approach in your latest code snippet you'll be fine also for future releases.
Thanks a lot for opening this issue and don't hesitate to open further ones in future. We're looking forward to any feature request or idea by the community.
All the best and take care,
Florian

Hi,
Fair.
I could propose to move language parameter logic from Component class to ODataModel class, I don't see why language parameter should be set only if you declared ODataModel in manifest :)

Actually I thought a bit about your answer and didn't get the problem.
Models are created using requireSync anyway in _createManifestModels method, which means that if you require the class earlier - it will change nothing.

Requiring the models in the component synchronously is not good because there are applications not using ODataModels at all.

That's of couse true, but I don't see how it is a problem.
Lets simulate some scenarios:
1) Class com.test.ODataModel is created, which extends sap.ui.model.v2.ODataModel.
com.test.ODataModel class is preloaded and .isA("sap.ui.model.v2.ODataModel") is used. It returns true, the parameters are added and earlier preloaded class is used later on in _createManifestModels method for creating the instance of the model.

2) Class com.test.JSONModel is created, which extends sap.ui.model.json.JSONModel.
com.test.JSONModel class is preloaded and .isA("sap.ui.model.v2.ODataModel") is used. It returns false, the parameters are not added and earlier preloaded class is used later on in _createManifestModels method for creating the instance of the model.

As far as I understood from your answer, the problem is that you need to require ODataModel in scenario 2, but according to .isA implementation that's not actually true:
image
.isA is not preloading the class which is used for checking.

Hi @iljapostnovs.

Models are created using requireSync anyway in _createManifestModels method, which means that if you require the class earlier - it will change nothing.

This is unfortunately not true. The point in time where the models now are required and loaded is guaranteed to have preloads the code already. For the earlier point in time where the model settings are prepared (incl. the injection of the sap-language code), this is not guaranteed and therefore sync XHRs could be created for individual files. The path on which models that are flagged with "preload:true" are loaded, explicitly checks whether the code is preloaded already and if not, postpones model creation.

.isA is not preloading the class which is used for checking.

This is correct (and the reason why we introduced .isA), but only for the target of the comparison. But the method can only be called on class metadata or on a class instance. Both require that the class has been required and executed beforehand. Therefore, the component still would have to require com.test.JSONModel early and due to the above timing issue, we have to avoid this.

We could optimise the check for some scenarios (mainly for apps that use a self-contained bundle): If the model implementation has already been preloaded, then we could require it and do the isA check instead of just comparing its name against a list of well known implementations. However, I don't think this would be a good solution as it would only work for certain deployments of an app whereas for others, the parameters would not be injected.

I could propose to move language parameter logic from Component class to ODataModel class, I don't see why language parameter should be set only if you declared ODataModel in manifest :)

That's the most appealing alternative from my POV. I think the reason why it originally wasn't done like that was that the models don't have access to some of the parameters (esp. cache tokens). The global settings like language and client however would be available to them.

for apps that use a self-contained bundle

Hi @codeworrior,
Thanks for explanation.
I would be more than happy to see the url parameter in ODataModel instead of Component :)
Should I create new issue for it?

I don't fully get the goal we are after here. The V4 OData model is already using "Accept-Language" header automatically. My understanding is that the sap-language URL parameter is most valuable when it comes to caching, and as @codeworrior said, "the models don't have access to some of the parameters (esp. cache tokens)". So what is the benefit of having sap-language URL w/o the others?

I don't fully get the goal we are after here. The V4 OData model is already using "Accept-Language" header automatically. My understanding is that the sap-language URL parameter is most valuable when it comes to caching, and as @codeworrior said, "the models don't have access to some of the parameters (esp. cache tokens)". So what is the benefit of having sap-language URL w/o the others?

Hi,
sap-language is valuable not only for caching.
Real life example:
1) Create com.test.ODataModel which extends sap.ui.model.odata.v2.ODataModel
2) Bind labels to ODataModel metadata labels.
3) You have e.g. German language in your Fiori Launchpad, but system language is EN. You will get english labels instead of german anyway, because sap-language parameter is added automatically only for sap.ui.model.odata.v2.ODataModel, for com.test.ODataModel it will not be added.

OK, I think I understand your scenario. As I said, this should not be an issue with v4.ODataModel because "Accept-Language" header is automatically set for both data and metadata. Just to clarify the scope of this issue...

OK, I think I understand your scenario. As I said, this should not be an issue with v4.ODataModel because "Accept-Language" header is automatically set for both data and metadata. Just to clarify the scope of this issue...

I didn't test this scenario for V4 ODataModel, so I hope that you are right :)

Looking at the code, I'd say that V2 is also using "Accept-Language" headers for both data and metadata. Can you please confirm this? Why doesn't this have the same effect as sap-language?

Looking at the code, I'd say that V2 is also using "Accept-Language" headers for both data and metadata. Can you please confirm this? Why doesn't this have the same effect as sap-language?

Hi,

Here is metadata request without sap-language parameter in LT language:
image
And here is english label:
image

Here is metadata request with sap-language parameter in LT language:
image
And here is lithuanian label:
image

So I guess at least v2 ODataModel is not using accept-language header.

Hello @iljapostnovs !

Thanks for this detailed analysis. When I speak of ODataModel, I refer to UI5's implementation. Your screenshot illustrates the presence of "Accept-Language" request headers. But I also understand that the server's response treats "sap-language" differently than "Accept-Language". That is not a question to UI5 in the 1st place. Which server implementation/framework are you using?

Best regards,
Thomas

Hello @iljapostnovs !

Thanks for this detailed analysis. When I speak of ODataModel, I refer to UI5's implementation. Your screenshot illustrates the presence of "Accept-Language" request headers. But I also understand that the server's response treats "sap-language" differently than "Accept-Language". That is not a question to UI5 in the 1st place. Which server implementation/framework are you using?

Best regards,
Thomas

I am using NetWeaver OData Service. I don't know which component exactly is responsible for OData implementation, but my guess would be that it is SAP_GWFND, release 750, SP-level 0008.
Indeed, the NW OData is not related to UI5, but adding sap-language url parameter to the request is. Taking in mind that parameter is added in the sap.ui.core.Component implementation, I hope that it makes sense to add it for all ODataModel (model extensions as well) instances, not only strictly for sap.ui.model.odata.v2.ODataModel models.

Hello @iljapostnovs !

Thanks for your input. I will discuss this internally (beginning of next week) and let you know here. Stay tuned!

Best regards,
Thomas

Hello @iljapostnovs !

I've got at least a preliminary answer: "Fix the server". I suggest you try and open a support ticket on SAP_GWFND asking why the "Accept-Language" request header does not have the desired effect. Then we will see if UI5 needs to change anything at all.

Best regards,
Thomas

Hello @iljapostnovs !

I've got at least a preliminary answer: "Fix the server". I suggest you try and open a support ticket on SAP_GWFND asking why the "Accept-Language" request header does not have the desired effect. Then we will see if UI5 needs to change anything at all.

Best regards,
Thomas

Hi,

I googled a bit about accept-language and seems that it works correctly.
https://help.sap.com/viewer/17ae0e97e0fc424a9c368f350c0ba6bd/2.10/en-US/65edb2db3a6b452a97633f0027bf0922.html

1) sap-language is checked
2) If no sap-language is provided, user language (SU01) is checked
3) If no user language detected, accept-language header is checked

In my case the default system language is EN, but users can login with different language.
If sap-language is not provided, language from SU01 is taken, and it is EN.
This basically means, that without sap-language URL parameter user will always get EN labels, no matter what language is used by Fiori Launchpad.

Is that a generic user you are using? Would it be an option to set the desired language also in SU01? But I get the point that Fiori Launchpad settings should win...

Is that a generic user you are using?

At least that's the case for my user in NW system I have.

Would it be an option to set the desired language also in SU01?

Technically yes, but I don't think that somebody will be happy to edit thousands of user languages. And again, that also basically means that metadata language will be strictly set to one language, which should not be the case.

But I get the point that Fiori Launchpad settings should win...

Precisely

Hello @iljapostnovs !

Could you please do us a favor and try your scenario with a different language, maybe "en" or "de" or "fr" or "es" or "it"? That might make a difference and would be interesting to know.

Best regards,
Thomas

Hello @iljapostnovs !

Could you please do us a favor and try your scenario with a different language, maybe "en" or "de" or "fr" or "es" or "it"? That might make a difference and would be interesting to know.

Best regards,
Thomas

Hi,

What exactly you want me to try out?
Change sap-language, accept-language or user language in SU01?

Was this page helpful?
0 / 5 - 0 ratings