How do we want to access the request/response in a jakarta world?

Hi everyone,

We decided in Introduce new jakarta servlet related APIs to deprecate the current (javax) servlet related APIs.

In this proposal, I would like to discuss new ways to access the HttpServletRequest/Response.

The old ways

First, here are the current main ways to access the HttpServletRequest (and it’s pretty much the same for the HttpServletResponse):

  • java
    • through the XWikiContext
    • through Container#getRequest() which is then cast to a ServletRequest
  • scripting
    • through the $request binding
    • through the $xcontext.request binding

Currently on Script side everything is manipulating servlet APIs, and we don’t have at all the generic concept of Request/Response we have on Java side. To be honest, we don’t really use that generic concept much in Java either (right now, the main use of org.xwiki.container.Request is to be cast into a org.xwiki.container.servlet.ServletRequest).

The new ways

Java

For the new servlet specific API I thought that it would be nice to simply (almost directly) inject the HttpServletRequest. In practice, you would use a Provider<HttpServletRequest> (that would return null if there is no HttpServletRequest in the current thread).

Script

For the script side, as discussed in the other forum thread, I believe we need to go through a service and not inject new bindings potentially colliding with variables. Here I’m hesitating between various possibilities:

  1. a servlet specific $services.servlet.request/response
  2. generic $services.container.request/response like with have org.xwiki.container.Container and org.xwiki.container.Request on Java side, and add the more specific
    2.1. $services.container.servlet.request/response
    2.2. or $services.container.request/response.servlet

Of course, those APIs would return something similar to ScriptXWikiServletRequest (which add some protection for authors without programming right).

WDYT ? Any other ideas you think would be better ?

Sounds like it could be open door to NPE. We decided to use Optional in our APIs to avoid NPE when possible, wouldn’t it be possible here to have something similar? e.g. Provider<Optional<HttpServletRequest>> or maybe more a Provider<HttpServletRequestOptional>?

You said that we don’t really use directly org.xwiki.container.Request on java side, so is there a real need to be able to use it on scripting side?

On the long run do you see other operations that $services.servlet could provide?

I’ve the feeling that 2.1 would be good but without offering a generic $services.container.request/response if there’s no need for now.

I think we don’t use it much right now because we still rely a lot on XWikiContext and because Request is pretty light. If we add a bit more common stuff to this API and stop using XWikiContext to access the request, we might use it more. Otherwise, I don’t see any point in keeping it at all and if we think XWiki is only ever going to support Servlet, then we should deprecate pretty much the whole xwiki-platform-container-api.

Provide direct access to the servlet session and the servlet context, both of which are very useful.

I guess we could also offer APIs to manipulate the sessions we have in HttpSessionManager, and plenty of other potential helpers.

Right now it’s a bit abstract to me, but I have a bit the feeling that with a Provider<HttpServletRequest> we wouldn’t really need that indeed.

ok, so might be a better solution. So all in all I think I’d +1 for solution 1 and -0 for 2.1.

The real question is whether it’s possible to abstract containers under an API. The idea of the container module was to do this for 2 environments (Servlet & Portlet - for those who don’t know we had a portlet integration of XWiki inside exo platform at some point) and have the ability to introduce new environments in the future (like the ability to run XWiki as a standalone app, using Spring Boot for example).

So the idea was that any module would not directly manipulate specific container implementation classes but go through this abstraction and thus be ready to support all containers. With the idea that some feature could be disabled if they’re container-specific (hence the cast to ServletRequest to check if the code is running inside a Servlet Container or not when it’s not possible to use an api common to all containers).

The idea was to slowly add new container APIs as the need arise but we never really did this.

On this day I’m still not sure whether it’s a good idea or a bad one. What I’d like to preserve though is the following:

  • Limit access to container-specific APIs in modules as much as possible, ie try to code modules so that they can be deployed anywhere
  • If they need to call Servlet APIs for some features, put the code that depend on servlet APIs in a separate module suffixed with -servlet to clearly indicate this, or something like this.

More generally, if we want to drop the concept of container, we need a specific thread with a VOTE for it.

Thanks

We are very far from this goal right now I’m afraid, we use servlet specific APIs everywhere.

This is not my proposal. I’m just trying to find the best replacement API for all the code which is currently using (javax) HttpServletRequest/Response API directly

This feels a bit like an over-statement, we probably use servlet specific apis in less than 10% of our modules, probably more like 1-5%. 0% in commons, probably 0% in rendering too and a bit more in platform, maybe 10%.

In this case the solution is 2. Right now we’re missing a scripting service for container because we didn’t see the need or forgot to add it, but it’s logical to have one if we keep the concept of container.

And no direct injection in java, instead get whatever is needed from the container api.

But I understood from this thread and the other one at Introduce new jakarta servlet related APIs that we were questioning the need for the container api. And it’s not new. So maybe it’s the time to decide what we do about it since it impacts the decision on new apis, including this thread.

I think that you did not count all the uses of the XWikiContext request/response which are servlet APIs and will have to be migrated.

Not sure where you got this impression from the other thread, since it’s actually proposing the opposite: " people should always go through org.xwiki.container.* APIs or a new container script service in the jakarta era of XWiki".

Indeed, I only counted direct usage of the servlet api (ie imports of javax.servlet). The request/response returned by XWikiContext are already a kind of encapsulation to a container (but not generic at all since it’s a direct mapping to the Servlet Request/Response) and we could imagine they’d return Container Request/Response objects instead (but since XWikiContext is old and not supposed to be used, it would probably be better to go through ExecutionContext or some shortcut component using ExecutionContext). It’s indeed a lot of work to migrate them to a Container API. I feel that it’s doable bit by bit though if we have an agreement about the api to use and we could all help to do that.

ok my bad then; I thought I had seen questions (especially by Simon) about the idea of dropping the container module.

It’s a true question for me too whether we should continue the container abstraction or drop it.

Thanks

No, they are not. They just extend javax.servlet interfaces to add a few things so it is direct usage of the servlet API, that’s why we said they need to be deprecated in the context of the move to jakarta.

That’s in this thread.