hlleb-lizunkou opened a new issue, #3826:
URL: https://github.com/apache/fory/issues/3826

   ### Search before asking
   
   - [x] I had searched in the [issues](https://github.com/apache/fory/issues) 
and found no similar issues describing this exact failure (related: #3621, but 
that covers a different symptom and its fix doesn't cover this case — see 
below).
   
   ### Version
   
   1.2.0, 1.3.0 (not reproducible on 1.1.0)
   
   ### Component(s)
   
   Java
   
   ### Minimal reproduce step
   
   ```java
   import org.apache.fory.Fory;
   import org.apache.fory.ThreadSafeFory;
   import org.apache.fory.config.Language;
   import org.hibernate.collection.spi.PersistentSet;
   
   import java.util.HashSet;
   import java.util.Set;
   
   public class Repro {
     public static class Holder {
       Set<String> tags;
     }
   
     public static void main(String[] args) {
       ThreadSafeFory fory = Fory.builder()
           .withLanguage(Language.JAVA)
           .withRefTracking(true)
           .requireClassRegistration(false)
           .buildThreadSafeFory();
   
       HashSet<String> backing = new HashSet<>();
       backing.add("a");
       backing.add("b");
   
       Holder holder = new Holder();
       // any Set/Collection impl that is (a) unregistered, (b) not a java.util 
builtin, and
       // (c) has instance fields beyond its elements should reproduce this
       holder.tags = new PersistentSet<>(null, backing);
   
       byte[] bytes = fory.serialize(holder);
       fory.deserialize(bytes); // throws
     }
   }
   ```
   
   `org.hibernate.collection.spi.PersistentSet` is from 
`org.hibernate.orm:hibernate-core` (used here as a real-world example of a 
`Set` implementation carrying extra instance state alongside its elements — 
session, role, key, dirty flags, etc.).
   
   ### What did you expect to see?
   
   Either:
   
   1. The unregistered `Set` implementation round-trips (as it does on 
fory-core 1.1.0), or
   2. A clear, actionable error at serialize or deserialize time, rather than 
an internal `ClassCastException` surfacing from generated code.
   
   ### What did you see instead?
   
   ```
   org.apache.fory.exception.DeserializationException: Deserialize failed, read 
objects are: [Holder, null]
   Caused by: java.lang.ClassCastException: class 
org.hibernate.collection.spi.PersistentSetForyRefCodecCompatible1_0 cannot be 
cast to class org.apache.fory.serializer.collection.CollectionLikeSerializer 
(org.hibernate.collection.spi.PersistentSetForyRefCodecCompatible1_0 is in 
unnamed module of loader 
org.apache.fory.util.ClassLoaderUtils$ByteArrayClassLoader; 
org.apache.fory.serializer.collection.CollectionLikeSerializer is in unnamed 
module of loader 'app')
        at 
org.hibernate.collection.spi.PersistentSetForyRefCodecCompatible1_0.readCollection$(PersistentSetForyRefCodecCompatible1_0.java)
        at 
org.hibernate.collection.spi.PersistentSetForyRefCodecCompatible1_0.readFields3$(PersistentSetForyRefCodecCompatible1_0.java)
        at 
org.hibernate.collection.spi.PersistentSetForyRefCodecCompatible1_0.read(PersistentSetForyRefCodecCompatible1_0.java)
        at 
org.apache.fory.context.ReadContext.readDataInternal(ReadContext.java)
        at org.apache.fory.context.ReadContext.readNonRef(ReadContext.java)
        at org.apache.fory.context.ReadContext.readRef(ReadContext.java)
        at org.apache.fory.Fory.deserialize(Fory.java)
   ```
   
   The same generated-code pattern appears at the enclosing bean's own 
field-read site, not just inside `PersistentSet`'s codec:
   
   ```java
   // generated for Holder.tags (declared java.util.Set<String>)
   private Object readCollection(ReadContext readContext, MemoryBuffer 
memoryBuffer) {
       CollectionLikeSerializer collectionSerializer =
           (CollectionLikeSerializer) _f_typeResolver.readTypeInfo(readContext, 
setTypeInfoHolder).getSerializer();
       ...
   }
   ```
   
   ### Root cause (as far as I could determine)
   
   The generated field-read code for a `Set`/`Collection`-typed field 
unconditionally casts whatever serializer resolves for the field's concrete 
runtime type to `CollectionLikeSerializer`. Because `PersistentSet` is 
unregistered and has instance fields beyond its Set elements, its own 
serializer is built via `CompatibleCodecBuilder` and extends 
`GeneratedCompatibleSerializer` — a plain bean codec that does **not** 
implement `CollectionLikeSerializer`. The cast above then fails.
   
   Bisected by pinning only the `fory-core` dependency version against the same 
reproduction:
   
   - `1.1.0` — passes (a single non-"Compatible" codec is generated and shared 
between read and write for the concrete class, so no such cast happens against 
a bean codec)
   - `1.2.0` — fails with the exact exception above
   - `1.3.0` — fails with the exact exception above
   
   This lines up with the 1.2.0 release note "default compatible mode for 
native serialization" as the likely point where read-time codec selection 
changed for fields like this.
   
   ### Anything else?
   
   This looks like the same underlying gap as #3621 (COMPATIBLE mode 
mishandling unregistered, non-`java.util` Collection/Map implementations), 
surfacing with a different symptom — a hard `ClassCastException` here instead 
of silent data loss there. The fix that closed #3621 (#3628) only special-cased 
containers implementing `Externalizable`; `PersistentSet` (and presumably other 
custom collection wrappers carrying their own extra state) is not 
`Externalizable`, so it still falls into the same general gap.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to