Skip to content
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

Normalize Slack form element presentational data | Attempt 2 #258

Merged
merged 2 commits into from
Dec 8, 2021

Conversation

omotnyk
Copy link
Contributor

@omotnyk omotnyk commented Dec 7, 2021

Same as #256 but fixed stackoverflow error during normalization caused by cyclic constructor calls in with methods.

@omotnyk omotnyk force-pushed the normalize_data_before_validation branch from f86d507 to e923f50 Compare December 7, 2021 19:24
Comment on lines +31 to +36
return SlackFormTextElement.builder()
.from(element)
.setPlaceholder(normalizePlaceholder(element))
.setLabel(normalizeLabel(element))
.setHint(normalizeHint(element))
.build();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced with calls with builder here.

Comment on lines +45 to +50
return SlackFormTextareaElement.builder()
.from(element)
.setPlaceholder(normalizePlaceholder(element))
.setLabel(normalizeLabel(element))
.setHint(normalizeHint(element))
.build();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced with calls with builder here.

Comment on lines +60 to +66
return SlackFormSelectElement.builder()
.from(element)
.setPlaceholder(normalizePlaceholder(element))
.setLabel(normalizeLabel(element))
.setOptionGroups(normalizeOptionGroups(element))
.setOptions(normalizeOptions(element))
.build();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced with calls with builder here.

Comment on lines +56 to +66
if (shouldNormalizePlaceholder(element)
|| shouldNormalizeLabel(element, SlackDialogFormElementLengthLimits.MAX_LABEL_LENGTH)
|| shouldNormalize(element.getOptionGroups(), SlackDialogFormElementLengthLimits.MAX_OPTION_GROUPS_NUMBER)
|| shouldNormalizeOptions(element)) {
return SlackFormSelectElement.builder()
.from(element)
.setPlaceholder(normalizePlaceholder(element))
.setLabel(normalizeLabel(element))
.setOptionGroups(normalizeOptionGroups(element))
.setOptions(normalizeOptions(element))
.build();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll describe the stack overflow problem with an example. Let's say we have the old code here:

    if (shouldNormalizePlaceholder(element)
        || shouldNormalizeLabel(element, SlackDialogFormElementLengthLimits.MAX_LABEL_LENGTH)
        || shouldNormalize(element.getHint(), SlackDialogFormElementLengthLimits.MAX_HINT_LENGTH)) {
      return SlackFormTextElement.copyOf(element)
          .withPlaceholder(normalizePlaceholder(element))
          .withLabel(normalizeLabel(element))
          .withHint(normalizeHint(element));
    }
    return element;

What we do here is define whether we should normalize any data first and then normalize it. The problem is actually obvious but still tricky. Let's say we have a very long label that should be normalized. In this case, when SlackFormSelectElement is created we do next:

  1. Check if we should normalize any field.
  2. Determine that we should normalize some fields(label).
  3. Start normalization process:
    1. Normalize placeholer and then call withPlaceholder.
    2. Normalize label and then call withLabel.
    3. Normalize the rest.
    4. Build the final normalized object.

The flow I described above is what I think is happening. What was actually happening is we were entering an endless loop upon calling withPlaceholder because unlike builder, this method creates the actual SlackFormSelectElement so it calls method annotated with @Value.Check, which then initiates the normalization process once again. SInce we didn't normalize the label yet, we determine that label still has to be normalized and run SlackFormTextElement.copyOf(element).withPlaceholder(normalizePlaceholder(element)).withLabel(normalizeLabel(element)) once again, which results in doing this again, and then again, and again.

This issue wasn't caught at first because it depends on the order of the checks and normalization as well as on the data to be normalized. If we place withLabel before withPlaceholder and try to build the object with a long label, everything works fine because on the call to withLabel method we have a fully normalized object that passes all the checks.

Copy link
Contributor

@zmarushchak-hs zmarushchak-hs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants