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

Refactor ConversionService to remove mutable operations from ConversionService.SHARED #8156

Merged
merged 5 commits into from
Oct 28, 2022

Conversation

dstepanov
Copy link
Contributor

@dstepanov dstepanov commented Oct 13, 2022

Fixes #7657

Hopefully replaced all the possible usages of ConversionService.SHARED.

Some use cases cannot work after this change:
The detached request body is being converted:

        when:
        def request = HttpRequest.POST('/', JsonObject.createObjectNode([:]))

        then:
        request.getBody(String).get() != '{}'

Not sure if it's something that is even make sense, the fix now it to use this:

        when:
        request.setConversionService(conversionService)

        then:
        request.getBody(String).get() == '{}'

@dstepanov dstepanov marked this pull request as draft October 13, 2022 14:35
@dstepanov dstepanov marked this pull request as ready for review October 17, 2022 07:43
@yawkat
Copy link
Member

yawkat commented Oct 18, 2022

fyi this will conflict with #8100, I made a similar ConversionService change in DefaultHttpClient there

@graemerocher
Copy link
Contributor

@dstepanov can you resolve the conflicts

@dstepanov
Copy link
Contributor Author

I think we can remove concurrent maps in the default implementation. I have measured it can get us 50% more throughput. The idea would be only to allow adding a new converter via TypeConverterRegistrar.

* @param <S> The source generic type
* @param <T> The target generic type
*/
<S, T> void addConverter(@NonNull Class<S> sourceType, @NonNull Class<T> targetType, @NonNull Function<S, T> typeConverter);
Copy link
Contributor

Choose a reason for hiding this comment

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

Return MutableConversionService to make the API fluent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you want to have it generic like it was before?

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense

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'm looking at it again, and I don't like to have it in this way. There are zero usages of chaining in the current codebase. The registration API defines this signature: void register(ConversionService<?> conversionService) which prevents to do the chaining. IMHO the generic parameter only makes the code ugly, and the chaining is not very important in this case. I would prefer not to have it. WDYT @micronaut-projects/core-developers ?

Copy link
Contributor

Choose a reason for hiding this comment

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

It is probably fine without it but the generic argument remains a potentially large source of breaking changes

* @author Graeme Rocher
* @since 1.0
*/
public interface ConversionService<Impl extends ConversionService> {
public interface ConversionService {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm concerned about the removal of the generic type argument here as it likely to break a lot of end user code. Is this a necessary change? What is the justification?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was only used for the mutable add methods, now those methods are gone so the generic parameter is unused.

Copy link
Contributor

Choose a reason for hiding this comment

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

It does mean though that any place a user injected ConversionService<?> will break which might be a significant breaking change. Thoughts @sdelamo ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Users might need to modify their code anyway if relying on the shared conversion service.

Copy link
Member

Choose a reason for hiding this comment

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

Our docs use ConversionService<?> in examples. Still I never liked that generic type argument, so my +1 to remove it if it's not needed

@sonarqubecloud
Copy link

SonarCloud Quality Gate failed.    Quality Gate failed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 60 Code Smells

77.1% 77.1% Coverage
0.0% 0.0% Duplication

@graemerocher graemerocher added the type: breaking Introduces a breaking change label Oct 28, 2022
@graemerocher graemerocher added this to the 4.0.0 milestone Oct 28, 2022
@graemerocher graemerocher added the type: improvement A minor improvement to an existing feature label Oct 28, 2022
@graemerocher graemerocher merged commit 8b2d53b into 4.0.x Oct 28, 2022
@graemerocher graemerocher deleted the conv branch October 28, 2022 09:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: breaking Introduces a breaking change type: improvement A minor improvement to an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Do not allow registering shared state type convertor into the shared instance ConversionService.DEFAULT
4 participants