I try to get information from web service that uses PasswordText WSS type. Firstly, I test it using soapUI and successfully got data. Then I implemented authentication on Ja
Here is what worked for me. Basically, it's an application of the idea pronounced by @Joseph Rajeev Motha (although I found it elsewhere, here: https://dwuysan.wordpress.com/2012/04/02/jax-ws-wsimport-and-the-error-mustunderstand-headers-not-understood/#comment-215 ), but his answer does not provide boilerplate, and without it, the answer is pretty mysterious.
Please note that this sequence applies to the standalone case (where you publish an Endpoint
yourself).
Create a SOAPHandler
that will 'understand' the header:
public class WSSESecurityUnderstandPretender implements SOAPHandler<SOAPMessageContext> {
@Override
public Set<QName> getHeaders() {
final QName securityHeader = new QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security",
"wsse");
final Set<QName> headers = new HashSet<>();
headers.add(securityHeader);
// notify the runtime that this is handled
return headers;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
// we must return true, or else the runtime will return
// wrong wrapper element name (like makeTransfer instead of
// makeTransferResponse)
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
// we must return true, or else the runtime will return
// wrong wrapper element name (like makeTransfer instead of
// makeTransferResponse)
return true;
}
@Override
public void close(MessageContext context) {
}
}
Create a handler-chain.xml
file and put it on classpath:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains
xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<javaee:handler-chain>
<javaee:handler>
<javaee:handler-class>com.mypackage.WSSESecurityUnderstandPretender</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
Annotate your implementation class (class that is annotated with @WebService
) with a reference to the handler chain file:
@HandlerChain(file = "handler-chain.xml")
Publish your endpoint:
Endpoint endpoint = Endpoint.publish(url, impl);
handleMessage()
and handleFault()
defined by the handler must return true
. Otherwise, you will get strange errors like 'Unexpected wrapper element' because a different wrapper element name will be used.
I found the solution. Following dependencies were required:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.2.3</version>
</dependency>
Good article on this topic and some pitfalls of cxf: http://www.logicsector.com/java/how-to-create-a-wsdl-first-soap-client-in-java-with-cxf-and-maven/
You could get this error when the service does not handle the headers. The service needs to implement a SOAPHandler with a getHeaders() that would resolve the headers. For the above mentioned fault the correct implementation would be as follows
@Override
public Set<QName> getHeaders() {
QName securityHeader = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security");
HashSet<QName> headers = new HashSet<QName>();
headers.add(securityHeader);
return headers;
}
It is also possible to get this when the service is actually not secure, but the client is attempting to use security configuration (possibly using a XWSS security configuration) For this, just check the published wsdl from a browser and make sure it contains the expected security policy (append ?wsdl to its endpoint URL)
If you have this problem in project with Java 11 try to use Apache CXF 3.3.x release.
Answer below from Apache CXF FAQ:
Can CXF run with JDK/ Java 9+ (10, 11)?
Yes. CXF will support Java 9-11 with the next 3.3.x release.