
| Key: |
XSTR-239
|
| Type: |
Bug
|
| Status: |
Closed
|
| Resolution: |
Fixed
|
| Assignee: |
Unassigned
|
| Reporter: |
Joerg Schaible
|
| Votes: |
0
|
| Watchers: |
0
|
|
If you were logged in you would be able to see more operations.
|
|
|
XStream
Created: 19/Aug/05 05:39 AM
Updated: 07/Aug/06 09:20 PM
|
|
| Component/s: |
None
|
| Affects Version/s: |
None
|
| Fix Version/s: |
1.2
|
|
|
Issue Links:
|
Supercedes
|
|
This issue supercedes:
|
|
|
|
|
|
XSTR-157
Hard to allow xstream to have a converter supporting generated classes
|
|
|
|
|
|
|
|
|
XStream seems to have trouble with CGLIB proxies based on real classes. See following effect for a proxy extending HashMap, where the ObjectName element gets lost, that is stored in the HashMap of the DelegatingHandler:
public class DelegatingHandler implements InvocationHandler, Serializable {
private final Object delegate;
public DelegatingHandler(Object delegate) {
this.delegate = delegate;
}
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
return method.invoke(delegate, args);
}
}
/**
* @throws Exception
*/
public void testCGLib() throws Exception {
final Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HashMap.class);
enhancer.setInterfaces(new Class[]{Map.class});
enhancer.setCallback(new DelegatingHandler(new HashMap()));
final Map orig = (Map)enhancer.create();
orig.put("ObjectName", new ObjectName("domain:type=xy"));
final XStream xstream = new XStream(new DomDriver());
final String xml = xstream.toXML(orig);
System.out.println(xml);
final Object clone = xstream.fromXML(xml);
System.out.println(orig);
System.out.println(clone);
assertEquals(orig.toString(), clone.toString());
}
|
|
Description
|
XStream seems to have trouble with CGLIB proxies based on real classes. See following effect for a proxy extending HashMap, where the ObjectName element gets lost, that is stored in the HashMap of the DelegatingHandler:
public class DelegatingHandler implements InvocationHandler, Serializable {
private final Object delegate;
public DelegatingHandler(Object delegate) {
this.delegate = delegate;
}
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
return method.invoke(delegate, args);
}
}
/**
* @throws Exception
*/
public void testCGLib() throws Exception {
final Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HashMap.class);
enhancer.setInterfaces(new Class[]{Map.class});
enhancer.setCallback(new DelegatingHandler(new HashMap()));
final Map orig = (Map)enhancer.create();
orig.put("ObjectName", new ObjectName("domain:type=xy"));
final XStream xstream = new XStream(new DomDriver());
final String xml = xstream.toXML(orig);
System.out.println(xml);
final Object clone = xstream.fromXML(xml);
System.out.println(orig);
System.out.println(clone);
assertEquals(orig.toString(), clone.toString());
}
|
Show » |
|
a) any direct access to a field will reference the element in the proxied instance
b) any indirect access will be delegated by the proxy
This may leed to the situation, that the values written into the stream might be from different objects.
In the above case the proxied HashMap writes a size of 0 into the stream and writes afterwards the elements of the delegate. Since those elements are written again later, XStream creates a reference. Unfortunately the readObject method of the HashMap will recognize, that it has no elements and just skip all the written values ... and all references will suddenly point to nothing.