-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Various cleanups of Handler.insertHandler #10792
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you run the EE10 ServletContextHandler.testReplaceHandler()
in this branch you get a new WARN logging event. (should probably rename this specific test case, as we don't really do "replace" anymore in that test case)
2023-10-26 10:56:49.405:WARN :oejes.ServletContextHandler:main: ServletContextHandler.setHandler should not be called directly. Use insertHandler or setSessionHandler etc.
Looks like Handler.insertHandler()
winds up calling ServletContextHandler.setHandler()
which triggers this warning.
That's a bit of a confusing warning.
...0/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java
Outdated
Show resolved
Hide resolved
jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java
Outdated
Show resolved
Hide resolved
Also, What's the right semantic for Given And if you If that's the case, can you write that example in the javadocs of the overridden method? |
jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java
Outdated
Show resolved
Hide resolved
...0/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java
Outdated
Show resolved
Hide resolved
...0/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java
Outdated
Show resolved
Hide resolved
...tty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/ServletContextHandlerTest.java
Outdated
Show resolved
Hide resolved
jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java
Show resolved
Hide resolved
...jetty-ee9-servlet/src/test/java/org/eclipse/jetty/ee9/servlet/ServletContextHandlerTest.java
Outdated
Show resolved
Hide resolved
@sbordet any chance of a re-review before you go on vacation, now that I've explained how core 2 nested Handlers work? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gregw I am still a bit confused by SCH interaction with setHandler()
and insertHandler()
.
I would like the following:
- Make
ServletHandler extends Handler.Abstract
so that it's clear that it has no child. It still can returnfalse
, only in particular cases where users configure it to not have aDefaultServlet
(in which case we just return the "core" 404). SCH.setHandler()
always sets the first child after SCH (like allSingleton
do), overwriting the existing one, with the special handling for "the triplet", i.e.Session|Security|ServletHandler
, and relinks the triplet.- The triplet is always last in the chain, so
SCH.getTail()
always returns theServletHandler
.
Some example:
sch.setHandler(gzipH);
sch.insertHandler(wsUpgradeH); // => sch-wsuh-gziph-[sessionh]-[securityh]-servleth
sch.getHandler() == wsuh
sch.getTail() == servleth
With the current PR, the code above sets up the following chain, which I think is wrong: sch-wsuh-[sessionh]-[securityh]-servleth-gziph
, as we would never gzip.
With the proposal above:
sch.setHandler(gziph);
sch.setHandler(wsuh); // sch-wsu-[sessionh]-[securityh]-servleth -- gziph is lost as expected.
sch.setHandler(B);
sch.getHandler() == B; // The current PR breaks this.
I am sure the proposal above is a change to what I said earlier, but I find it clearer.
Would it work for you?
A quick test of this PR and it's handler tree looks like this ... ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SECURITY);
ServletHolder sh = new ServletHolder(new TestServlet());
servletContextHandler.addServlet(sh, "/foo");
servletContextHandler.setHandler(new GzipHandler());
servletContextHandler.insertHandler(new XYHandler());
Handler handler = servletContextHandler.getHandler(); // what does this look like ? This results in the Handler tree ...
Seems odd to have GzipHandler under the ServletHandler like this. |
@joakime the following code: Server server = new Server();
ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SECURITY);
servletContextHandler.setHandler(new GzipHandler());
servletContextHandler.insertHandler(new Handler.Wrapper());
server.setHandler(servletContextHandler);
server.start();
servletContextHandler.dumpStdErr(); produces:
I think the insert behaviour is exactly what we want. Either way, I don't think it is hugely important, as I can't see I real use case for wanting to do setHandler in this situation. However, with EE10 and beyond, it is slightly more important as users can no longer use a ServletHandler with a plain ContextHandler. It only works with a ServletContextHandler (to avoid the need for a ScopedHandler mechanism we establish servlet scope as we enter the context). As I said, I'm 60:40... but as I've currently implemented/tested the 40... I'm happy to go with it if there is consensus??? |
@sbortdet
I think we have always had some strangeness here where one handle carries a tuple of other handlers that must be in a specific structure. I'm not sure we can avoid t he situation. We can only address confusion by a bit better consistency and better documentation, which is what I think this PR does. We can't make the issue go away.
@sbordet there are definitely usages of
That's what I've now implemented for you. If it is not a
Not an option. There are valid use-cases for falling through a
I said I was 60:40 in my reply to @joakime, but now I'm 95:5 for the former behaviour of setHandler with less magic since the following should always be true:
I think the less magic, then the less confusion. My intention is to go back to a simple setHandler with warnings for bad behaviours. Perhaps it should not even intercept |
# Conflicts: # jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/SessionHandler.java
@joakime nudge |
@sbordet nudge |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still confused.
I think we should stick to the behavior of the other Handler
s and not make this one any special.
As I said, I was wrong wanting setHandler()
to set the child of ServletHandler
.
I think it should just do what any other Handler
does, i.e. setting the immediate child.
insertHandler()
would have the same semantic as others, i.e. setting the immediate child and shifting the current child.
The "triplet" always come last.
I'm fine for ServletHandler
to be a Wrapper
if there are use cases, but setting its child should always be done explicitly, i.e. sch.getServletHandler().setHandler(...)
, not via some "magic" in SCH.setHandler()
.
if (handler instanceof SessionHandler && getHandler() instanceof SessionHandler) | ||
setSessionHandler((SessionHandler)handler); | ||
else if (handler instanceof SecurityHandler && getHandler() instanceof SecurityHandler) | ||
setSecurityHandler((SecurityHandler)handler); | ||
else if (handler instanceof ServletHandler && getHandler() instanceof ServletHandler) | ||
setServletHandler((ServletHandler)handler); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this logic is right.
Calling setHandler()
with one of the 3 handlers will never work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has been this way for several years at least. So we are not making it special. It is already special.
I'm not sure we want to put a breaking change into the API without thought. I found a few places in the code that did rely on this behaviour, so other users may also.
I think if we want to change setHandler, that should be a different PR with more consideration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sbordet I've put the implementation of setHandler back to exactly what it has been for some time. However, this PR removes any usage of it that depends on that behaviour. If it is an issue, then we can make the method always warn if called on SCH.
…super. Moved call to relinkHandlers() in insertHandler(), as the various setSession|Security|ServletHandler() already call relinkHandlers(). Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gregw see my last commit where I added in one place and moved in another the call to relinkHandlers().
LGTM with the current behavior.
The move of the relink in But the I'll make a unit test to check this and then try to fix relinkHandler.... but I just don't think we should try to do magic with anything other than the Session/Security/Servlet handlers. Even that magic is probably too much. |
@sbordet OK I was wrong. |
Fixes #9297