Register JavaType.ShallowClass codec on the Python RPC side#7441
Merged
knutwannheden merged 1 commit intomainfrom Apr 21, 2026
Merged
Conversation
When Java sends a `JavaType$ShallowClass` over RPC, the Python side had
no codec registered and threw:
No RPC codec registered on the Python side for
'org.openrewrite.java.tree.JavaType$ShallowClass'
`ShallowClass` extends `Class` in Java (and in Python's `support_types`),
so its wire format is identical — only the Java class name differs.
- `python_receiver.py`: factor out `_receive_java_type_class_fields` and
register a `JavaType$ShallowClass` codec that constructs
`JT.ShallowClass()` while consuming the same field sequence as `Class`.
- `send_queue.py`: check `isinstance(obj, JavaType.ShallowClass)` before
the `JavaType.Class` check so Python-created `ShallowClass` instances
round-trip with the correct type name.
C# already handles `JavaType$ShallowClass` — reflection-based type
resolution resolves `JavaType+ShallowClass` and `VisitType`'s
`case JavaType.Class cls:` matches via inheritance. Go collapses
`ShallowClass` into `*JavaTypeClass` by design (no separate struct);
the receive-side factory for `JavaTypeShallowClassKind` is already
registered.
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Production SB4 runs in
rewrite-pip(the Python-side RPC runtime) were failing with:JavaType.ShallowClassis the placeholder used when full JVM type resolution isn'tavailable. It's a subclass of
JavaType.Classwith the same wire shape but a distincttype name — and the Python RPC side wasn't registering a codec for it, so any Java
recipe that sent a
ShallowClassto the Python process deadlocked the queue.I audited the three non-Java RPC implementations:
rewrite-python) — no codec registered forJavaType$ShallowClass.Fixed here.
rewrite-csharp) — already works.FromJavaTypeNameByConventionresolvesorg.openrewrite.java.tree.JavaType$ShallowClassto the existing nestedOpenRewrite.Java.JavaType+ShallowClassclass via reflection, andJavaReceiver.VisitType'scase JavaType.Class cls:matchesShallowClassthroughinheritance. On the send side,
ToJavaTypeNamehandles nested types recursively andproduces the correct Java FQN.
rewrite-go) — already works for the receive path. The factory forJavaTypeShallowClassKindis registered inrewrite-go/pkg/rpc/registry.go,producing a
*JavaTypeClassinstance that the visitor dispatches toVisitClass.Go has no separate
JavaTypeShallowClassstruct by design — all class-like typescollapse to
*JavaTypeClass, so the Go process never constructs aShallowClassto send.
Summary
_receive_java_type_class_fieldsinpython_receiver.pyso the samefield-consumption logic can populate either a
JT.Classor aJT.ShallowClass.org.openrewrite.java.tree.JavaType$ShallowClasson the Python side.
isinstance(obj, JavaType.ShallowClass)check beforethe
JavaType.Classcheck insend_queue.pyso ShallowClass instances round-tripwith the correct Java type name (the existing check would have collapsed them into
JavaType$ClassbecauseShallowClassinherits fromClass).Test plan
name, and that
RpcSendQueue._get_value_type()returnsJavaType$ShallowClassfor aJT.ShallowClass()andJavaType$Classfor aJT.Class().This PR does not by itself fix the production failure — the fix lands on the
Python-side runtime and needs a
rewrite-piprelease before the next SB4 flagshiprun will pick it up.