-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix @ApplicationScoped ValueExtractors #20386
Fix @ApplicationScoped ValueExtractors #20386
Conversation
Note : this PR is based on #20382, which should be merged first. I will mark this one as draft in the meantime, even though CI passes just fine. |
1ed71ab
to
18e6feb
Compare
#20382 has been merged; I rebased this PR on |
This workflow status is outdated as a new workflow run has been triggered. |
/** | ||
* Returns true if the given class has type parameters or if its superclass or superinterfaces require a signature | ||
*/ | ||
public static boolean needsSignature(ClassInfo klass) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to remove this method? It looks orthogonal to the issue at hand?
But I'll let @mkouba decide about all this anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not orthogonal; it was used in ClientProxyGenerator
to know whether we need to create a signature for a proxy class. We used to pass the proxied class as a parameter. But that was wrong: a proxy class needing a signature is not the same as the proxied (parent) class needing a signature.
For example:
class MyClass implements Supplier<Integer> {
}
class MyClass_Proxy extends MyClass {
}
The proxied class (MyClass
) needs a signature, since it extends a parameterized type, but the proxy class (MyClass_Proxy
) doesn't.
Since this method was being misused, and the only use was in ClientProxyGenerator
, and it very much looks like internal code, I think it should be removed.
This workflow status is outdated as a new workflow run has been triggered. Failing Jobs - Building 18e6feb
Full information is available in the Build summary check run. Failures⚙️ MicroProfile TCKs Tests #- Failing: tcks/resteasy-reactive
📦 tcks/resteasy-reactive✖ 📦 tcks/resteasy-reactive/target/testsuite/tests✖
|
18e6feb
to
30f382e
Compare
The test failure in the MicroProfile TCK seems unrelated; I certainly cannot reproduce it locally. I rebased on |
I'll let @FroMage review this one as he's the author of the original code. |
Hey @FroMage , any opinion on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a closer look and the changes make sense to me.
Let's wait a few days to see if @FroMage has some feedback. If not, I'll merge.
Thanks! |
Fixes #20375.
It turns out the problem was how we generate class signatures in client proxies.
"class signatures" are the metadata in Java classes that provides un-erased type information, such as type parameters for implemented interfaces. See https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-4.html#jvms-4.7.9.1 for more information.
Some time ago, we had to add some feature to generate those class signatures in generated client proxies. IIUC, the hack was necessary for Kotlin class generation. See #10769 (comment) for more information.
However, that signature generation was incorrect: it was essentially copy-pasting the signature of the parent (proxied) class. Consequently, the generic info of the proxy class was identical to that of the proxied class. If the parent class implemented
ValueExtractor<List<?>>
, then the signature of the proxied class looked as if the proxied class implemented that interface directly, too. Which is incorrect.It gets worse, though: the proxied class appeared as if it implemented that interface... but only when querying generic-aware methods, such as
getAnnotatedInterfaces()
. When querying non-generic-aware methods, such asgetInterfaces()
, it would appear that the proxied class did not implementValueExtractor
, at least not directly.As you can imagine, that was a lot of fun to debug.
This PR changes signature generation for client proxy classes so that:
class MyClass<T> implements SomeInterface<T>
, the generated proxy has a signature that matches a declaration similar toclass MyClass_ClientProxy<T> extends MyClass<T>
. That will, at least, be consistent with the non-generic-aware class metadata.In the case of Hibernate Validator, a value extractor declared as
MyExtractor implements ValueExtractor<List<?>>
will yield a proxy without any signature at all, since the proxy does not need type parameters andMyExtractor
cannot be parameterized. Thus the Hibernate Validator test now passes.Let's see if it's enough to make all tests added in #10769 pass.