gwtproject / gwt

GWT Open Source Project
http://www.gwtproject.org
1.53k stars 377 forks source link

Issue with tomcat version of GWT 2.11 for class javax.validation.Path #9942

Open PriyaKolekar opened 8 months ago

PriyaKolekar commented 8 months ago

Hi Team,

We are working on development environment with Tomcat 10 where third-party jar jakarta.validation-api.jar has been updated to tomcat specific version where package structure is changed from javax.validation to jakarta.validation.

When GWT 2.11 with tomcat specific jars(Gwt-servlet and requestfactory-server.jar) are deployed, it is trying to find javax.validation.Path with below stack trace-

Exception while dispatching incoming RPC call java.lang.NoClassDefFoundError: javax/validation/Path java.base/java.lang.Class.forName(Class.java:467)   at com.google.gwt.user.server.rpc.SerializationPolicyLoader.loadFromStream(SerializationPolicyLoader.java:217)   at com.google.gwt.user.server.rpc.jakarta.RemoteServiceServlet.loadSerializationPolicy(RemoteServiceServlet.java:98)   at com.google.gwt.user.server.rpc.jakarta.RemoteServiceServlet.doGetSerializationPolicy(RemoteServiceServlet.java:437)   at com.google.gwt.user.server.rpc.jakarta.RemoteServiceServlet.getSerializationPolicy(RemoteServiceServlet.java:251)   at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.prepareToRead(ServerSerializationStreamReader.java:505)   at com.google.gwt.user.server.rpc.jakarta.RPC.decodeRequest(RPC.java:241)

As this package has been changed in our environment to jakarta.validation.path, GWT source code is unable to find this class, giving NoClassDefFoundError.

Also we can find several references of javax.validation.Path in gwt-user and other jar source code under GWT 2.11 jars.

My queries are -

  1. Has anyone come across such error, if yes, what is workaround thats working.
  2. As javax packages are outdated and replaced by jakarta, are those references deliberately kept is there a plan to update them. Also, how this failure can be addressed.
  3. One solution I could see for older releases, is to add dependency for gwt-servlet-deps.jar, but that is not viable solution to us, as we are moving away from javax packages due to tomcat upgrade.

Any immediate help will be appreciated. Thanks!

FrankHossfeld commented 8 months ago

Are you using this dependency on the server side?

<dependency>
    <groupId>org.gwtproject</groupId>
    <artifactId>gwt-servlet-jakarta</artifactId>
    <version>2.11.0</version>
</dependency>

instead of this one:

<dependency>
    <groupId>org.gwtproject</groupId>
    <artifactId>gwt-servlet</artifactId>
    <version>2.11.0</version>
</dependency>
PriyaKolekar commented 8 months ago

Yes, we are using gwt-servlet-jakarta and requestfactory-server-jakarta versions

FrankHossfeld commented 8 months ago

Oh, yes, I see: com.google.gwt.user.server.rpc.jakarta.RPC.decodeRequest(RPC.java:241)

FrankHossfeld commented 8 months ago

Have you tried to add the java.validation.validation-api dependency?

PriyaKolekar commented 8 months ago

Yes, jakarta.validation-api dependency has been added. But now jakarta.validation-api has also moved packages from javax.validation.Path to Jakarta.validation.Path , so javax.validation.Path is no longer accessible for GWT

niloc132 commented 8 months ago

GWT-RPC does not actually use javax.validation (though request-factory does), so there is no requirement that your server use javax.validation at all - if you are seeing this error, it indicates that your own client project's RemoteService types reference javax.validation in some way (very likely as annotations on fields/properties in your DTOs/beans).

On the other hand, GWT's client APIs for validation have been deprecated for many years ("Deprecate JSR 303 Bean Validation support (javax.validation, c.g.g.validation). The code hasn’t been maintained for years."). There are other projects in the ecosystem (the main one here) that can be used instead, with updates to newer versions of the api, including jakarta support.

Assuming what I've said so far is correct, you should be able to update your own project's use of javax.validation to jakarta.validation, and this error will go away. Alternatively, you can keep sending javax.validation-decorated types, and add the validation-api jar to your server, so that it can safely deserialize those types.

Adding jakarta.validation support in a backward-compatible way is tricky - https://github.com/gwtproject/gwt/issues/9844 is filed to track this, but is looking for a volunteer/sponsor to lead it at this time.

PriyaKolekar commented 8 months ago

@niloc132, thanks for quick response. In continuation with your suggestions, I have below queries -

  1. In gwt-user.jar, several classes under package - "com.google.gwt.validation" refer javax.validation classes. Also com.google.gwt.validation.Validation.gwt.xml inherits javax.validation.Validation. Can you please let me know significance of those classes and where they are actually used.

  2. As in your reply "it indicates that your own client project's RemoteService types reference javax.validation in some way (very likely as annotations on fields/properties in your DTOs/beans).", are there any specific annotations or properties to be looked for. because directly I couldn't find references for "javax.validation" in application source code.

niloc132 commented 8 months ago
  1. gwt-user.jar must not be present on your server classpath (likewise, gwt-dev.jar must not be present), so this should be a non-issue for your server code. In your case, using RPC and jakarta, only gwt-servlet-jakarta.jar should be on the server classpath. That still has some validation apis, but they are specific to requestfactory (which is not used for RPC).
  2. Something has a field either typed as javax.validation.Path, or some type that extends from that interface. That's the best I can guess right now with the information provided.

This is the top line in the provided stack trace: https://github.com/gwtproject/gwt/blob/63dc05bfc5c96313a4fbaa149501345126c9e143/user/src/com/google/gwt/user/server/rpc/SerializationPolicyLoader.java#L217-L218

The GWT-RPC wiring here is loading the serialization policy from disk, iterating through the classes mentioned in that policy, and examining each class (without initializing it). The class that is failing, according to your error, is javax.validation.Path - by itself not serializable, but it is possible that you have subclasses that are serializable, and that you somehow are referencing those in your shared DTO types. Beyond that, without seeing code, I can't easily guess.

If this is something accidental like using raw generics or a field of type Object/Serializable (against advise of documentation and compiler warnings), your application is written to ask any possible type to be serialized, and either the app will need to be updated to be more specific (and will get smaller compiled output as a result..), or you need to make sure that the classes which the client might be using are also available to the server. If something like this is happening, correcting the code is the best option, but adding javax.validation types to the server classpath will not mean they will be used, only that they will be available. You might also look into excluding any such types, to keep them from being used as potential candidates for serialization, see RemoteService.gwt.xml's rpc.blacklist configuration property: https://github.com/gwtproject/gwt/blob/63dc05bfc5c96313a4fbaa149501345126c9e143/user/src/com/google/gwt/user/RemoteService.gwt.xml#L75-L84

niloc132 commented 1 month ago

Do you have more info on this, or can we close this as a duplicate of https://github.com/gwtproject/gwt/issues/9844?