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

Refine how resource classes with same components are merged #25489

Merged
merged 3 commits into from
Feb 2, 2023

Conversation

Postremus
Copy link
Member

@Postremus Postremus commented May 10, 2022

Fixes #25462

Resources classes where merged by using all components as map key. This leads to situations where the only differing property of a component may be its name. The name is for a DEFAULT_REGEX however not enough to be considered a different path itself.

The merge is now based on a custom (String) key, build on properties which should enforce uniqueness when needed: type, literal, and pattern.

@Postremus Postremus force-pushed the issues/25462 branch 2 times, most recently from ad348f1 to 23bf08e Compare May 10, 2022 20:12
@geoand
Copy link
Contributor

geoand commented May 11, 2022

Thanks for looking into this @Postremus!

While working on this, please make sure that the JAX-RS TCK is passing with this change

@Postremus
Copy link
Member Author

@geoand
Where are the tcks located for resteasy-reactive?
Is it this module? https://github.com/quarkusio/quarkus/tree/main/tcks/resteasy-reactive

@geoand
Copy link
Contributor

geoand commented May 11, 2022

Nope, it's this one: https://github.com/quarkusio/resteasy-reactive-testsuite.
Just run mvn install on that module once you've built your change in Quarkus.

@Postremus
Copy link
Member Author

@geoand
TCKs are passing.

@Postremus Postremus marked this pull request as ready for review May 11, 2022 20:16
@Postremus Postremus requested a review from geoand May 11, 2022 20:17
@quarkus-bot

This comment has been minimized.

@Postremus
Copy link
Member Author

Test failures do not look related. The kafka dev service container could not be started.

java.lang.RuntimeException: 
java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
	[error]: Build step io.quarkus.kafka.client.deployment.DevServicesKafkaProcessor#startKafkaDevService threw an exception: java.lang.RuntimeException: org.testcontainers.containers.ContainerLaunchException: Container startup failed

Copy link
Contributor

@geoand geoand left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@stuartwdouglas any objections?

Copy link
Contributor

@geoand geoand left a comment

Choose a reason for hiding this comment

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

Actually, looking at #25462 (comment), it seems like this was an opt-in feature of RESTEasy Classic.

So we should probably do the same here.

@Postremus
Copy link
Member Author

I don't see how resteasy.wider.request.matching is related to this issue.

This flag was first mentioned, as far as I found, in the migration guide for 3.0-beta-5 to 3.0-beta-6:
https://docs.jboss.org/resteasy/docs/3.0.6.Final/userguide/html/Migration_from_older_versions.html

[..] For example, resource classes are scanned for a best match, other are ignored in the match. [..] There is one config switch I added so that Resteasy will ignore the Spec defined class expression filtering step and instead match base on the full expressions of each JAX-RS method. resteasy.wider.request.matching. [..]

I found these integration tests in resteasy:

The test consisist of:

  • one resource class with path "/hello"
  • one resource class with path "{x:.*}"

In WiderMappingTest (resteasy.wider.request.matching=true), {x:.*} must match, while "/hello" must match in the negative test.

Also, as far as I can tell, the handling of the flag resteasy.wider.request.matching is done in ResourceMethodRegistry. In each method of this class, widerMatching is checked. if true, do operations on rootNode (all endpoints), otherwise operate on root (only resource classes).

This flag only changes the order of how resources with different paths are merged, but has no influence in how resources with the same paths are matched.

I therefore believe that this fix is still correct, and no config switch is needed. We merge resources with the same path (components) on class level. No change is done to the specific resource matching.

@Postremus
Copy link
Member Author

Postremus commented May 17, 2022

I am btw. happy to introduce a config switch for this @geoand , I just don't want to do anything based on false assumptions on how the old stack worked.

However, this change passes the tck, and the resource class merge is imo what users (i.e. me) expect to happen anyway.

Copy link
Member

@stuartwdouglas stuartwdouglas left a comment

Choose a reason for hiding this comment

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

I think this looks ok.

@Postremus Postremus requested a review from geoand May 19, 2022 04:28
@geoand
Copy link
Contributor

geoand commented May 19, 2022

@Postremus thanks for this.

Any chance you can do a small benchmark to see if this introduces any noticeable overhead?

@Postremus
Copy link
Member Author

yep, will prepare a test project and do a simple benchmark (e.g. look at either profiler data or check how long dev mode restarts take comperativly)

@geoand
Copy link
Contributor

geoand commented May 19, 2022

Thanks!

We also want to make sure throughput for simple hello-world style rest calls is not affected

Copy link
Member

@gsmet gsmet left a comment

Choose a reason for hiding this comment

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

@Postremus could you have another look at this one so that we finalize it?

I added a small suggestion.

keyBuilder.append("|");
}

this.key = keyBuilder.toString();
Copy link
Member

Choose a reason for hiding this comment

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

My guess is that it would be better if you could compute the hashCode here and cache it in a final field.

@gsmet
Copy link
Member

gsmet commented Aug 9, 2022

@Postremus friendly ping.

@geoand
Copy link
Contributor

geoand commented Sep 1, 2022

@Postremus are you still interested in driving this home?

It seems like a rather good improvement

@gsmet
Copy link
Member

gsmet commented Feb 2, 2023

@geoand I rebased and applied some minor tweaks to reduce the cost of this new layer. I think you're more equipped than me to see if it introduces some significant overhead?

@geoand
Copy link
Contributor

geoand commented Feb 2, 2023

I'll have a look

@quarkus-bot

This comment has been minimized.

Postremus and others added 3 commits February 2, 2023 13:33
Resources classes where merged by using all components as map key. This leads to situations where the only differing property of a component may be its name. The name is for a DEFAULT_REGEX however not enough to be considered a different path itself.

The merge is now based on a custom (String) key, build on properties which should enforce uniqueness when needed: type, literal, and pattern.
This all comes from the observations I did in HV:

- Objects.hash() can be costly as it creates an array
- no real need to compare the classes given we know this object will
  only be used in a map that is consistent

Also:
- we don't need to cache the hashCode as String.hashCode() has a cache
- better use equals() than compareTo()
@geoand
Copy link
Contributor

geoand commented Feb 2, 2023

Fixed the styling issue and applied one more small enhancement

@quarkus-bot
Copy link

quarkus-bot bot commented Feb 2, 2023

✔️ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

@geoand geoand merged commit a9070e8 into quarkusio:main Feb 2, 2023
@quarkus-bot quarkus-bot bot added this to the 3.0 - main milestone Feb 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Request routing partially broken in reactive RESTEasy
4 participants