RFR: 7494: Unable to view JMC Help Contents

Alex Ciminian duke at openjdk.java.net
Sun Jan 9 15:08:45 UTC 2022


This PR fixes a problem that makes all JMC help pages fail. 

We use the eclipse help plugin, it plugin starts a web server which renders the XML content in the docs plugin via JSP. When the user clicks help in the JMC UI they are sent to the browser, which tries to render one of these JSP pages. 

In #306 we introduced new dependencies on multiple Jetty packages so we can run a websocket server inside JMC. After these changes we notice that the help pages fail to render with the following error:


javax.servlet.ServletException: non-HTTP request or response
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:578)
	at org.eclipse.equinox.http.jetty.internal.HttpServerManager$InternalHttpServiceServlet.service(HttpServerManager.java:308)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:508)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)


This is the code that throws the exception:


    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request;
        HttpServletResponse response;

        if (!(req instanceof HttpServletRequest && res instanceof HttpServletResponse)) {
            throw new ServletException("non-HTTP request or response");
        }

        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;

        service(request, response);
    }


The help plugin has Jetty as a transitive dependency so it's likely this error is caused by the new `servlet-api` dependency that we've introduced. Using the debugger, we can set a breakpoint before the exception is thrown and we can inspect `req` and `res` to see why the `instanceof` check fails. The result of this is very strange:

<img width="443" alt="Screenshot 2022-01-08 at 18 05 43" src="https://user-images.githubusercontent.com/348973/148687951-006c9a92-f6d2-4039-b38d-137a74fb2af0.png">

I don't understand why this fails here, since we can see with reflection that `req` implements the expected `javax.servlet.http.HttpServletRequest` interface. It's likely this is because we have two `servlet-api` bundles loaded, `org.eclipse.jetty.servlet-api` (explicit dependency of `flightrecorder.ui`) and `jakarta.servlet-api` (transitive dependency of the help plugin). 

I also don't understand if it's possible that `instanceof` fails because it tries to compare `javax.servlet.http.HttpServletRequest` loaded from the different bundles, given that the package and interface names are identical.

Regardless of the root cause, removing the explicit dependency on `org.eclipse.jetty.servlet-api` from the target platform and depending on `jakarta.servlet-api` in the `flightrecorder.ui` manifest fixes the issue. Now help pages load successfully and the websocket server works as before.

-------------

Commit messages:
 - Remove dependency on jetty.servlet-api, use jakarta instead

Changes: https://git.openjdk.java.net/jmc/pull/347/files
 Webrev: https://webrevs.openjdk.java.net/?repo=jmc&pr=347&range=00
  Issue: https://bugs.openjdk.java.net/browse/JMC-7494
  Stats: 6 lines in 6 files changed: 0 ins; 5 del; 1 mod
  Patch: https://git.openjdk.java.net/jmc/pull/347.diff
  Fetch: git fetch https://git.openjdk.java.net/jmc pull/347/head:pull/347

PR: https://git.openjdk.java.net/jmc/pull/347


More information about the jmc-dev mailing list