spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

Implement Eclipse Jetty core HTTP handler adapter

Open gregw opened this issue 2 years ago • 25 comments

This provides an implementation of a HTTP Handler Adaptor that is coded directly to the Eclipse Jetty core API, bypassing any servlet implementation.

Fixes #32035

gregw avatar Jan 24 '24 06:01 gregw

@gregw Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

pivotal-cla avatar Jan 24 '24 06:01 pivotal-cla

@pivotal-cla Working on getting a CCLA signed. Stand by....

gregw avatar Jan 24 '24 08:01 gregw

@lachlan-roberts can you sign the individual CLA.

gregw avatar Feb 01 '24 01:02 gregw

This PR is failing 2 tests that undertow also fails: See https://github.com/spring-projects/spring-framework/issues/25310. Thus I'm currently suspecting bad tests or a spring bug, as both Jetty core and undertow are similar fully asynchronous integrations without servlets. We will investigate more, but any ideas that can help...

gregw avatar Feb 01 '24 01:02 gregw

@gregw Thank you for signing the Contributor License Agreement!

pivotal-cla avatar Feb 01 '24 01:02 pivotal-cla

@jhoeller Is there anything process wise that we need to do to move this PR on? It would be good to get some review to make sure we are on the right path.

gregw avatar Mar 22 '24 10:03 gregw

@jhoeller @bclozel @sbrannen What can we do to move this PR on? I'm sure there is lots that we need to update, but we need review to know what that is.

gregw avatar Apr 04 '24 12:04 gregw

@gregw Hi Greg, sorry for the recent lack of feedback. I plan to take a look at this PR soon, and hopefully we can merge it in 6.2 M2 or M3.

poutsma avatar Apr 16 '24 14:04 poutsma

@poutsma Would be good to get at least an initial review, as I'm sure there is some rough edges that need to be knocked off. Giving us a few comments will get us working on this and updating... plus we want to flow the work through springboot as well.

gregw avatar May 23 '24 23:05 gregw

@gregw Fair point. I had to take some unforeseen medical leave, but plan to focus on this PR this coming week.

poutsma avatar May 24 '24 09:05 poutsma

@gregw First off, thank you for submitting this PR, as well as your patience with regards to us handling it. The PR seems to be quite usable, and I am sure it will make it into 6.2.

Before getting into any specific details, my main question is why do JettyCoreServerHttpRequest and JettyCoreServerHttpResponse implement the ServerHttpRequest and ServerHttpResponse interfaces, and not to extend the abstract base classes? It appears that a lot of changes in the PR derive from this decision (for instance getNativeRequest is moved from the abstract base class to the interface). While it can be argued that this refactoring is desirable, it seems unrelated and makes this PR harder to review.

How should we proceed? If you prefer, I can take the PR from here, and get back you when I have questions. Or I can provide a more thorough review.

poutsma avatar May 28 '24 14:05 poutsma

@gregw First off, thank you for submitting this PR, as well as your patience with regards to us handling it. The PR seems to be quite usable, and I am sure it will make it into 6.2.

Awesome!

Before getting into any specific details, my main question is why do JettyCoreServerHttpRequest and JettyCoreServerHttpResponse implement the ServerHttpRequest and ServerHttpResponse interfaces, and not to extend the abstract base classes? It appears that a lot of changes in the PR derive from this decision (for instance getNativeRequest is moved from the abstract base class to the interface). While it can be argued that this refactoring is desirable, it seems unrelated and makes this PR harder to review.

Very good question. I cannot recall and looking at the code now, I see no particular reason, at least not for the request.

How should we proceed? If you prefer, I can take the PR from here, and get back you when I have questions. Or I can provide a more thorough review.

I'm flexible. I think it would be good to get you closely involved as I'm sure there a spring things that I'm doing wrong and working together would be a good way to communicate knowledge. So how about this as an approach:

  1. I'll have a go at reacting to your first feedback: i.e. try to use the abstract base classes. That will refresh my brain on this branch (it has been a while since I looked).
  2. You can then take over it for a while, changing anything you don't like or that is wrong
  3. I can stay involved, helping out as you require and reviewing your changes with a Jetty eye.

gregw avatar May 28 '24 23:05 gregw

I'm flexible. I think it would be good to get you closely involved as I'm sure there a spring things that I'm doing wrong and working together would be a good way to communicate knowledge. So how about this as an approach:

  1. I'll have a go at reacting to your first feedback: i.e. try to use the abstract base classes. That will refresh my brain on this branch (it has been a while since I looked).
  2. You can then take over it for a while, changing anything you don't like or that is wrong
  3. I can stay involved, helping out as you require and reviewing your changes with a Jetty eye.

Sounds good to me. It looks like you committed step 1 (d6986ee), so I will get started with step 2. Unless there are more changes forthcoming?

poutsma avatar May 29 '24 08:05 poutsma

@poutsma my step 1 is pretty broken. I think it need more work. stand by....

gregw avatar May 29 '24 12:05 gregw

@poutsma I've backed out the abstract response changes for now, as they broke a lot of tests. So I need to understand the difference and try again. Probably tomorrow now...

gregw avatar May 29 '24 12:05 gregw

@poutsma I've backed out the abstract response changes for now, as they broke a lot of tests. So I need to understand the difference and try again. Probably tomorrow now...

@gregw No worries, just let me know when you want me to take a look.

poutsma avatar May 30 '24 08:05 poutsma

@poutsma OK I think I've cracked the abstract response now as well. There is one test that fails occasionally that I need to look into more, but I think the PR is good for you to look at now. If you want to start making changes, go for it.. or direct me.

gregw avatar May 31 '24 00:05 gregw

@gregw I have made a first pass at reviewing the PR, and so far have made two changes:

  • I have reverted all unnecessary changes to ServerHttpRequest, ServerHttpRequest and subtypes, and simplified JettyCoreHttpHandlerAdapter, JettyCoreServerHttpRequest and JettyCoreServerHttpResponse, see here.
  • I have replaced flatMap(mapper, 1) with concatMap(mapper) in JettyCoreServerHttpResponse as these are semantically equivalent, and we use concatMap elsewhere, see here.

Regardless of whether the changes above have been applied, the main test failure I see is MultipartWebClientIntegrationTests. Next week I will take a look at why these fail. I will also take a look at the websocket changes, as I haven't done so yet.

poutsma avatar May 31 '24 11:05 poutsma

I have committed several other changes, see https://github.com/poutsma/spring-framework/commits/gh-32097/.

The only test that fails is the MultipartWebClientIntegrationTests. It does not fail in the IDE, making it a bit harder to reproduce. This is the server-side stack trace I get:

java.lang.IllegalArgumentException: demand pending
    at org.eclipse.jetty.server.internal.HttpChannelState$ChannelRequest.demand(HttpChannelState.java:955) ~[jetty-server-12.0.10.jar:12.0.10]
    at org.eclipse.jetty.io.content.ContentSourcePublisher$SubscriptionImpl.process(ContentSourcePublisher.java:124) ~[jetty-io-12.0.10.jar:12.0.10]
    at org.eclipse.jetty.util.thread.SerializedInvoker$Link.run(SerializedInvoker.java:191) [jetty-util-12.0.10.jar:12.0.10]
    at org.eclipse.jetty.server.internal.HttpConnection$DemandContentCallback.succeeded(HttpConnection.java:680) [jetty-server-12.0.10.jar:12.0.10]
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:99) [jetty-io-12.0.10.jar:12.0.10]
    at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53) [jetty-io-12.0.10.jar:12.0.10]
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:979) [jetty-util-12.0.10.jar:12.0.10]
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1209) [jetty-util-12.0.10.jar:12.0.10]
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1164) [jetty-util-12.0.10.jar:12.0.10]
    at java.base/java.lang.Thread.run(Thread.java:840) [?:?]

@gregw Does that ring any bell with you, or are we doing something wrong in the Spring code?

I have also asked @rstoyanchev and @simonbasle to review (my branch of) the PR, so comments from them might be forthcoming.

The next Spring Framework milestone (6.2.0-M4) is on June 13th. I am not sure if we will have resolved the test above by that point, so this PR might not make that milestone. The milestone after that is scheduled for July 11th.

poutsma avatar Jun 06 '24 09:06 poutsma

My apologies for being slow now... I've seen your reviews and will respond in the next few days.

gregw avatar Jun 11 '24 00:06 gregw

@poutsma Our branches have diverged as I made the changes to use AbstractServerHttpRequest and AbstractServerHttpResponse in my branch and you forked before that. Let me see if I can rebase yours onto mine....

gregw avatar Jun 12 '24 00:06 gregw

Actually, I'm not exactly sure why our branches were seen as divergent. I've merged yours back to mine and made sure that there are no differences, and also merged to lastest origin/main. I'm not 100% sure the merge is correct, so we may want to proceed with your branch, but at least we can see your changes in this PR and I can work with it as well. Now looking at the test failure....

gregw avatar Jun 12 '24 00:06 gregw

@poutsma

The only test that fails is the MultipartWebClientIntegrationTests. It does not fail in the IDE, making it a bit harder to reproduce. This is the server-side stack trace I get:

java.lang.IllegalArgumentException: demand pending
  ...

@gregw Does that ring any bell with you, or are we doing something wrong in the Spring code?

I think it is likely a problem with the jetty ContentSourcePublisher, for which we already have a PR in review: https://github.com/jetty/jetty.project/pull/11849

The next Spring Framework milestone (6.2.0-M4) is on June 13th. I am not sure if we will have resolved the test above by that point, so this PR might not make that milestone. The milestone after that is scheduled for July 11th.

Agreed we are not making the 13th. We have a jetty release at the end of the month, so I will get #11849 merged for that and also look at change @rstoyanchev made.

@lachlan-roberts can you look at the websocket reviews before end of month, so that any changes needed in next jetty release can be included. E.g. anything needed to get the Container without the Handler

gregw avatar Jun 12 '24 01:06 gregw

The MultipartWebClientIntegrationTests test did not fail running from command line with jetty 12.0.11-SNAPSHOT

gregw avatar Jun 23 '24 23:06 gregw

The MultipartWebClientIntegrationTests test did not fail running from command line with jetty 12.0.11-SNAPSHOT

Great! If I understand your other comment correctly, Jetty 12.0.11 will be out by the end of June, which should give us enough time to get this PR into 6.2.0-M5.

poutsma avatar Jun 24 '24 13:06 poutsma

@poutsma @rstoyanchev the build of this branch is now passing all tests with the staged release of jetty-12.0.11, which should be released very soon.

lachlan-roberts avatar Jul 01 '24 06:07 lachlan-roberts

@lachlan-roberts @gregw I see the artifacts appear to be on Maven Central as of June 28, but I see no announcements and the release-tracking issue jetty/jetty.project/issues/11980 is not closed. Can you confirm if we should be waiting for anything before merging?

I've retrieved Arjen's branch locally, made a couple polishes (fixing duplicate start/stop methods in JettyWebSocketClient notably), rebased on the latest main and all the tests ran successfully 👍

simonbasle avatar Jul 05 '24 10:07 simonbasle

@simonbasle The release is out in maven central and there is no taking it back. We have some people on vacation, hence the issue process has not yet completed.

gregw avatar Jul 05 '24 10:07 gregw

@lachlan-roberts unless I've missed something, you haven't yet signed the CLA have you?

simonbasle avatar Jul 05 '24 13:07 simonbasle

@simonbasle yes I have already signed the CLA.

lachlan-roberts avatar Jul 05 '24 15:07 lachlan-roberts