I spent some time on this topic and I am now leaning towards solving it
differently.
Our most important requirement is that existing code runs without
changes. I think our second most important requirement is to keep
maintenance of Sling code manageable as well as not causing too much
discomfort to our user base.
The current plan was to update the most important parts of Sling (API,
Engine, Auth) and replace in those bundles javax.servlet with
jakarta.servlet. With that Sling would use jakarta servlet and without
any further work this would be breaking all existing code. We came up
with the idea to have some tooling that rewrites existing bundles and
replaces usage of javax.servlet with jakarta.servlet (most likely at
deployment or runtime time). With that our main requirement should be
solved.
However, this most likely means that we have to maintain two branches
for all those modules for bug fixes. It also means that we create an
incompatible change for packages where it does not really make sense.
The most prominent one is the resource package where javax.servlet is
only used in single methods.
It also means it is an all or nothing approach for our users. Within a
single bundle it is only possible to either use the old API or the new
one - as we use the same package and class names. I have the feeling
that this will create issues. While replacing in source code is easy,
what about testing code, 3rd party libraries etc. All of that out of a
sudden needs to work with jakarta.servlet. We have a huge ecosystem and
I am almost certain that this will create pain here and there. Might
again be solvable to some degree with additional tooling.
The easier solution for us and our users is most likely that we provide
an API that can deal with both servlet APIs, basically duplicating
interfaces where required. This allows for a step by step updating of
existing user code and provides a much better support in your IDE (the
deprecated and the new method are visible).
I was initially against this as I thought the implementation (in Sling
Engine and scripting) will be way too complicated but weighting this
pain in the implementation against potential pain for our users, I think
we have to take the pain and deal with it. It might not be as bad as I
initially thought. And to be fair, the tooling we would need is not
there today either - there are some promising basic tools we could built
upon, but still it does not come for free.
Long story short, I heavily favor now Option 1, providing new API based
on jakarta.servlet next to the existing one.
Regards
Carsten
On 01.10.2023 15:59, Carsten Ziegeler wrote:
> There are different options to do this move:
>
> Option 1: provide new API interfaces based on Jakarta - parallel to
the old ones with side-by-side packages (similar to the web console).
Maybe this should focus on Servlet 6 (with removed deprecated stuff), to
not have two migration steps for the users. While this is also an
opportunity to clean up our API around the Servlet API, it unfortunately
includes a complete fork of our API - and the implementation to support
old and new one will be pretty complex.
>
> Option 2: Update the existing API directly to Servlet 5/6. This
breaks all code out there and forces it to migrate. This is only an
option if we could provide tooling (byte code rewriting?) that either at
assembly or runtime rewrites usage of the old packages to the new
packages. This approach would not allow us to clean up the API. That
would need to be handled separately.
>
> Option 3: do nothing now and wait until this switch is actually
becoming a real problem.
>
> Giving the complexity of this problem, option 3 is maybe not the best
choice. Option 1 is very tempting, but I fear the complexity and risk
involved. I did this work for the web console and it was already quite
challenging there. If Option 2 would work, this could be a nice way out.
>
> Thoughts? Maybe there are better options?
--
Carsten Ziegeler
Adobe
[email protected]