-
Bug
-
Resolution: Unresolved
-
P4
-
8, 11, 17, 21, 25, 26
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
When XMLEncoder.writeObject() a bean containing a javax.swing.border.LineBorder whose lineColor is null (or any non-default combination), the resulting XML omits all of the border’s state. On decode it fall back to the bean’s default LineBorder. Even registering a PersistenceDelegate( "lineColor","thickness","roundedCorners" ) for LineBorder has no effect
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
successfully serialize Bean and its value(a LineBorader).
ACTUAL -
<?xml version="1.0" encoding="UTF-8"?>
<java version="24.0.1" class="java.beans.XMLDecoder">
<object class="LineBorderXMLSerializationTest$Bean"/>
</java>
Exception in thread "main" java.lang.RuntimeException: Color mismatch: original=null, deserialized=java.awt.Color[r=255,g=0,b=0]
at LineBorderXMLSerializationTest.main(LineBorderXMLSerializationTest.java:63)
---------- BEGIN SOURCE ----------
import javax.swing.border.LineBorder;
import java.awt.Color;
import java.beans.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
public class LineBorderXMLSerializationTest {
public static class Bean {
public final static LineBorder DEFAULT = new LineBorder(Color.RED, 2, true);
private LineBorder value;
public Bean() {this.value = DEFAULT;}
public LineBorder getValue() {return value;}
public void setValue(LineBorder value) {this.value = value;}
}
public static void main(String[] args) throws IOException {
LineBorder originalBorder = new LineBorder(null, 0, false);
Bean beanToEncode = new Bean();
beanToEncode.setValue(originalBorder);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (XMLEncoder encoder = new XMLEncoder(outputStream)) {
encoder.setPersistenceDelegate(
LineBorder.class,
new PersistenceDelegate() {
@Override
protected Expression instantiate(Object oldInstance, Encoder out) {
LineBorder lb = (LineBorder) oldInstance;
return new Expression(
lb,
lb.getClass(),
"new",
new Object[]{lb.getLineColor(),
lb.getThickness(),
lb.getRoundedCorners()}
);
}
}
);
encoder.writeObject(beanToEncode);
}
byte[] xmlData = outputStream.toByteArray();
System.out.println(new String(xmlData, StandardCharsets.UTF_8));
Bean deserializedBean;
ByteArrayInputStream inputStream = new ByteArrayInputStream(xmlData);
try (XMLDecoder decoder = new XMLDecoder(inputStream)) {
deserializedBean = (Bean) decoder.readObject();
}
LineBorder deserializedBorder = deserializedBean.getValue();
Color originalColor = originalBorder.getLineColor();
Color deserializedColor = deserializedBorder.getLineColor();
if (!Objects.equals(originalColor, deserializedColor)) {
throw new RuntimeException("Color mismatch: original=" + originalColor + ", deserialized=" + deserializedColor);
} else {
System.out.println("\nColors match.");
}
}
}
---------- END SOURCE ----------
Workaround
following way can get correct result
encoder.setPersistenceDelegate(
Bean.class,
new PersistenceDelegate() {
@Override
protected Expression instantiate(Object old, Encoder out) {
return new Expression(old, old.getClass(), "new", new Object[]{});
}
@Override
protected void initialize(Class<?> type, Object old, Object existing, Encoder out) {
super.initialize(type, old, existing, out);
Bean bOld = (Bean) old;
if (bOld.getValue() != ((Bean) existing).getValue()) {
out.writeStatement(
new Statement(old, "setValue", new Object[]{ bOld.getValue() })
);
}
}
}
);
When XMLEncoder.writeObject() a bean containing a javax.swing.border.LineBorder whose lineColor is null (or any non-default combination), the resulting XML omits all of the border’s state. On decode it fall back to the bean’s default LineBorder. Even registering a PersistenceDelegate( "lineColor","thickness","roundedCorners" ) for LineBorder has no effect
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
successfully serialize Bean and its value(a LineBorader).
ACTUAL -
<?xml version="1.0" encoding="UTF-8"?>
<java version="24.0.1" class="java.beans.XMLDecoder">
<object class="LineBorderXMLSerializationTest$Bean"/>
</java>
Exception in thread "main" java.lang.RuntimeException: Color mismatch: original=null, deserialized=java.awt.Color[r=255,g=0,b=0]
at LineBorderXMLSerializationTest.main(LineBorderXMLSerializationTest.java:63)
---------- BEGIN SOURCE ----------
import javax.swing.border.LineBorder;
import java.awt.Color;
import java.beans.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
public class LineBorderXMLSerializationTest {
public static class Bean {
public final static LineBorder DEFAULT = new LineBorder(Color.RED, 2, true);
private LineBorder value;
public Bean() {this.value = DEFAULT;}
public LineBorder getValue() {return value;}
public void setValue(LineBorder value) {this.value = value;}
}
public static void main(String[] args) throws IOException {
LineBorder originalBorder = new LineBorder(null, 0, false);
Bean beanToEncode = new Bean();
beanToEncode.setValue(originalBorder);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (XMLEncoder encoder = new XMLEncoder(outputStream)) {
encoder.setPersistenceDelegate(
LineBorder.class,
new PersistenceDelegate() {
@Override
protected Expression instantiate(Object oldInstance, Encoder out) {
LineBorder lb = (LineBorder) oldInstance;
return new Expression(
lb,
lb.getClass(),
"new",
new Object[]{lb.getLineColor(),
lb.getThickness(),
lb.getRoundedCorners()}
);
}
}
);
encoder.writeObject(beanToEncode);
}
byte[] xmlData = outputStream.toByteArray();
System.out.println(new String(xmlData, StandardCharsets.UTF_8));
Bean deserializedBean;
ByteArrayInputStream inputStream = new ByteArrayInputStream(xmlData);
try (XMLDecoder decoder = new XMLDecoder(inputStream)) {
deserializedBean = (Bean) decoder.readObject();
}
LineBorder deserializedBorder = deserializedBean.getValue();
Color originalColor = originalBorder.getLineColor();
Color deserializedColor = deserializedBorder.getLineColor();
if (!Objects.equals(originalColor, deserializedColor)) {
throw new RuntimeException("Color mismatch: original=" + originalColor + ", deserialized=" + deserializedColor);
} else {
System.out.println("\nColors match.");
}
}
}
---------- END SOURCE ----------
Workaround
following way can get correct result
encoder.setPersistenceDelegate(
Bean.class,
new PersistenceDelegate() {
@Override
protected Expression instantiate(Object old, Encoder out) {
return new Expression(old, old.getClass(), "new", new Object[]{});
}
@Override
protected void initialize(Class<?> type, Object old, Object existing, Encoder out) {
super.initialize(type, old, existing, out);
Bean bOld = (Bean) old;
if (bOld.getValue() != ((Bean) existing).getValue()) {
out.writeStatement(
new Statement(old, "setValue", new Object[]{ bOld.getValue() })
);
}
}
}
);