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

Jetty 11 support #1942

Merged
merged 11 commits into from
Dec 30, 2022
Merged

Jetty 11 support #1942

merged 11 commits into from
Dec 30, 2022

Conversation

reta
Copy link
Contributor

@reta reta commented Sep 3, 2022

Jetty 11 support, closes #1760

  • Finish upload refactoring
    • multipart/mixed is not handled yet (4 tests in the MultipartBodyMatchingAcceptanceTest)
  • Fix logging support (slf4j 2.0.0): switched to Logback 1.4.0 since Log4j2 does not support Slf4j 2.0 APIs (yet)
  • HttpServletResponse::setStatus(int sc, String sm) is deprecated and not implemented by Jetty 11 (StubbingAcceptanceTest::settingStatusMessage)
  • Fix failing test cases: 1 test case is failling
    • GeneralCodingRulesTest > RULE_NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS FAILED

@reta reta force-pushed the issue-1760 branch 2 times, most recently from 923c30c to ffeee5a Compare September 4, 2022 01:33
Copy link
Member

@tomakehurst tomakehurst left a comment

Choose a reason for hiding this comment

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

Thanks for making a start on this.

Please let me know if you'd like any help getting specific features working again. I know the faults stuff can be tricky as I've had to re-fix them at least twice during Jetty upgrades.

@@ -34,23 +34,15 @@ private static Constructor<? extends JettyHttpServer> getServerConstructor() {
try {
Class<? extends JettyHttpServer> serverClass =
(Class<? extends JettyHttpServer>)
Class.forName("com.github.tomakehurst.wiremock.jetty94.Jetty94HttpServer");
Class.forName("com.github.tomakehurst.wiremock.jetty11.Jetty11HttpServer");
Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering if we should ditch the reflection now and just construct it directly.

This was originally used so that both JDK7/Jetty 9.2.x and JDK8+/Jetty 9.4.x could be selected appropriately at runtime. Since we're dropping support for all Jetty versions except 11 (for now at least) there's no good reason I can think of to load reflectively.

It'll help cold start performance too if we do it directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I think direct usage will be better option

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed that as well, thanks @tomakehurst

@@ -82,7 +84,7 @@ public void testStopTimeout() {

@Test
public void testStopTimeoutNotSet() {
long expectedStopTimeout = 1000L;
long expectedStopTimeout = 5000L;
Copy link
Member

Choose a reason for hiding this comment

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

Does the original 1s value cause problems with this Jetty verrsion?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is very interesting but the graceful shutdown in Jetty 11 is taking more time, ~3s on average, I set it to 5s to eliminate possible flakiness.

Copy link
Member

Choose a reason for hiding this comment

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

Wow, 3s is pretty bad. Since many (most probably) WireMock tests start and stop the server per test case, this is going hurt performance pretty badly.

I wonder if there's something we do to tune this (or something we're doing to cause in in the first place)?

Copy link
Contributor Author

@reta reta Sep 4, 2022

Choose a reason for hiding this comment

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

Yeah, we surely could look at it, I have not spend much time into looking"why" but Graceful.shutdown is the one taking time, we could look which components here to look after

@reta
Copy link
Contributor Author

reta commented Sep 4, 2022

Thanks for making a start on this.

Please let me know if you'd like any help getting specific features working again. I know the faults stuff can be tricky as I've had to re-fix them at least twice during Jetty upgrades.

I will, thanks @tomakehurst , I will try to fix what I could before asking for your time.

@tomakehurst
Copy link
Member

I've just pushed a bunch of fixes to the master branch to get Jetty 9.4.48 working, in case that's any use.

@reta
Copy link
Contributor Author

reta commented Sep 9, 2022

👍 thanks @tomakehurst , I will rebase shortly, almost done with multipart/*

@reta reta force-pushed the issue-1760 branch 3 times, most recently from 1eed022 to e320d83 Compare September 9, 2022 16:55
@reta
Copy link
Contributor Author

reta commented Sep 9, 2022

@tomakehurst I think we are there, could I ask you please to run the workflow (if possible) to check if I missed something , I have only 1 test case failing: GeneralCodingRulesTest > RULE_NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS FAILED. Thank you.

* properly. To preserve backward compatibility and support wider range of multipart content,
* re-implementing this part of the upload.
*/
class FileUpload {
Copy link
Contributor Author

@reta reta Sep 9, 2022

Choose a reason for hiding this comment

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

@tomakehurst this is probably the most controversial change but here is the story. Jetty supports multipart/form-data out of the box, so that is cool. However, the fileupload components also support multipart/mixed and multipart/related (+ attachments). The problems with fileupload are: a) no releases for the last 4 years b) tight integration with javax.servlet.

There are 3 routes to take here:

  • drop multipart/mixed and multipart/related support, not very pleasant for backward compatibility
  • adapt fileupload to deal with Jakarta Servlet (this pull request)
  • drop fileupload and write own multipart parsers for multipart/mixed, multipart/related and attachments (may take some time)

Appreciate your opinion on the matter, thanks!

Copy link
Member

Choose a reason for hiding this comment

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

I think dropping support for /mixed and /related wouldn't go down well, since it only got added relatively recently: #1415.

The second option seems like the best choice to me, since we know the library does what we need. Rolling your own always takes time and inevitably means fixing bugs for a while afterwards.

Do you see any downsides of option 2?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tomakehurst thanks for opinion, the only downside I see is bringing the additional code (which I shamelessly copied, acknowledging that) which would need to be maintained, otherwise - reasonable tradeoff.

Copy link
Member

Choose a reason for hiding this comment

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

The other consideration is licensing. It'd be the only case where we're copying source code into the project rather than depending on libraries and I'm not sure what impact this has on our ability to present WireMock as being from a single copyright source etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The license is Apache v2.0 [1], should be good on this front, and there are still chances that fileupload gets new release with Jakarta support [2], no hints when though ...

[1] https://www.apache.org/licenses/LICENSE-2.0
[2] https://github.com/apache/commons-fileupload/tree/master/src/main/java/org/apache/commons/fileupload2/jaksrvlt

Copy link
Member

Choose a reason for hiding this comment

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

Another solution to this that might be worth considering is adding just the servlet API back into the dependencies.

I haven't fully tested it yet, but adding implementation 'javax.servlet:servlet-api:2.5' to the build file seems to fix the issue and allow you to use the fileupload library.

Copy link
Contributor Author

@reta reta Sep 20, 2022

Choose a reason for hiding this comment

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

Technically you are right (since the Servlet API is referenced only in some static methods if I am not mistaken), but that would be quite confusing to be fair. It may work for wiremock specifically but have unintended consequences for the projects using it: I would imaging classpath scanning issues fe (even if we are talking about tests only).

Copy link
Member

Choose a reason for hiding this comment

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

It would certainly complicate things for users who've already got the servlet API in their classpath from somewhere else, and it'd be a shame to make people switch to the standalone JAR just to avoid this.

So I guess the copied version is the least worst option at the moment.

There are some things that are necessary to do in order to comply with the Apache 2.0 licence, which are summarised here:
https://tldrlegal.com/license/apache-license-2.0-(apache-2.0)
The NOTICE file we'll need to include is here: https://github.com/apache/commons-fileupload/blob/commons-fileupload-1.4/NOTICE.txt

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tomakehurst thanks a lot, I will do that shorly (travelling next couple of days), apologies for that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tomakehurst
Copy link
Member

Can I suggest dropping Java 8 from the build matrix (since our minimum is now 11)?

@reta reta marked this pull request as ready for review September 19, 2022 16:45
@reta reta changed the title [WIP] Jetty 11 support Jetty 11 support Sep 19, 2022
@tomakehurst
Copy link
Member

Excellent progress - great to see all the tests green.

Do you have any theories on how we can deal with this slow shutdown issue?

@reta
Copy link
Contributor Author

reta commented Sep 27, 2022

Excellent progress - great to see all the tests green.

Thank you!

Do you have any theories on how we can deal with this slow shutdown issue?

Oh, sorry, I forget to troubleshoot it, I will update you on the matter shortly

@reta
Copy link
Contributor Author

reta commented Sep 30, 2022

Do you have any theories on how we can deal with this slow shutdown issue?

@tomakehurst getting back to this one, so the Graceful shutdown includes 6 components (see please below), each of them is subject of own Graceful shutdown sequences. The NetworkTrafficServerConnector (last one in the list) takes indeed more than 1 second - it shuts all connectors / acceptors (we have in this case 4 of them, vs 2 in case of Jetty 9), it probably adds up.

Elapsed for NetworkTrafficServerConnector@18cc679e{HTTP/1.1, (http/1.1, h2c)}{localhost:0}: 1ms
Elapsed for o.e.j.s.ServletContextHandler@19058533{/__admin,null,SHUTDOWN}: 0ms
Elapsed for o.e.j.s.ServletContextHandler@4315e9af{/,null,SHUTDOWN}: 0ms
Elapsed for HTTP2SessionContainer@730e5763[size=0]: 1ms
Elapsed for HTTP2SessionContainer@7275c74b[size=0]: 0ms
Elapsed for NetworkTrafficServerConnector@263f04ca{SSL, (ssl, alpn, h2, http/1.1)}{localhost:0}: 1017ms

I think we could safely drop 5s to 3s but going below could be a bit risky (unstable).
Wdyt?

@tomakehurst
Copy link
Member

I think there's something fundamentally wrong if we can't get down into the sub 100ms range. Certainly, we'll be sacrificing a lot of performance vs. the previous version.

Are you able to profile it to see what the connector class is spending so much time on?

@reta
Copy link
Contributor Author

reta commented Sep 30, 2022

Are you able to profile it to see what the connector class is spending so much time on?

No, I instrumented the server code to find the cultprit but didn't profile, I am afraid that rabbit hole could take me a while, I may look into that in a few weeks, apologies but do not have enough spare time these days.

Signed-off-by: Andriy Redko <drreta@gmail.com>
Signed-off-by: Andriy Redko <drreta@gmail.com>
Signed-off-by: Andriy Redko <drreta@gmail.com>
…ustom status message

Signed-off-by: Andriy Redko <drreta@gmail.com>
Signed-off-by: Andriy Redko <drreta@gmail.com>
Signed-off-by: Andriy Redko <drreta@gmail.com>
…ate Jetty11HttpServer (no reflection)

Signed-off-by: Andriy Redko <drreta@gmail.com>
Signed-off-by: Andriy Redko <drreta@gmail.com>
@reta
Copy link
Contributor Author

reta commented Oct 8, 2022

Are you able to profile it to see what the connector class is spending so much time on?

@tomakehurst I was able to get back to that, so there is another timeout in play here, shutdownIdleTimeout with default set to 1 second. I lowered the default to 100ms and also exposed it as part of JettySettings (so it becomes possible to customize it by the need), the stop delay is reverted back to 1 second, no issues observed (at least locally).

@jimma
Copy link
Contributor

jimma commented Oct 18, 2022

@reta @tomakehurst It's nice to see the Jetty11 support is addressed in this PR. Nice work ! @tomakehurst Is there any plan to have a release with this change soon ?

@reta
Copy link
Contributor Author

reta commented Nov 4, 2022

@tomakehurst anything else left or I could help you with to move this thing forward? It would be very helpful, thank you.

@tomakehurst
Copy link
Member

I think this is looking pretty good, although I wanted to do a bit of profiling on it before merging as it still seems to be a bit slower than than with Jetty 9.x.

(Was also waiting until I'd shipped the last minor release to avoid having to deal with branches, but that's done now).

@raphw
Copy link

raphw commented Nov 25, 2022

No intend to nag, I was just wondering if you have a release date in mind. The current wiremock is incompatible with Spring Boot 3 and due to the Jakarta switch, there's quite a bit of work involved that grows stale quickly through the huge change set, that's the reason for my interest. Thanks for the great work!

@tomakehurst
Copy link
Member

@raphw I'll try to look at this the w/c 12th of December (I'm maxed out with the day job up until then)

@raphw
Copy link

raphw commented Nov 25, 2022

Brilliant. I'll try to set off some time myself for performance testing the diff!

@marcingrzejszczak
Copy link

Why is WireMock incompatible with Boot 3? Spring Cloud Contract works really well with it 🤔

@reta
Copy link
Contributor Author

reta commented Nov 25, 2022

Why is WireMock incompatible with Boot 3? Spring Cloud Contract works really well with it 🤔

At the moment, WireMock uses Jetty 9 (and javax.servlet.* under the hood), while Spring Boot 3 moved to Jetty 11 and JakartaEE [1]. I would clarify that it is not compatible with Spring Boot 3 web applications that use Jetty 11, you may overcome some of these limitations using wiremock-standalone as a dependency.

[1] https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes

@marcingrzejszczak
Copy link

That's exactly what we're doing - using wiremock-standalone - I guess that's why we don't face any issues.

@jorgerod
Copy link

We have the same problem. We have a framework that we want to migrate to SpringBoot 3 and we are blocked by this issue.

@tomakehurst Are you planning to release this feature soon?

Thank you very much

@tomakehurst tomakehurst merged commit 86f64d4 into wiremock:master Dec 30, 2022
@reta
Copy link
Contributor Author

reta commented Dec 30, 2022

@tomakehurst thank you!

@tomakehurst
Copy link
Member

@reta thank you for contributing this!

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.

Jetty 11 support
6 participants