第二次调用SOAP服务触发org.w3c.dom.DOMException异常求助
嘿,这个org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR我之前做SOAP服务时也踩过坑!本质就是DOM节点被跨文档复用了——简单说,你把一个由A DOM文档创建的节点,硬塞到另一个完全不同的B DOM文档里,DOM规范可不允许这种“跨文档串门”的操作。结合你的代码,我梳理了几个最可能的触发原因:
1. setObj()里复用了旧请求的DOM节点(头号嫌疑)
看你的execute方法,每次调用都会新建new webreferences.CustomerWS.SaveNewCustomer(),这本身没问题,但如果你的setObj()方法里,存在把第一次请求生成的DOM节点直接赋值给第二次请求对象的逻辑,就会触发这个异常。
举个例子,如果setObj()里有类似这种代码:
// 第一次请求时把某个DOM节点存在全局/闭包变量里 let cachedNode = requestObject.someXmlNode; // 第二次请求时直接把这个旧节点赋值给新的请求对象 customerRequestObjTest.customerInfo = cachedNode;
这时候cachedNode属于第一次请求对应的SOAP DOM文档,而新的customerRequestObjTest属于第二次请求的新DOM文档,跨文档赋值直接就会抛出WRONG_DOCUMENT_ERR。
2. SOAP服务客户端被意外复用(上下文没隔离)
你的initServiceClient方法返回的是this.webReference.getDefaultService(),如果getDefaultService()返回的是单例实例,那多次调用时会复用同一个SOAP客户端,而客户端内部的DOM文档上下文没被正确重置,导致第二次请求时混入了第一次请求的DOM节点残留。
3. 请求对象requestObject被跨请求复用
你的createRequest方法直接返回了传入的params(也就是requestObject),如果这个requestObject是被缓存起来跨请求复用的,它内部可能持有第一次请求的DOM节点引用,第二次调用时就会把旧节点带到新的请求文档里,触发异常。
针对性修复建议
- 检查并修正
setObj()逻辑:所有赋值给customerRequestObjTest的节点,必须是当前请求上下文创建的新节点。如果需要复用旧节点的内容,要用importNode把节点导入到当前文档中,比如:// 假设oldNode是来自其他文档的节点 let currentDoc = svc.serviceClient.getDocument(); let newNode = currentDoc.importNode(oldNode, true); // true表示深拷贝 customerRequestObjTest.customerInfo = newNode; - 避免复用SOAP客户端单例:如果
getDefaultService()返回的是单例,尝试每次调用initServiceClient时创建全新的服务实例,而不是依赖默认单例。 - 确保请求对象每次都新建:在
createRequest里不要直接返回params,而是基于params的内容创建一个新对象,彻底避免残留旧的DOM引用。
内容的提问来源于stack exchange,提问作者Adrian Setniewski

