After change data model on server side my XStream client throw Exception
com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field {fieldName}
To prevent this behavior I try to do something to ignore unknown elements. I am using XStreamMarshaller from Spring-oxm 4.0.5 and XStream 1.4.5. I known that since XStream version 1.4.5 is available method ignoreUnknownElements().
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setStreamDriver(streamDriver);
marshaller.setAutodetectAnnotations(autodetectAnnotations);
marshaller.getXStream().ignoreUnknownElements();
Above solution doesn't work and I still get mentioned exception.
I have client side model copied from server. For example:
public class Device implements Serializable {
protected String device_id;
protected String device_model_code;
protected String device_model_name;
protected String device_name;
//getters, setters
}
If I comment field for example device_model I will have Exception
com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field device_name
How can I solve my problem? How can I implement XStreamMarshaller to ignore unknown elements?
First thing is that method ignoreUnknownElements() available since XStream 1.4.5 is only for marshaling not for unmarshaling. So it doesn't work if somebody adds a new field in data model on server side.
To solve described problem you have to override protected method constructXStream() from org.springframework.oxm.xstream.XStreamMarshaller implementation:
public class CustomXStreamMarshaller extends XStreamMarshaller {
@Override
protected XStream constructXStream() {
// The referenced XStream constructor has been deprecated as of 1.4.5.
// We're preserving this call for broader XStream 1.4.x compatibility.
return new XStream() {
@Override
protected MapperWrapper wrapMapper(MapperWrapper next) {
return new MapperWrapper(next) {
@Override
public boolean shouldSerializeMember(Class definedIn, String fieldName) {
if (definedIn == Object.class) {
return false;
}
return super.shouldSerializeMember(definedIn, fieldName);
}
};
}
};
}}
You only need to use your own implementation in XStreamMarshaller declaration:
CustomXStreamMarshaller marshaller = new CustomXStreamMarshaller();
marshaller.setStreamDriver(streamDriver);
marshaller.setAutodetectAnnotations(autodetectAnnotations);