-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do not serialize DTO fields with empty or null objects and arrays #13515
Conversation
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
core/che-core-api-dto/src/main/java/org/eclipse/che/dto/server/NullOrEmptyMapAdapter.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, I'm OK with these changes. Let's run ci-test
to check if it does not break current functionalities
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
ci-test |
Results of automated E2E tests of Eclipse Che Multiuser on OCP: |
@Override | ||
public JsonElement serialize(List<?> src, Type typeOfSrc, JsonSerializationContext context) { | ||
if (src == null || src.isEmpty()) { | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is correct. Isn't there a semantic difference between null
and empty list? While it may solve an issue for stuff within the devfile, I'm not sure it won't cause trouble for other types of entities...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to our DTOs impl - there is not any semantic difference between null or empty list/map. I mean null and empty collection/map can be used only as initialized collection/map (not null) after parsing.
From Che Server and GWT (client impls) perspective, nothing is changed.
For CLI that we used to use nothing is changed as well since typescript DTO generator initializes null fields.
The things that may be affected:
- UD: it uses received JSON directly via interface without using DTO impls, and null collections/maps are not initialized. So, code like
workspace.devfile.properties["persistVolumes"] = false
may cause a failure, but I'm not sure. Thank @ashumilova, who agreed to check this and provide more info how it may affect UD; - Any other Che Server API client that relies on current DTO serialization style where all fields are set, even if they were not set initially;
I think we can stop serialization empty collections/maps if does not cause any ingressions.
What are the alternatives?:
- stop using the same DTO object for all kind of components types and have like different classes for CheEditorComponentDto, ChePluginComponentDto, .... I do not have a clear picture of how it could be implemented;
- make ComponentDto - a special DTO that has untypical behavior for DTOs (null, empty collections/maps are not serialized). It looks safer against the implemented solution, but it makes our DTOs behavior variational from class to class, which is not a good thing IMHO.
- Do not use DTOs for devfile at all, and it's not clear what we can use instead, especially if we take into account that Devfile should be returned as part of WorkspaceDto.
I'm not sure it won't cause trouble for other types of entities...
@metlos Can you elaborate more about your thoughts about possible issues? Are you OK with this approach if everything works fine (ci-test result is 97+%, I do not expect issues in master)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the thing that changes for the clients is that where they saw empty collections coming from our API endpoints, they're going to start seeing nulls. So if anyone happens to rely on non-null arrays being present, they will be caught by surprise by this...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in case of objects, instead of properties with empty arrays, they won't see the properties at all anymore, so the clients will have to start dealing with undefined values where before they didn't have to. Am I right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm OK with making such change because we kinda need it, I just want to point out the consequences for the existing clients (e.g. che-theia and any other custom UI built on top of wsmaster API).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so the clients will have to start dealing with undefined values where before they didn't have to. Am I right?
Right!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mkuznyetsov and I found some generated typescript DTOs impl which look like initialize collections and maps
home/michael/IdeaProjects/che/dockerfiles/lib/src/api/dto/che-dto.ts
export module org.eclipse.che.api.workspace.shared.dto.devfile {
export class DevfileDtoImpl implements org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto {
components : Array<org.eclipse.che.api.workspace.shared.dto.devfile.ComponentDto>;
metadata : org.eclipse.che.api.workspace.shared.dto.devfile.MetadataDto;
projects : Array<org.eclipse.che.api.workspace.shared.dto.devfile.ProjectDto>;
apiVersion : string;
name : string;
attributes : Map<string,string>;
commands : Array<org.eclipse.che.api.workspace.shared.dto.devfile.DevfileCommandDto>;
__jsonObject : any;
constructor(__jsonObject?: any) {
this.__jsonObject = __jsonObject;
this.components = new Array<org.eclipse.che.api.workspace.shared.dto.devfile.ComponentDto>();
if (__jsonObject) {
if (__jsonObject.components) {
__jsonObject.components.forEach((item) => {
this.components.push(new org.eclipse.che.api.workspace.shared.dto.devfile.ComponentDtoImpl(item));
});
}
}
@mmorhun helps us to find that Theia works with DTOs without impls but via generated interfaces, but undefined/null should not happen here since all fields are marked as optional (?
) and strictNull
option is set on compiler, everyplace should contain the corresponding check before invocation of it. Terminology may be not right, but that's what I understand from converstation with @evidolob and @mmorhun
And Dashboard uses manually written interfaces and not all fields are marked as optional
https://github.com/eclipse/che/blob/master/dashboard/src/components/typings/che.d.ts#L340
Also, I do not know what is settings of compiler, if before invocation client should check field existence. @ashumilova @benoitf Can you take a look? For Dashboard it works in the same way as for Theia? If not, can we so them work in the same way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in dashboard it fails at runtime if try to access workspace.attributes.plugins
, when attributes is null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For typescript, consumers of the DTO should never see null values on collections/map
if field is mandatory then it needs to be empty
value, if the field is optional then it can be undefined
if it's not the case, then the TypeScript DTO needs to be enhanced.
in Ann's case, if attributes is optional field then all consumers have to check if it's defined or not but if attributes is mandatory then it should always return an empty value
ci-test |
Results of automated E2E tests of Eclipse Che Multiuser on OCP: |
Signed-off-by: Anna Shumilova <ashumilo@redhat.com>
ci-test |
Results of automated E2E tests of Eclipse Che Multiuser on OCP: |
ci-test |
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
Results of automated E2E tests of Eclipse Che Multiuser on OCP: |
ci-test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Platform team agreed that there is no necessity to serialize empty collections/fields.
The only bad side of not doing it: clients must check fields existence before using it.
And as Florent said
if field is mandatory then it needs to be empty value, if the field is optional then it can be undefined
In case of Che, we have some required collections/maps in our model which are used on REST API(machines in workspace config), but required collection or map means that at least one value MUST be present and empty collection/map is not valid.
If anybody has strong concerns against this PR then this solution can be rethinking again even after a merging.
But now it looks as the simplest solution for devfile issue and drawbacks looks not critical.
Results of automated E2E tests of Eclipse Che Multiuser on OCP: |
Selenium tests execution on Eclipse Che Multiuser on OCP (https://ci.codenvycorp.com/job/che-pullrequests-test-ocp/1861//Selenium_20tests_20report/) doesn't show any regression against this Pull Request. |
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
ci-test |
Results of automated E2E tests of Eclipse Che Multiuser on OCP: |
ci-test |
Results of automated E2E tests of Eclipse Che Multiuser on OCP: |
ci-test |
@@ -588,8 +588,8 @@ export class WorkspaceDetailsController { | |||
* Checks whether "plugins" are enabled in workspace config. | |||
*/ | |||
isPluginsEnabled(): boolean { | |||
let editor = this.workspaceDetails.config.attributes.editor || ''; | |||
let plugins = this.workspaceDetails.config.attributes.plugins || ''; | |||
let editor = this.workspaceDetails.config.attributes ? this.workspaceDetails.config.attributes.editor : ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't it be an empty array instead of '' ? (same for the next line)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that whole method may as well be removed since it's not used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed the method
Results of automated E2E tests of Eclipse Che Multiuser on OCP: |
Signed-off-by: Mykhailo Kuznietsov mkuznets@redhat.com
What does this PR do?
currently serialization of devfileDto creates problems, when null or empty fields with collection/map types get serialized, which results in invalid Devfile.
In PR, special adapters for GSON would exclude fields with null or empty collections/maps from serialization.
Also added additional Enviroment Variable that can be used to revert the old behaviour:
CHE_LEGACY__DTO__JSON__SERIALIZATION
(if true, empty and null collections and maps will be serialized)What issues does this PR fix or reference?