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>