[BEANUTILS-417] Refactor serialization methods to conform to Java Object Serialization Specification - #430
[BEANUTILS-417] Refactor serialization methods to conform to Java Object Serialization Specification#430rzanner wants to merge 7 commits into
Conversation
|
@rzanner The build is broken. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Refactors DynaProperty custom Java serialization to call defaultReadObject() / defaultWriteObject() first (per the Java Object Serialization Spec) to avoid WildFly ObjectCloner failures.
Changes:
- Reordered
DynaProperty.readObject/writeObjectto calldefaultReadObject()/defaultWriteObject()before custom serialization. - Added tests covering basic Java serialization round-trip and WildFly
ObjectClonercloning. - Added a new test-scoped WildFly dependency and updated
.gitignorefor IDE metadata.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/main/java/org/apache/commons/beanutils/DynaProperty.java | Reorders serialization hooks to satisfy spec/WildFly cloner expectations. |
| src/test/java/org/apache/commons/beanutils/DynaPropertyTest.java | Adds serialization + WildFly cloner regression tests; adjusts test property type to be indexed (List). |
| pom.xml | Adds a test dependency to obtain the WildFly/JBoss marshalling cloner classes. |
| .gitignore | Ignores IntelliJ .iml files. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { | ||
| // read default values | ||
| in.defaultReadObject(); | ||
|
|
||
| // read custom values | ||
| this.type = readAnyClass(in); | ||
| if (isMapped() || isIndexed()) { | ||
| this.contentType = readAnyClass(in); | ||
| } | ||
| // read other values | ||
| in.defaultReadObject(); | ||
| } |
There was a problem hiding this comment.
I'll just bump serialVersionUID, as supporting both serialization strategies is non-trivial to impossible.
| private void writeObject(final ObjectOutputStream out) throws IOException { | ||
| writeAnyClass(this.type,out); | ||
| // write out default | ||
| out.defaultWriteObject(); | ||
|
|
||
| // write custom values | ||
| writeAnyClass(this.type, out); | ||
| if (isMapped() || isIndexed()) { | ||
| writeAnyClass(this.contentType,out); | ||
| writeAnyClass(this.contentType, out); | ||
| } | ||
| // write out other values | ||
| out.defaultWriteObject(); | ||
| } |
There was a problem hiding this comment.
writeObject() wouldn't need to be adapted, as we want to write the new format always.
However, I'll just bump serialVersionUID, as supporting both serialization strategies is non-trivial to impossible.
| public void testSerialization() throws Exception { | ||
| ByteArrayOutputStream buffer = new ByteArrayOutputStream(); | ||
| ObjectOutputStream oos = new ObjectOutputStream(buffer); | ||
| oos.writeObject(testPropertyWithNameAndTypeAndContentType); | ||
| oos.flush(); | ||
| oos.close(); | ||
|
|
||
| ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray())); | ||
| Object obj = ois.readObject(); | ||
|
|
||
| assertEquals(testPropertyWithNameAndTypeAndContentType, obj); | ||
| } |
| <dependency> | ||
| <groupId>org.wildfly</groupId> | ||
| <artifactId>wildfly-ejb3</artifactId> | ||
| <version>9.0.2.Final</version> | ||
| <scope>test</scope> | ||
| </dependency> |
|
@rzanner |
|
Hi @garydgregory, thanks for the review - will fix the comments that make all sense to me tomorrow. For the broken build: is there a specific reason why the JBoss repos are blocked? |
|
Hello @rzanner The build is broken on GitHub and for local builds for me as well. Are you on an intranet that provides its own Maven repository (Nexus or Artifacory for exampel) before hitting the internet? That could explain why it works for you. It could also be that the JARs are blocked due to CVEs. There is no sense in creating another PR when this one is broken. |
…ed versions of DynaProperty
…s-marshalling dependency
|
Posted some fixes for the dev review comments - I needed to adapt the serialization test cases as the new version is not supporting the old serialization format anymore. |
I don't think we want to break 1.x call sites. For 2.0, that's OK, not in 1.x. This will just lead to bug reports and unhappy folks. It's OK for a new version to write a new wire format but it should be able to read the old format as well as the new one. Or, am I missing something? |
After a whole day of trying around with the serialization methods I see no solution how to support both formats to be read by the same implementation. It's Java serialization, after all, which is based on Object streams which cannot be tried to read and then read again in the correct way. 😐 The 2.x stream doesn't have the serialization methods and therefore also not this problem anymore, which is fine for me. Unfortunately it's not released, yet. |
|
How about https://docs.oracle.com/javase/8/docs/platform/serialization/spec/class.html#4100 and something like: ObjectInputStream in = new ObjectInputStream(fileStream) {
@Override
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
ObjectStreamClass desc = super.readClassDescriptor();
if (desc.getName().equals(MyClass.class.getName())) {
return ObjectStreamClass.lookup(MyClass.class);
}
return desc;
}
};? |
The order of method calls in the serialization methods in {{DynaProperty}} must be changed to conform to the Java Object Serialization Specification. In our case EJB calls in Wildfly failed as the ObjectCloner of Wildfly was checking that the {{in.defaultReadObject}} and {{out.defaultWriteObject}} methods must be called first in the {{Serializable}}'s {{readObject}} and {{writeObject}} methods.
Here are the relevant parts of the Java Object Serialization Specification:
The stacktrace we got from our Wildfly server is as follows:
Thanks for your contribution to Apache Commons! Your help is appreciated!
Before you push a pull request, review this list:
mvn; that'smvnon the command line by itself.