我有一个用于 Microsoft WCF 服务的 apache CXF 客户端,并且我正在尝试通过 MTOM 发送文件。但是,我不断收到 400,根据合作伙伴的说法,WCF 端的错误是创建 MTOM 读取器时出错
我追踪了出站消息,它看起来像这样:
INFO: Outbound Message
---------------------------
ID: 1
Address: https://someserver.com/ImportService.svc?wsdl
Encoding: UTF-8
Http-Method: POST
Content-Type: multipart/related; type="application/xop+xml"; boundary="uuid:1d46d7c9-047b-440d-928b-ab8689ab5e6f"; start="<[email protected]>"; start-info="application/soap+xml; action=\"http://tempuri.org/IImportService/UploadFile\""
Headers: {Accept=[*/*], Accept-Encoding=[gzip;q=1.0, identity; q=0.5, *;q=0], Content-Encoding=[gzip]}
Payload: --uuid:1d46d7c9-047b-440d-928b-ab8689ab5e6f
Content-Type: application/xop+xml; charset=UTF-8; type="application/soap+xml; action=\"http://tempuri.org/IImportService/UploadFile\""
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="true">
<wsse:UsernameToken wsu:Id="UsernameToken-e51a6fdd-5053-4aae-a9fb-363dde7d9e77">
<wsse:Username>[email protected]</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">mypassword</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<ns2:letterOptions xmlns="http://schemas.datacontract.org/2004/07/PublicServices.Import" xmlns:ns2="http://tempuri.org/">
<EnableQBPlanConsolidation>false</EnableQBPlanConsolidation>
<MASKSSN>true</MASKSSN>
<SRPrintedNumberofDays>2</SRPrintedNumberofDays>
<SuppressAllLetters>false</SuppressAllLetters>
<SuppressNewMemberLoginLetter>false</SuppressNewMemberLoginLetter>
<SuppressTakeOverLetterForTermed>false</SuppressTakeOverLetterForTermed>
<SuppressTerminationLetter>false</SuppressTerminationLetter>
</ns2:letterOptions>
<ns2:JobQueueType xmlns="http://schemas.datacontract.org/2004/07/PublicServices.Import" xmlns:ns2="http://tempuri.org/">Import</ns2:JobQueueType>
<Filename xmlns="http://tempuri.org/">testImport.csv</Filename>
<Action xmlns="http://www.w3.org/2005/08/addressing">http://tempuri.org/IImportService/UploadFile</Action>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:f380e4cc-225f-4b7d-bd46-6b5d607a59ca</MessageID>
<To xmlns="http://www.w3.org/2005/08/addressing">https://someserver.com/ImportService.svc?wsdl</To>
<ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
</ReplyTo>
</soap:Header>
<soap:Body>
<FileUploadMessage xmlns="http://tempuri.org/" xmlns:ns2="http://schemas.datacontract.org/2004/07/PublicServices.Import" xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/">
<FileByteStream>
<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:[email protected]"/>
</FileByteStream>
</FileUploadMessage>
</soap:Body>
</soap:Envelope>
--uuid:1d46d7c9-047b-440d-928b-ab8689ab5e6f
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>
[VERSION],1.0
[NPM],552652222,1,Basic Client,Basic Client,Bob,Z,Jones,MR,[email protected],402444555,,1234 Some street,,Omaha,NE,68123,,M,T,F,F
--uuid:1d46d7c9-047b-440d-928b-ab8689ab5e6f--
我发现很多其他人也遇到同样问题的例子: https://coderanch.com/t/224995/java/Apache-CXF-MTOM-enabled-WCF
请求 WCF 服务合约时出现 HTTP Bad Request 错误
这些都无法解决我的问题。我尝试了多个不同版本的 CXF,但所有版本都出现相同的错误。
这是调用服务的代码的合并版本:
JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
proxyFactory.setBindingId(SOAPBinding.SOAP12HTTP_MTOM_BINDING);
proxyFactory.setServiceClass(IImportService.class);
proxyFactory.setAddress(proxyEndpoint);
proxyFactory.getFeatures().add(new WSAddressingFeature());
IImportService importService = (IImportService) proxyFactory.create();
Client client = (Client) importService;
LetterOptions letterOptions = new LetterOptions();
letterOptions.setSRPrintedNumberofDays(2);
letterOptions.setMASKSSN(true);
letterOptions.setEnableQBPlanConsolidation(false);
List<Object> headerList = new ArrayList<>();
headerList.add(new Header(new QName("http://tempuri.org/", "letterOptions"),
letterOptions, new JAXBDataBinding(LetterOptions.class)));
headerList.add(new Header(new QName("http://tempuri.org/", "JobQueueType"), JobQueueType.IMPORT, new JAXBDataBinding(JobQueueType.class)));
headerList.add(new Header(new QName("http://tempuri.org/", "Filename"), "testImport.csv", new JAXBDataBinding(String.class)));
client.getRequestContext().put(Header.HEADER_LIST, headerList);
client.getEndpoint().getActiveFeatures().add(new LoggingFeature());
client.getInInterceptors().add(new GZIPInInterceptor());
client.getInInterceptors().add(new LogResponseInterceptor());
GZIPOutInterceptor outInterceptor = new GZIPOutInterceptor();
outInterceptor.setForce(true);
client.getOutInterceptors().add(outInterceptor);
Map props = new HashMap();
props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
props.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallbackHandler.class.getName());
props.put(WSHandlerConstants.USER, "[email protected]");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props);
client.getOutInterceptors().add(wssOut);
HTTPConduit conduit = (HTTPConduit) client.getConduit();
HTTPClientPolicy policy = conduit.getClient();
if(policy == null) {
policy = new HTTPClientPolicy();
}
policy.setAllowChunking(false);
FileUploadMessageReponse response = importService.uploadFile(fileUploadMessage);
一个有趣的花絮是我可以复制正在登录到 SoapUI 的相同请求,并且它工作得很好。
您似乎在使用 Apache CXF 通过 MTOM 将文件发送到 Microsoft WCF 服务时遇到问题。 400 Bad Request 错误表示服务器端出现问题,特别是在 MTOM 读取器的创建过程中。以下是一些排除故障并可能解决问题的建议:
检查WCF服务配置:
确保 WCF 服务已正确配置为处理 MTOM。这包括配置绑定并启用 MTOM。确保 WCF 服务设置为处理大型消息,因为 MTOM 通常用于优化二进制数据的传输。 验证 CXF 配置:
仔细检查 CXF 客户端配置以确保 MTOM 已正确启用。您似乎已将绑定 ID 设置为 SOAP12HTTP_MTOM_BINDING,这对于 MTOM 来说是正确的。另外,请确保服务类别和地址设置正确。 研究标头和拦截器:
确保标头、拦截器和功能设置正确。特别是,GZIPInInterceptor 和 GZIPOutInterceptor 可能会干扰 MTOM 处理,因此您可能需要尝试删除或调整它们。 出站消息中的内容类型:
对于 MTOM,出站消息中的内容类型看起来是正确的。但是,您可以通过删除 Content-Transfer-Encoding 标头进行试验,因为 MTOM 旨在更有效地处理二进制数据。 确保正确处理二进制数据:
确认二进制数据(文件内容)已正确序列化并作为 MTOM 消息的一部分发送。内容 ID (cid:[email protected]) 应与 xop:Include 元素中的引用匹配。 比较工作 SoapUI 请求:
由于请求在 SoapUI 中工作,请将工作 SoapUI 请求与 CXF 客户端生成的请求进行比较。查找可能导致 WCF 服务拒绝请求的标头、格式或内容中的任何差异。 记录和追踪:
提高 CXF 的日志记录级别以获取有关请求和响应的更多详细信息。这可能有助于深入了解导致问题的具体原因。 更新CXF版本:
检查您正在使用的 Apache CXF 版本中是否存在与 MTOM 相关的任何已知问题。考虑更新到 CXF 的最新稳定版本,看看问题是否仍然存在。 通过仔细检查这些方面并根据需要进行调整,您应该能够排除故障并解决通过 MTOM 将文件发送到 WCF 服务的问题。