naiveallen opened a new issue, #3832:
URL: https://github.com/apache/fory/issues/3832

   ### Search before asking
   
   - [x] I had searched in the [issues](https://github.com/apache/fory/issues) 
and found no similar issues.
   
   
   ### Version
   
   - Fory version: 0.15.0
   - JDK: 21
   - Language: Java
   
   ### Component(s)
   
   Java
   
   ### Minimal reproduce step
   
   When using Fory with withCompatible(true) and @ForyField annotations, adding 
a new field to a class breaks backward compatibility. Specifically, when the 
producer (new code with the extra field) serializes data, and the consumer (old 
code without the extra field) tries to deserialize it, a ClassCastException is 
thrown.
   
   The issue occurs when the extra field's type is a class that is already 
registered in the consumer's Fory instance (e.g., the consumer already has 
another field of the same type).
   
   ```java
   import lombok.Data;
   import org.apache.fory.Fory;
   import org.apache.fory.config.Language;
   import org.apache.fory.annotation.ForyField;
   
   // ---- Shared class, registered in both producer and consumer ----
   
   @Data
   public class Address {
       @ForyField(id = 1, nullable = true)
       private String city;
   
       @ForyField(id = 2, nullable = true)
       private String zip;
   }
   
   // ---- Consumer version: 3 fields, already has an Address field ----
   
   @Data
   public class UserV1 {
       @ForyField(id = 1)
       private Long id;
   
       @ForyField(id = 2, nullable = true)
       private String name;
   
       @ForyField(id = 3, nullable = true)
       private Address homeAddress;  // Address is already registered
   }
   
   // ---- Producer version: 4 fields, added another Address field ----
   
   @Data
   public class UserV2 {
       @ForyField(id = 1)
       private Long id;
   
       @ForyField(id = 2, nullable = true)
       private String name;
   
       @ForyField(id = 3, nullable = true)
       private Address homeAddress;
   
       @ForyField(id = 4, nullable = true)
       private Address workAddress;  // new field, same type as homeAddress
   }
   ``` 
   
   ```java
   // ---- Producer Fory: registers UserV2 + Address ----
   Fory producerFory = Fory.builder()
           .withLanguage(Language.JAVA)
           .withCompatible(true)
           .requireClassRegistration(true)
           .build();
   producerFory.register(UserV2.class);
   producerFory.register(Address.class);
   
   // ---- Consumer Fory: registers UserV1 + Address (old code) ----
   Fory consumerFory = Fory.builder()
           .withLanguage(Language.JAVA)
           .withCompatible(true)
           .requireClassRegistration(true)
           .build();
   consumerFory.register(UserV1.class);
   consumerFory.register(Address.class);
   
   // ---- Serialize with producer (new code) ----
   UserV2 user = new UserV2();
   user.setId(1L);
   user.setName("Alice");
   
   Address home = new Address();
   home.setCity("NYC");
   home.setZip("10001");
   user.setHomeAddress(home);
   
   Address work = new Address();   // non-null value for the new field
   work.setCity("SF");
   work.setZip("94000");
   user.setWorkAddress(work);
   
   byte[] bytes = producerFory.serialize(user);
   
   // ---- Deserialize with consumer (old code) — throws ClassCastException ----
   UserV1 result = (UserV1) consumerFory.deserialize(bytes);
   ``` 
   
   
   
   
   ### What did you expect to see?
   
   With withCompatible(true), the consumer (old code with 3 fields) should be 
able to deserialize data serialized by the producer (new code with 4 fields). 
The extra workAddress field should be skipped (read and discarded), and the id, 
name, and homeAddress fields should be correctly deserialized.
   
   ### What did you see instead?
   
   org.apache.fory.exception.DeserializationException: Failed to deserialize 
input
       at org.apache.fory.Fory.deserialize(Fory.java:893)
       at org.apache.fory.Fory.deserialize(Fory.java:807)
       ...
   
   Caused by: java.lang.ClassCastException: class Address cannot be cast to 
class org.apache.fory.serializer.UnknownClass$UnknownStruct
       at 
UserV2ForyCodecMetaShared4_0.readFields2$(UserV2ForyCodecMetaShared4_0.java:149)
       at 
UserV2ForyCodecMetaShared4_0.read(UserV2ForyCodecMetaShared4_0.java:162)
       at org.apache.fory.Fory.readDataInternal(Fory.java:1065)
       at org.apache.fory.Fory.deserialize(Fory.java:889)
       ...
   
   ### Anything Else?
   
   - The issue does not occur when the extra field's value is null.
   - The issue is not specific to the Address type — any registered class used 
as the new field type triggers the same error.
   - This is a critical issue for rolling deployments: when a new field is 
added (even reusing an existing registered type), all services that deserialize 
the data must be updated simultaneously, which defeats the purpose of 
withCompatible(true).
   
   ### Are you willing to submit a PR?
   
   - [ ] I'm willing to submit a PR!


-- 
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