我已经获得了SOAP Web服务的WSDL
我在RAD Developer(一个与IBM Websphere一起使用的基于Eclipse的编译器)中创建了一个“自上而下,Java Bean”Web服务客户端,并自动生成了一堆JAX-WS .java模块
< / LI>以下是其中一项操作的自动生成的JAX-WS代码:
@WebMethod(operationName = "CommitTransaction", action = "http://myuri.com/wsdl/gitsearchservice/CommitTransaction")
@RequestWrapper(localName = "CommitTransaction", targetNamespace = "http://myuri.com/wsdl/gitsearchservice", className = "com.myuri.shwsclients.CommitTransaction")
@ResponseWrapper(localName = "CommitTransactionResponse", targetNamespace = "http://myuri.com/wsdl/gitsearchservice", className = "com.myuri.shwsclients.CommitTransactionResponse")
public void commitTransaction(
@WebParam(name = "requestOptions", targetNamespace = "http://myuri.com/wsdl/gitsearchservice")
RequestOptions requestOptions,
@WebParam(name = "transactionData", targetNamespace = "http://myuri.com/wsdl/gitsearchservice")
TransactionData transactionData);
问题:
“transactionData”来自大型复杂的XML数据记录。 WSDL格式与我将在Java端编写的XML完全匹配,并且完全匹配Web服务将在服务器端读取的内容。
问:如何绕过“transactionData”参数的Java序列化,在SOAP消息中发送原始XML?而不是必须读取我的XML,解析它,并逐字段打包Java“TransactionType”结构?
提前谢谢!
答案 0 :(得分:1)
我对RequestWrapper
和ResponseWrapper
注释的使用并不熟悉,但您的出站邮件最终看起来像是:
<CommitTransaction>
<requestOptions>...</requestOptions>
<transactionData>...</transactionData>
</CommitTransaction>
让我们假装它确实:)并且我们还假设TransactionData
param的XML由Source
实例表示。创建一个自定义SOAPHandler
,维护Source
的句柄:
public class TransactionDataHandler implements SOAPHandler<SOAPMessageContext> {
private final Source transactionDataSource;
public TransactionDataHandler(Source transactionDataSource) {
this.transactionDataSource = transactionDataSource;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
// no exception handling
Boolean isOutbound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (Boolean.TRUE.equals(isOutbound)) {
SOAPMessage message = context.getMessage();
SOAPBody body = message.getSOAPBody();
Node commitTransactionNode = body.getFirstChild();
Result commitTransactionResult = new DOMResult(commitTransactionNode);
TransformerFactory.newInstance().newTransformer().transform(this.transactionDataSource, commitTransactionResult);
}
return true;
}
@Override
public Set<QName> getHeaders() {
return null;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
return true;
}
@Override
public void close(MessageContext context) {
// no-op
}
}
我们的想法是转换步骤应该创建子<transactionData>
节点。您还需要一个自定义HandlerResolver
,可能类似于:
public class TransactionDataHandlerResolver implements HandlerResolver {
private final Handler transactionDataHandler;
public TransactionDataHandlerResolver(Source transactionDataSource) {
this.transactionDataHandler = new TransactionDataHandler(transactionDataSource);
}
@Override
public List<Handler> getHandlerChain(PortInfo portInfo) {
return Collections.singletonList(this.transactionDataHandler);
}
}
最后,创建一个Service
实例并挂钩XML Source
和HandlerResolver
:
Source transactionDataSource;
URL wsdlDocumentLocation;
QName serviceName;
Service service = Service.create(wsdlDocumentLocation, serviceName);
service.setHandlerResolver(new TransactionDataHandlerResolver(transactionDataSource));
从此处,您可以获得Dispatch
或端口代理并启动操作。这可能不完全适合您现有的代码/环境,但希望它能为您提供一些思考的东西......
编辑:如果您正在使用端口代理,请为第二个arg传递null
:
port.commitTransaction(requestOptions, null);