-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[WFLY-16296] Jakarta EE based WildFly have to communicate successfull…
…y with previous Java EE based WildFly versions
- Loading branch information
Showing
1 changed file
with
214 additions
and
0 deletions.
There are no files selected for viewing
214 changes: 214 additions & 0 deletions
214
backward-compatibility/WFLY-16296_JavaEE_And_JakartaEE_Compatibility.adoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
= Jakarta EE based WildFly have to communicate successfully with previous Java EE based WildFly | ||
:author: Richard Opalka; Flavia Rainone | ||
:email: [email protected]; frainone@@redhat.com | ||
:toc: left | ||
:icons: font | ||
:idprefix: | ||
:idseparator: - | ||
|
||
== Overview | ||
|
||
This feature will ensure bidirectional EJB, JNDI & HTTP remote protocols backward | ||
compatibility between Java EE 8- and Jakarta EE 9+ WildFly versions. | ||
|
||
== Issue Metadata | ||
|
||
=== Issue: | ||
|
||
* https://issues.redhat.com/browse/WFLY-16296[WFLY-16296] | ||
|
||
=== Dev Contacts: | ||
* mailto:[email protected][Richard Opalka] | ||
* mailto:[email protected][Flavia Rainone] | ||
|
||
=== QE Contacts: | ||
TODO!!! | ||
|
||
=== Testing By | ||
* [ ] Engineering | ||
|
||
* [x] QE | ||
|
||
=== Affected Projects or Components: | ||
|
||
* JBoss Marshalling, JBoss EJB Client, WildFly Naming Client, WildFly Http Client | ||
|
||
=== Relevant Installation Types | ||
* [x] Traditional standalone server (unzipped or provisioned by Galleon) | ||
|
||
* [x] Managed domain | ||
|
||
* [x] OpenShift s2i | ||
|
||
* [x] Bootable jar | ||
|
||
== Requirements | ||
|
||
=== Hard requirements | ||
|
||
* Ability of Java EE 8- client/server to communicate with Jakarta EE 9+ server/client via EJB, JNDI and HTTP remote protocols. | ||
* Ability of Jakarta EE 9+ client/server to communicate with Java EE 8- server/client via EJB, JNDI and HTTP remote protocols. | ||
* Java EE 8- WildFly versions cannot be modified in order to be able to communicate with Jakarta EE9+ WildFly variants. | ||
* Backward compatibility mode is off by default, and can be enabled by setting the `org.wildfly.ee.namespace.interop` system | ||
property to `true`. | ||
* If the property is set to `true` on a Java EE 8- server/client, it is ignored, as those clients and servers are not | ||
responsible for handling interoperability. | ||
|
||
|
||
=== None requirements | ||
|
||
* Infinispan and Clustering protocols backward compatibility. | ||
* ABI compatibility for non existing mapping of classes/methods available in Java EE 8- but not in Jakarta EE 9+ and vice versa. | ||
Users will need to migrate their clients/applications for such problematic scenarios manually. | ||
|
||
== Test Plan | ||
|
||
The test will be created for hard requirements scenarios. This test will reside in QE's testsuite and will become | ||
one of the must-execute tests for ensuring backward compatibility between Java EE based WildFly and Jakarta EE based WildFly variants. | ||
|
||
== Community Documentation | ||
|
||
Community documentation will be provided for how the aforementioned compatibility among remote EE clients and servers. | ||
It will be added to the WildFly documentation, and it will be based on this analysis document as reference. | ||
|
||
Also, the wildfly-http-client project documentation must also be updated describing the changes applied to the WildFly | ||
HTTP Client protocol. | ||
|
||
== Release Note Content | ||
Bullet point: support interoperability between Jakarta EE 9 servers and Java EE 8 or older servers | ||
|
||
== Design Notes | ||
|
||
The backward compatibility between two Java EE 8- and Jakarta EE 9+ remote endpoints has to be enabled at the endpoint | ||
that supports Jakarta EE 9+. To accomplish that, the Jakarta EE 9+ endpoint (a client or a server) is started with the system | ||
property `org.wildfly.ee.namespace.interop` set to `true`. With this property enabled, a Jakarta EE 9+ server or client | ||
becomes compatible with other Java EE 8- servers/clients, while still keeping the ability to communicate with other | ||
Jakarta EE 9+ endpoints(as long as those endpoints have the same property enabled, see | ||
<<communication-across-multiple-endpoints>>). We say that this particular server or client is running on *EE namespace | ||
interoperable mode*. | ||
|
||
Only Jakarta EE 9+ endpoints can run on EE namespace interoperable mode. For other endpoints, this property will be | ||
ignored if set to `true`. | ||
|
||
To implement that, we propose the following changes to the following libraries: | ||
|
||
|
||
=== JBoss Marshalling | ||
|
||
* Introduce new abstraction ClassNameTransformer that will allow to remap one java type to another java type. | ||
* Provide hooks for that abstraction to allow renaming java types before/after marshalling/unmarshalling them. | ||
* Provide default Java EE <-> Jakarta EE class name transformer implementation. | ||
|
||
=== JBoss EJB Client | ||
|
||
Since JBoss EJB protocol supports 'handshake' kind of messages it is possible to detect other side protocol version before exchanging messages. Because of this we propose to: | ||
|
||
* Introduce new major version 4 of remote EJB protocol to indicate EJB client/server is supporting Jakarta EE 9+. | ||
* Activate version 4 of EJB protocol if and only if JBoss EJB client/server is used in Jakarta EE9+ environment. | ||
* Install Java EE <-> Jakarta EE class name transformer if and only if the client/server is running on EE namespace | ||
interoperable mode, and the other side is using version 1 or 2 or 3 of the protocol. | ||
|
||
=== WildFly Naming Client | ||
|
||
Since WildFly NAMING protocol supports 'handshake' kind of messages it is possible to detect other side protocol version before exchanging messages. Because of this we propose to: | ||
|
||
* Introduce new major version 3 of remote NAMING protocol to indicate NAMING client/server is supporting Jakarta EE 9+. | ||
* Activate version 3 of NAMING protocol if and only if WildFly NAMING client/server is used in Jakarta EE9+ environment. | ||
* Install Java EE <-> Jakarta EE class name transformer if and only if the client/server is running on EE namespace | ||
interoperable mode, and the other side is using version 1 or 2 of the protocol. | ||
|
||
=== WildFly Http Client | ||
|
||
Since WildFly HTTP protocol doesn't support 'handshake' kind of messages it is not possible to detect other side | ||
protocol version in advance. The version number is in the URL of the particular service provided by the server, and the request | ||
is sent directly to that particular URL, without prior negotiation. Because of this we propose to: | ||
|
||
* implement a handshake based on a HTTP header | ||
* Install Java EE <-> Jakarta EE class name transformer if and only if the server is on EE namespace interoperable mode | ||
and the handshake indicates the connection requires such transformer | ||
|
||
The handshaking between two Jakarta 9+ client and servers, both running on EE namespace interoperable mode, works as follows: | ||
|
||
* whenever the client side opens a new connection to a server, the first request it sends via that connection contains | ||
the `x-wf-ee-ns: interop` HTTP header, and that first request is marshalled | ||
with the Java EE 8- <-> Jakarta EE 9+ class transformer, transforming the EE api classes in the request to `javax` EE | ||
namespace | ||
* the server receives the request, verifies it has the `x-wf-ee-ns: interop` header, and enables the class name | ||
transformer to transform the request back to `jakarta` namespace. The server though sends the response without the | ||
transformer, with the Jakarta EE 9+ classes intact, and adds the `x-wf-ee-ns: jakarta` header to the response | ||
* the client receives such response and reads the header. It indicates that this connection is a | ||
Jakarta EE 9+ connection at both ends, and the client is not supposed to transform the namespace of the EE classes | ||
contained in the response data. | ||
* from that point on, whenever the client uses the same connection, no transformation is done on its side. Furhtermore, | ||
all requests sent by the client through this connection contain the | ||
`x-wf-ee-ns: jakarta` header | ||
* whenever the server receives a request with the `x-wf-ee-ns: jakarta` header, it knows that the client is a | ||
Jakarta EE 9+ client running on EE namespace interoperable mode. So, it does not use any class file transformer | ||
for reading the request and writing the response. | ||
|
||
Here is how the handshaking works when an EE namespace interoperable client sends a request to a Java EE 8- server: | ||
|
||
* as in the previous case, the client side opens a new connection to a server, and the first request it sends via that | ||
connection contains the `x-wf-ee-ns: interop` HTTP header. Also, that first request is marshalled | ||
with the Java EE <-> Jakarta EE class transformer, porting the request from `javakarta` to `javax` EE namespace | ||
* the Java EE 8- server receives the request in Java EE format and handles the request normally, ignoring the | ||
`x-wf-ee-ns: interop` header. | ||
* the client receives the server response and checks it does not contain the `x-wf-ee-ns` header. So, it enables the | ||
Java EE <-> Jakarta EE class name transformer for that connection's lifetime. | ||
* from that point on, whenever the client uses the same connection, no extra header is added, and the | ||
class name transformer is always enabled, guaranteeing that the Jakarta EE 9+ classes are ported to Java EE 8- namespace | ||
on every request, and transformed back on every response | ||
|
||
The final handshake scenario is a Java EE 8- client sending a request to a EE namespace interoperable server: | ||
|
||
* client sends the request to the server in the standard way, and the request naturally can contain `javax` EE | ||
namespace classes | ||
* the server receives the request and verifies it does not contain the `x-wf-ee-ns` header. The server interprets | ||
this as an indication that the client is Java EE 8-, and it enables the class name transformer for both reading the request | ||
and writing the response back to the client. | ||
|
||
If a Jakarta EE9+ server receives a request from an EE namespace interoperable client, even if the server is not on | ||
interoperable mode it will be able to respond, because it will check the presence of the `x-wf-ee-ns: interop` | ||
header. In this case, it will apply the class name transformation to the request on read, and it will add the | ||
`x-wf-ee-ns: jakarta` header to the response on write. This allows the non-interoperable server to be able to serve | ||
requests from interoperable clients. | ||
|
||
=== Communication Across Multiple Endpoints | ||
The following table summarizes the possible scenarios where a client can | ||
communicate with a server remotely: | ||
|
||
|=== | ||
| |Java EE 8- client | Jakarta EE 9+ client | Jakarta EE 9+ namespace interoperable client | ||
|Java EE 8- server | Yes | No | Yes | ||
|Jakarta EE 9+ server | No | Yes | Yes | ||
|Jakarta EE 9+ namespace interoperable server | Yes | No | Yes | ||
|=== | ||
|
||
Notice that, in order for a Jakarta EE 9+ client to be able to communicate with a Jakarta EE 9+ interoperable server, | ||
the client must be also running on EE namespace interoperable mode. | ||
|
||
Regarding handling cases where a server is non interoperable and receives a Javax EE namespace request, the code could, | ||
in the future, be smarter and detect potential mismatches between the endpoints that will cause the | ||
communication to fail. Such as current endpoint is not EE namespace interoperable while the other end is otherwise, or | ||
even if the other end is a Java EE 8- instance. If we do so, we could print a warning indicating that the EE namespace | ||
interoperability must be enabled at this server/client, so it can establish proper communication with the remote | ||
endpoint. However, there are two options to print this warning: | ||
|
||
* verifying if the message indicates the remote endpoint is running on EE namespace interoperability mode | ||
* or catching a ClassCastException when marshalling/unmarshalling and checking if the exception message contains `"javax"` | ||
|
||
While the former option sounds more elegant. The client would not have a way of detecting if it is invoking an incompatible | ||
server, unless we change the protocol to apply a `x-wf-ee-ns:javax` header to | ||
Java 8- clients requests. Both extra actions at the two ends will result in a performance penalty. The solution | ||
we propose at this moment was designed in a way to prevent by all means any kind of overhead in the standard | ||
communication between two Jakarta EE 9+ endpoints, leaving the extra overhead to the special case of an Java EE 9+ | ||
endpoint needing to communicate with Java EE8- endpoints. | ||
|
||
[IMPORTANT] | ||
==== | ||
All servers and clients are interoperable if the communication does not involve any EE class. | ||
This might lead a user to mistakenly believe that no such configuration was needed _"before, when my code was doing one | ||
thing, but now it has changed and it no longer works"_. However, *full interoperability among the clients and servers | ||
with mixed different EE libraries (i.e, `javax` vs `jakarta` namespace) is only guaranteed when all Jakarta EE 9+ | ||
elements of that communication are running on _EE namespace interoperable mode_*. | ||
==== |