由于工作的原因,接触了SDO,在研发的过程中遇到很多类型转换方面的问题,网上相应的中文资料比较少,自己总结了一些tip,希望对大家有所帮助
将一个DataObject赋予另一个同schema生成的DataObject时,报
Exception in thread "main" java.lang.ClassCastException: The feature 'ReceiveOrder's type 'ReceiveOrder' does not permit a value of type 'ReceiveOrder' at org.eclipse.emf.ecore.impl.EStructuralFeatureImpl$BasicFeatureMapEntry. validate(EStructuralFeatureImpl.java:2843) at org.eclipse.emf.ecore.util.FeatureMapUtil.createEntry(FeatureMapUtil.java:146) at org.eclipse.emf.ecore.util.BasicFeatureMap.createEntry(BasicFeatureMap.java:94) at org.eclipse.emf.ecore.util.BasicFeatureMap.set(BasicFeatureMap.java:1051) at org.eclipse.emf.ecore.util.FeatureMapUtil$FeatureValue.set(FeatureMapUtil.java:1149) at org.eclipse.emf.ecore.impl.EStructuralFeatureImpl$InternalSettingDelegateFeatureMapDelegator .dynamicSet(EStructuralFeatureImpl.java:1401) at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eDynamicSet(BasicEObjectImpl.java:709) at org.apache.tuscany.sdo.impl.DynamicDataObjectImpl.eDynamicSet(DynamicDataObjectImpl.java:160) at org.apache.tuscany.sdo.impl.DataObjectImpl.eSet(DataObjectImpl.java:1476) at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eSet(BasicEObjectImpl.java:654) at org.apache.tuscany.sdo.helper.XMLDocumentImpl.save(XMLDocumentImpl.java:204) at org.apache.tuscany.sdo.helper.XMLDocumentImpl.save(XMLDocumentImpl.java:160) at org.apache.tuscany.sdo.helper.XMLDocumentImpl.save(XMLDocumentImpl.java:167) at org.apache.tuscany.sdo.helper.XMLHelperImpl.save(XMLHelperImpl.java:168) at org.apache.tuscany.sdo.helper.XMLHelperImpl.save(XMLHelperImpl.java:130)
我们看下试验的代码:
//从字符串创造DataObject String dataObjectStr = "<m:ReceiveOrder xmlns:m=\"http://ordertomanufacturingservice.services.starflow.ro.icss.com/wsdl\">" + "<orderId>testreciiveServcice11111</orderId>" + "<customerId>String</customerId>" + "<customerName>String</customerName>" + "<orderItems>" + "<orderItem> " + "<productName>String</productName>" + "<price>3.1415926535897932384626433832795</price>" + "<quantity>String</quantity>" + "<comment>String</comment>" + "<shipDate>String</shipDate> " + "</orderItem>" + "</orderItems>" + "</m:ReceiveOrder>"; //创造第一个DataObject HelperContext scope = SDOUtil.createHelperContext(); loadTypesFromXMLSchemaStr(scope,schema3); XMLDocument xmlDoc = getXMLDocumentFromString(scope,dataObjectStr); DataObject root = xmlDoc.getRootObject(); //创造第二个DataObject HelperContext scope2 = SDOUtil.createHelperContext(); DataObject obj = createRootDataObject(scope2,schema3,"ReceiveOrder"); //将第一个DO赋予第二个DO obj = root; String xmlstr = scope2.getXMLHelper().save(obj, getNameSpaceFromSchema(schema3), "ReceiveOrder"); System.out.println(xmlstr); /** * 从字符串中获取XMLDocument对象 * @param scope * @param xmlDoc * @return * @throws IOException */ private static XMLDocument getXMLDocumentFromString(HelperContext scope, String xmlDoc) throws IOException { InputStream is = new ByteArrayInputStream(xmlDoc.getBytes()); XMLDocument result = scope.getXMLHelper().load(is); return result; } /** * 创建文档的顶层DO * @param schemaStr * @param type * @return * @throws UnsupportedEncodingException * @throws FileNotFoundException */ private static DataObject createRootDataObject(HelperContext scope,String schemaStr ,String type) throws UnsupportedEncodingException, FileNotFoundException{ loadTypesFromXMLSchemaStr(scope,schemaStr); DataFactory factory = scope.getDataFactory(); DataObject root = factory.create(getNameSpaceFromSchema(schemaStr),type); return root; }
打印结果如下:
Exception in thread "main" java.lang.ClassCastException: The feature 'ReceiveOrder's type 'ReceiveOrder' does not permit a value of type 'ReceiveOrder' at org.eclipse.emf.ecore.impl.EStructuralFeatureImpl$BasicFeatureMapEntry .validate(EStructuralFeatureImpl.java:2843) at org.eclipse.emf.ecore.util.FeatureMapUtil.createEntry(FeatureMapUtil.java:146) at org.eclipse.emf.ecore.util.BasicFeatureMap.createEntry(BasicFeatureMap.java:94) at org.eclipse.emf.ecore.util.BasicFeatureMap.set(BasicFeatureMap.java:1051) at org.eclipse.emf.ecore.util.FeatureMapUtil$FeatureValue.set(FeatureMapUtil.java:1149) at org.eclipse.emf.ecore.impl.EStructuralFeatureImpl$InternalSettingDelegateFeatureMapDelegator .dynamicSet(EStructuralFeatureImpl.java:1401) at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eDynamicSet(BasicEObjectImpl.java:709) at org.apache.tuscany.sdo.impl.DynamicDataObjectImpl.eDynamicSet(DynamicDataObjectImpl.java:160) at org.apache.tuscany.sdo.impl.DataObjectImpl.eSet(DataObjectImpl.java:1476) at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eSet(BasicEObjectImpl.java:654) at org.apache.tuscany.sdo.helper.XMLDocumentImpl.save(XMLDocumentImpl.java:204) at org.apache.tuscany.sdo.helper.XMLDocumentImpl.save(XMLDocumentImpl.java:160) at org.apache.tuscany.sdo.helper.XMLDocumentImpl.save(XMLDocumentImpl.java:167) at org.apache.tuscany.sdo.helper.XMLHelperImpl.save(XMLHelperImpl.java:168) at org.apache.tuscany.sdo.helper.XMLHelperImpl.save(XMLHelperImpl.java:130) at com.icss.ro.starflow.service.mappingservice.Test2.main(Test2.java:305)
这就奇怪了,我明明用同样的schema创建的两个对象,按照java中最基本的赋值原则,我这样直接给DO赋值也应该没错啊,百思不得其解。仔细观察发现,两个DO虽然属于同一个schema,但隶属于不同的HelperContext,问题会不会出在这里呢,我们再试验下,代码修改为:
//创造第一个DataObject HelperContext scope = SDOUtil.createHelperContext(); loadTypesFromXMLSchemaStr(scope,schema3); XMLDocument xmlDoc = getXMLDocumentFromString(scope,dataObjectStr); DataObject root = xmlDoc.getRootObject(); //创造第二个DataObject HelperContext scope2 = SDOUtil.createHelperContext(); DataObject obj = createRootDataObject(scope,schema3,"ReceiveOrder"); //将第一个DO赋予第二个DO obj = root; String xmlstr = scope.getXMLHelper().save(obj, getNameSpaceFromSchema(schema3), "ReceiveOrder"); System.out.println(xmlstr);
这时的打印结果为:
<?xml version="1.0" encoding="UTF-8"?> <tns:ReceiveOrder xmlns:tns="http://ordertomanufacturingservice.services.starflow.ro.icss.com/wsdl"> <orderId>testreciiveServcice11111</orderId> <customerId>String</customerId> <customerName>String</customerName> <orderItems> <orderItem> <productName>String</productName> <price>3.1415926535897932384626433832795</price> <quantity>String</quantity> <comment>String</comment> <shipDate>String</shipDate> </orderItem> </orderItems> </tns:ReceiveOrder>
通过这个例子,我们发现,如果要给两个DO赋值的话,它不单要隶属于同一个xsd文件的同一个类型,而且还要隶属同一个HelperConetxt,否则就要报如上的异常了。