Spring Object/XML Marshalling support providing generic interfaces for converting Java objects to XML and vice versa
The XStream implementation provides XML marshalling and unmarshalling using the XStream library. It offers an alternative to JAXB with different configuration options, security controls, and converter-based customization.
The main XStream implementation class that extends AbstractMarshaller and provides XStream-based XML processing.
public class XStreamMarshaller extends AbstractMarshaller implements BeanClassLoaderAware, InitializingBean {
// Configuration Methods
public void setSupportedClasses(Class<?>... supportedClasses);
public void setTypePermissions(TypePermission... typePermissions);
public void setConverters(ConverterMatcher... converters);
public void setMarshallingStrategy(MarshallingStrategy marshallingStrategy);
public void setMode(int mode);
public void setAliases(Map<String, ?> aliases);
public void setAliasesByType(Map<Class<?>, String> aliasesByType);
public void setFieldAliases(Map<String, String> fieldAliases);
public void setUseAttributeFor(Map<?, ?> useAttributeFor);
public void setUseAttributeForTypes(Class<?>... useAttributeForTypes);
public void setImplicitCollections(Map<Class<?>, String> implicitCollections);
public void setOmittedFields(Map<Class<?>, String> omittedFields);
public void setStreamDriver(HierarchicalStreamDriver streamDriver);
public void setEncoding(String encoding);
public void setClassLoader(ClassLoader classLoader);
public void setAutodetectAnnotations(boolean autodetectAnnotations);
public void setReflectionProvider(ReflectionProvider reflectionProvider);
public void setMapperWrappers(Class<? extends MapperWrapper>... mapperWrappers);
// Security Methods - Type permissions and supported classes provide security controls
// Inherited methods
public boolean supports(Class<?> clazz);
public void marshal(Object graph, Result result) throws IOException, XmlMappingException;
public Object unmarshal(Source source) throws IOException, XmlMappingException;
}import org.springframework.oxm.xstream.XStreamMarshaller;
XStreamMarshaller marshaller = new XStreamMarshaller();
// Specify supported classes for security
marshaller.setSupportedClasses(Customer.class, Order.class, Product.class);
// Initialize the marshaller
marshaller.afterPropertiesSet();XStream requires explicit security configuration to prevent deserialization vulnerabilities:
import com.thoughtworks.xstream.security.TypePermission;
import com.thoughtworks.xstream.security.WildcardTypePermission;
XStreamMarshaller marshaller = new XStreamMarshaller();
// Option 1: Use supported classes (recommended)
marshaller.setSupportedClasses(Customer.class, Order.class);
// Option 2: Use type permissions for more granular control
TypePermission[] permissions = {
new WildcardTypePermission(new String[]{"com.example.model.**"}),
new WildcardTypePermission(new String[]{"java.util.**"})
};
marshaller.setTypePermissions(permissions);
// Security is handled through type permissions and supported classes
marshaller.afterPropertiesSet();Customize XML element names and structure:
import java.util.HashMap;
import java.util.Map;
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setSupportedClasses(Customer.class, Order.class);
// Class aliases (changes root element name)
Map<String, Class<?>> aliases = new HashMap<>();
aliases.put("customer", Customer.class);
aliases.put("order", Order.class);
marshaller.setAliases(aliases);
// Type-based aliases
Map<Class<?>, String> aliasesByType = new HashMap<>();
aliasesByType.put(Customer.class, "customer");
marshaller.setAliasesByType(aliasesByType);
// Field aliases (changes property names)
Map<String, String> fieldAliases = new HashMap<>();
fieldAliases.put("Customer.firstName", "fname");
fieldAliases.put("Customer.lastName", "lname");
marshaller.setFieldAliases(fieldAliases);
marshaller.afterPropertiesSet();Configure which fields should be XML attributes instead of elements:
Map<String, Class<?>> useAttributeFor = new HashMap<>();
useAttributeFor.put("Customer.id", String.class);
useAttributeFor.put("Order.status", String.class);
marshaller.setUseAttributeFor(useAttributeFor);
// Or specify by type
marshaller.setUseAttributeForTypes(Long.class, Integer.class);Configure implicit collections to avoid wrapper elements:
Map<Class<?>, String> implicitCollections = new HashMap<>();
implicitCollections.put(Order.class, "items");
implicitCollections.put(Customer.class, "addresses");
marshaller.setImplicitCollections(implicitCollections);Implement custom conversion logic for specific types:
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class DateConverter implements Converter {
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
@Override
public boolean canConvert(Class type) {
return Date.class.isAssignableFrom(type);
}
@Override
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {
Date date = (Date) source;
writer.setValue(dateFormat.format(date));
}
@Override
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
try {
return dateFormat.parse(reader.getValue());
} catch (ParseException e) {
throw new ConversionException("Cannot parse date", e);
}
}
}
// Configure marshaller with custom converter
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setSupportedClasses(Customer.class);
marshaller.setConverters(new DateConverter());
marshaller.afterPropertiesSet();Configure different XML processing drivers:
import com.thoughtworks.xstream.io.xml.StaxDriver;
import com.thoughtworks.xstream.io.xml.DomDriver;
// Use StAX driver for better performance
marshaller.setStreamDriver(new StaxDriver());
// Or use DOM driver for DOM processing
marshaller.setStreamDriver(new DomDriver());import org.springframework.oxm.xstream.XStreamMarshaller;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.StringWriter;
import java.io.StringReader;
// Configure marshaller
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setSupportedClasses(Customer.class);
marshaller.afterPropertiesSet();
// Marshal object to XML
Customer customer = new Customer("John", "Doe");
StringWriter writer = new StringWriter();
marshaller.marshal(customer, new StreamResult(writer));
String xml = writer.toString();
// Unmarshal XML to object
StringReader reader = new StringReader(xml);
Customer unmarshalled = (Customer) marshaller.unmarshal(new StreamSource(reader));import java.util.HashMap;
import java.util.Map;
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setSupportedClasses(Customer.class, Order.class);
// Configure aliases
Map<String, Class<?>> aliases = new HashMap<>();
aliases.put("customer", Customer.class);
aliases.put("order", Order.class);
marshaller.setAliases(aliases);
// Configure attributes
Map<String, Class<?>> useAttributeFor = new HashMap<>();
useAttributeFor.put("Customer.id", Long.class);
marshaller.setUseAttributeFor(useAttributeFor);
// Configure encoding
marshaller.setEncoding("UTF-8");
marshaller.afterPropertiesSet();
// Use marshaller
Customer customer = new Customer();
customer.setId(123L);
customer.setFirstName("John");
StringWriter writer = new StringWriter();
marshaller.marshal(customer, new StreamResult(writer));
// Results in: <customer id="123"><firstName>John</firstName></customer>try {
Customer customer = new Customer();
StringWriter writer = new StringWriter();
marshaller.marshal(customer, new StreamResult(writer));
} catch (MarshallingFailureException e) {
System.err.println("Marshalling failed: " + e.getMessage());
Throwable cause = e.getCause();
if (cause instanceof ConversionException) {
System.err.println("XStream conversion error: " + cause.getMessage());
}
}Utility converter for handling unregistered types:
public class CatchAllConverter implements Converter {
public boolean canConvert(Class type);
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context);
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context);
}XStream has known security vulnerabilities when deserializing untrusted XML. Always:
setSupportedClasses() to whitelist allowed classessetTypePermissions() for granular control// Secure configuration example
XStreamMarshaller marshaller = new XStreamMarshaller();
// Explicitly allow only specific classes
marshaller.setSupportedClasses(
Customer.class,
Order.class,
String.class,
java.util.Date.class,
java.util.ArrayList.class
);
// Security is handled through type permissions and supported classes
marshaller.afterPropertiesSet();import org.springframework.oxm.xstream.XStreamMarshaller;
import org.springframework.oxm.xstream.CatchAllConverter;
import org.springframework.oxm.MarshallingFailureException;
import org.springframework.oxm.UnmarshallingFailureException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.security.TypePermission;
import com.thoughtworks.xstream.security.WildcardTypePermission;
import com.thoughtworks.xstream.MarshallingStrategy;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.util.Map;
import java.util.HashMap;<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="supportedClasses">
<list>
<value>com.example.Customer</value>
<value>com.example.Order</value>
</list>
</property>
<property name="aliases">
<map>
<entry key="customer" value="com.example.Customer"/>
<entry key="order" value="com.example.Order"/>
</map>
</property>
<property name="secureProcessing" value="true"/>
</bean>@Configuration
public class XStreamConfig {
@Bean
public XStreamMarshaller xstreamMarshaller() {
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setSupportedClasses(Customer.class, Order.class);
Map<String, Class<?>> aliases = new HashMap<>();
aliases.put("customer", Customer.class);
marshaller.setAliases(aliases);
marshaller.setSecureProcessing(true);
return marshaller;
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework--spring-oxm