使用Apache CXF客户端调用SOAP Web服务时遭遇415及DOM层级异常的问题求助
Let's break down your two issues one by one and walk through practical fixes:
1. Resolving the HTTP 415: Unsupported Media Type Error
This error stems from a mismatch between the Content-Type your client sends and what the server accepts. Here's the breakdown:
- SOAP 1.1 uses
text/xmlas itsContent-Type, while SOAP 1.2 usesapplication/soap+xml. - Your initial CXF client likely defaulted to SOAP 1.1 (sending
text/xml), but the server expects SOAP 1.2. Switching toSOAP12HTTP_BINDINGwas the correct first move—it tells CXF to use the SOAP 1.2Content-Type.
To confirm the server's expected SOAP version, check its WSDL:
- Look for
<soap:binding>(indicates SOAP 1.1) or<soap12:binding>(indicates SOAP 1.2) in the binding section.
2. Fixing the org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR
This error occurs when the DOM parser tries to insert a node in an invalid position. In your case, this is almost certainly caused by a SOAP namespace mismatch between your client configuration and request payload.
Looking at your outbound request payload:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="myNamespace"> soapenv:Body <a:operatioName> ... </a:operatioName> </soapenv:Body> </soapenv:Envelope>
You're using the SOAP 1.1 namespace (http://schemas.xmlsoap.org/soap/envelope/) in your Envelope, but you configured the client to use SOAP 1.2 binding. SOAP 1.2 requires the Envelope to use the namespace http://www.w3.org/2003/05/soap-envelope. This mismatch confuses CXF's DOM processing, leading to the hierarchy error.
Here's how to fix this:
Step 1: Properly Configure CXF Client for SOAP 1.2
If you're using code to create the client:
import javax.xml.ws.soap.SOAPBinding; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; // Initialize the factory JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(DummyImpl.class); factory.setAddress("myHostName"); // Explicitly set SOAP 1.2 binding factory.setBindingId(SOAPBinding.SOAP12HTTP_BINDING); // Create the client instance DummyImpl client = (DummyImpl) factory.create();
If using Spring XML configuration:
<jaxws:client id="myServiceClient" serviceClass="com.yourpackage.DummyImpl" address="myHostName"> <jaxws:binding> <soap:soap-binding version="1.2" mtom-enabled="false"/> </jaxws:binding> </jaxws:client>
Step 2: Correct the SOAP Envelope Namespace
Once configured for SOAP 1.2, CXF will automatically generate the Envelope with the correct namespace. If you're manually constructing payloads (not recommended with CXF), update it to use the SOAP 1.2 namespace:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:a="myNamespace"> <soapenv:Body> <a:operatioName>...</a:operatioName> </soapenv:Body> </soapenv:Envelope>
Step 3: Fix the SOAPAction Header for SOAP 1.2
In SOAP 1.2, the SOAPAction is optional and passed as an action parameter in the Content-Type header. Your current request has an empty action="", which may confuse the server. If the server expects a specific SOAPAction:
- Update the
Content-Typeheader to include it, e.g.,application/soap+xml; charset=UTF-8;action="mySoapAction" - Or configure CXF to set it via an interceptor:
client.getOutInterceptors().add(new AbstractPhaseInterceptor<Message>(Phase.WRITE) { @Override public void handleMessage(Message message) throws Fault { Map<String, List<String>> headers = (Map<String, List<String>>) message.get(Message.PROTOCOL_HEADERS); headers.put("SOAPAction", Collections.singletonList("mySoapAction")); // Update Content-Type with the correct action parameter headers.put("Content-Type", Collections.singletonList("application/soap+xml; charset=UTF-8;action=\"mySoapAction\"")); } });
Step 4: Check Custom Interceptors or DOM Manipulation
If you have custom interceptors that modify the request DOM, ensure they're not inserting nodes in invalid positions (e.g., adding elements directly under the Envelope instead of the Body). Temporarily disable these interceptors to see if the error resolves—if it does, debug the interceptor's DOM logic.
Step 5: Verify JAXB Configuration (If Applicable)
If using JAXB to map Java objects to XML, ensure your annotations don't introduce namespace conflicts. Confirm your service's operation elements use the correct namespace (myNamespace) and don't clash with the SOAP Envelope namespace.
内容的提问来源于stack exchange,提问作者TSSK

