spring-integration中测试XML Transformers的一些代码:
maven:
<!-- for spring-oxm --> <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.3.1</version> <optional>true</optional> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.1.7</version> <optional>true</optional> </dependency> <dependency> <groupId>org.jibx</groupId> <artifactId>jibx-run</artifactId> <version>1.1.5</version> <optional>true</optional> </dependency> <dependency> <groupId>org.apache.xmlbeans</groupId> <artifactId>xmlbeans</artifactId> <version>2.4.0</version> <optional>true</optional> </dependency> <dependency> <groupId>org.codehaus.castor</groupId> <artifactId>castor-xml</artifactId> <version>1.3.2</version> <optional>true</optional> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <!-- spring-xml --> <dependency> <groupId>org.apache.ws.commons.schema</groupId> <artifactId>XmlSchema</artifactId> <version>1.4.7</version> <optional>true</optional> </dependency> <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> <version>1.1.1</version> <!-- 1.1.3 version is not good. --> <optional>true</optional> </dependency>
Marshaller:
@Configuration
public class XmlConfiguration {
@Bean
public CastorMarshaller marshaller() {
CastorMarshaller marshaller = new CastorMarshaller();
return marshaller;
}
}
报错日志:
10:04:43,305 INFO main handler.LoggingHandler:136 - [Payload=<?xml version="1.0" encoding="UTF-8"?> <customer><address>100 State Street</address><last-name>Smith</last-name><zip>90064</zip><first-name>John</first-name><state>CA</state><city>Los Angeles</city></customer>][Headers={timestamp=1331172283294, id=ed20763b-8061-4207-88d1-688673621b81}] createUnmarshaller() Exception in thread "main" org.springframework.integration.transformer.MessageTransformationException: failed to transform message at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:44) at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:67) ...... Caused by: org.exolab.castor.xml.MarshalException: The class for the root element 'customer' could not be found.{File: [not available]; line: 2; column: 11} at org.exolab.castor.xml.Unmarshaller.convertSAXExceptionToMarshalException(Unmarshaller.java:866) ...... Caused by: org.xml.sax.SAXException: The class for the root element 'customer' could not be found. at org.exolab.castor.xml.UnmarshalHandler.processFirstElement(UnmarshalHandler.java:890) ...
可以看出传输的对象已经正确转换成xml,但是将xml转回类的时候说根节点Customer对应的类没找到。
单独编写测试代码:
package com.apress.prospringintegration.transform;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.xml.transform.stream.StreamSource;
import org.exolab.castor.xml.Unmarshaller;
import org.xml.sax.InputSource;
public class Test {
public static void main(String[] args) throws Exception {
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
sb.append("<customer>");
sb.append("<address>100 State Street</address>");
sb.append("<last-name>Smith</last-name>");
sb.append("<zip>90064</zip>");
sb.append("<first-name>John</first-name>");
sb.append("<state>CA</state>");
sb.append("<city>Los Angeles</city>");
sb.append("</customer>");
InputStream in = new ByteArrayInputStream(sb.toString().getBytes());
Unmarshaller u = new Unmarshaller();
u.setClass(Customer.class);
Object o = u.unmarshal(new InputSource(in));
System.out.println(o.getClass());
}
}
发现,只有设置了setClass(Clazz)才能正确解析。
spring-oxm中的org.springframework.oxm.castor.CastorMarshaller类封装了org.exolab.castor.xml.Unmarshaller。单很奇怪的是,CastorMarshaller并没有封装Unmarshaller的setClass方法。
怎么回事,bug?
翻了一遍Spring 3以来所有版本的源代码,CastorMarshaller都一样。
但Google这个关键字时,第3个结果第427到430行代码是3.0版本以后没有的!
425 private Unmarshaller createUnmarshaller() {
426 Unmarshaller unmarshaller = xmlContext.createUnmarshaller();
427 if (targetClass != null) {
428 unmarshaller.setClass(targetClass);
429 unmarshaller.setClassLoader(targetClass.getClassLoader());
430 }
431 customizeUnmarshaller(unmarshaller);
432 return unmarshaller;
433 }
有了这一段代码,就可以设置CastorMarshaller的targetClass来指定转换的类。
问题来了,貌似刚才说到的这个类是很早以前版本的,那就是说3.0以后官方把这个类改掉了,是优化了,提供了替代的方法,然后还没发现吗?
[2012.6.24 10:57 补充]
将pom.xml的依赖包换成:
<dependency> <groupId>org.codehaus.castor</groupId> <artifactId>castor</artifactId> <version>1.2</version> <optional>true</optional> <scope>test</scope> </dependency> <dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId> <version>2.9.1</version> <optional>true</optional> <scope>test</scope> </dependency>