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

Add capacity for ReflectionToStringBuilder to include methods annotated with @ToStringInclude #1082

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

shashankrnr32
Copy link

@shashankrnr32 shashankrnr32 commented Jul 20, 2023

Note: Please feel free to close this PR if this was previously discussed before and was decided not to be added to this implementation.

Currently, ReflectionToStringBuilder allows users to exclude fields from the toString output by adding an annotation @ToStringExclude to the field but there is no support to include methods declared in the class to be included in the toString output.

This PR introduces a new annotation @ToStringInclude(String) that can be added to the methods of a class with which, the methods in the toString output.

Some of the points which can be considered

  1. Add this implementation to a completely different class (extending ReflectionToStringBuilder) instead of modifying the current implementation
  2. Wrap this inside a flag, say allowReflectingMethods before going into this added implementation.

@codecov-commenter
Copy link

Codecov Report

Merging #1082 (9b44cf0) into master (60b55f2) will decrease coverage by 0.01%.
The diff coverage is 78.94%.

@@             Coverage Diff              @@
##             master    #1082      +/-   ##
============================================
- Coverage     92.08%   92.08%   -0.01%     
- Complexity     7501     7508       +7     
============================================
  Files           195      195              
  Lines         15720    15738      +18     
  Branches       2897     2900       +3     
============================================
+ Hits          14476    14492      +16     
- Misses          670      671       +1     
- Partials        574      575       +1     
Impacted Files Coverage Δ
...a/org/apache/commons/lang3/builder/Reflection.java 28.57% <33.33%> (+3.57%) ⬆️
...mmons/lang3/builder/ReflectionToStringBuilder.java 91.22% <87.50%> (-0.70%) ⬇️

... and 1 file with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@garydgregory
Copy link
Member

garydgregory commented Jul 27, 2023

All fileds are included by default, so why do we need to specify which ones to include?

@shashankrnr32
Copy link
Author

shashankrnr32 commented Jul 28, 2023

Yes. But the methods declared in a class are not included in the toString output. Lets say I want to exclude a field in the output and include a modified value (masked, abbreviated) that is generated by a method, we can include with such a feature.

Surely we can rename the annotation from @ToStringInclude to something like @ToStringMethodInclude?

@shashankrnr32
Copy link
Author

Adding a small example for more clarity. In the below example, lets say the usecase is to print "******" in place of the actual username (to mask the personally identifable information), this will help include the outputs of the methods by calling reflection invoke on the methods that are annotated with @ToStringInclude

package org.apache.commons.lang3.builder;

import org.apache.commons.lang3.StringUtils;

class TestFixture {
    @ToStringExclude
    private String username;

    @ToStringExclude
    private String phoneNumber;

    @ToStringInclude
    private String toStringUsername() {
        return StringUtils.repeat("*", StringUtils.length(username));
    }

    @ToStringInclude
    private String toStringPhoneNumber() {
        return StringUtils.repeat("*", StringUtils.length(phoneNumber));
    }

    @Override
    public String toString() {
        return new ReflectionToStringBuilder(this).build();
    }
}

@garydgregory
Copy link
Member

Note: Don't use code like this example in production, you're revealing the length of secrets. This might not be harmful in itself, but, combined with other leaks, could prove fatal. Perhaps this a good enough reason to avoid providing a potential foot gun like this one.

@shashankrnr32
Copy link
Author

shashankrnr32 commented Jul 29, 2023

Agreed. Just a crude example to understand the use case. Couple of other uses I can think of here

  1. A method that calculates something based on the values present in the class which needs to be added to the toString output
  2. Inferred attributes
  3. Masking only certain characters when the entire String masking is not required.
  4. A method that's annotated with @JsonProperty (Jackson) which will get serialized as JSON but is not printed in toString output

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.

3 participants