问题
I generated client java objects using JAX-WS RI. I am trying to make a SOAP request to a web service. Service requires authentication in the header which looks like below:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<xsd:authHeader>
<xsd:user>username@gmail.com</xsd:user>
<xsd:password>password1</xsd:password>
</xsd:authHeader>
</soapenv:Header>
<soapenv:Body>
<ns:searchAssetsParam>
<ns:includeSubfolders>true</ns:includeSubfolders>
<ns:resultsPage>2</ns:resultsPage>
</ns:searchAssetsParam>
</soapenv:Body>
</soapenv:Envelope>
The generated java objects have methods for calling the service, creating the objects and constructing the header. But, I am having trouble setting the header while making the call.
Here's the code that I am using:
IpsApiService service = new IpsApiService();
IpsApiPortType port = service.getIpsApiSoapPort();
SearchAssetsParam searchAssetsParam = buildSearchAssetsParam();
SearchAssetsReturn response = port.searchAssets(searchAssetsParam);
buildSearchAssetsParam() constructs the request object. I created the header object as follows:
AuthHeader header = new AuthHeader();
header.setUser("username@gmail.com");
header.setPassword("password1");
How do I set this AuthHeader to the service request?
Thanks, Venu
回答1:
Once I had the same problem. I needed to modify the JAX-WS
web service SOAP header at every request. To solve this problem I have created a handler like this:
public class MyHandler implements SOAPHandler<SOAPMessageContext> {
private static final Logger LOGGER = LoggerFactory.getLogger(MyHandler.class);
private String username;
private String password;
@Override
public boolean handleMessage(SOAPMessageContext context) {
try {
SOAPMessage message = context.getMessage();
SOAPHeader header = message.getSOAPHeader();
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
if (header == null) {
header = envelope.addHeader();
}
QName qNameUserCredentials = new QName("https://your.target.namespace/", "UserCredentials");
SOAPHeaderElement userCredentials = header.addHeaderElement(qNameUserCredentials);
QName qNameUsername = new QName("https://your.target.namespace/", "Username");
SOAPHeaderElement username = header.addHeaderElement(qNameUsername );
username.addTextNode(this.username);
QName qNamePassword = new QName("https://your.target.namespace/", "Password");
SOAPHeaderElement password = header.addHeaderElement(qNamePassword);
password.addTextNode(this.password);
userCredentials.addChildElement(username);
userCredentials.addChildElement(password);
message.saveChanges();
//TODO: remove this writer when the testing is finished
StringWriter writer = new StringWriter();
message.writeTo(new StringOutputStream(writer));
LOGGER.debug("SOAP message: \n" + writer.toString());
} catch (SOAPException e) {
LOGGER.error("Error occurred while adding credentials to SOAP header.", e);
} catch (IOException e) {
LOGGER.error("Error occurred while writing message to output stream.", e);
}
return true;
}
//TODO: remove this class after testing is finished
private static class StringOutputStream extends OutputStream {
private StringWriter writer;
public StringOutputStream(StringWriter writer) {
this.writer = writer;
}
@Override
public void write(int b) throws IOException {
writer.write(b);
}
}
@Override
public boolean handleFault(SOAPMessageContext context) {
LOGGER.debug("handleFault has been invoked.");
return true;
}
@Override
public void close(MessageContext context) {
LOGGER.debug("close has been invoked.");
}
@Override
public Set<QName> getHeaders() {
LOGGER.debug("getHeaders has been invoked.");
return null;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
It adds the needed parameters to my SOAP
header and it is invoked on every request. All you need to do is to modify handleMessage
method to suit your needs.
回答2:
It works for me by overriding the public void setAttribute(String namespace, String localName, String value)
method.
import javax.xml.namespace.QName;
import org.apache.axis.Constants;
import org.apache.axis.message.SOAPHeaderElement;
@SuppressWarnings("serial")
public class ADESHeaderElement extends SOAPHeaderElement
{
public ADESHeaderElement(QName qname, Object value)
{
super(qname, value);
}
@Override
public void setAttribute(String namespace, String localName, String value)
{
if (!Constants.ATTR_MUST_UNDERSTAND.equals(localName))
{ // Or any other attribute name you'd want to avoid
super.setAttribute(namespace, localName, value);
}
}
}
Create header element like this:
ADESHeaderElement custheader = new ADESHeaderElement(qname, clientserv);
custheader.setActor(null);
回答3:
When you create your service from classess generated by cxf, add custom interceptor
Service service = new MyService(wsdlURL, new QName("http://myservice.com/MyService/", "MyService"));
MyPort port = service.getMyPort();
Client client = ClientProxy.getClient(port);
// adding interceptor programmatically
client.getOutInterceptors().add(new MyHeaderHandler());
Your can extend AbstractSoapInterceptor to implement your custom interceptor to handle message.
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.jaxb.JAXBDataBinding;
import org.apache.cxf.phase.Phase;
import com.rpc.core.utils.DomainContext;
public class MyHeaderHandler extends AbstractSoapInterceptor {
/**
* Constructor
*/
public MyHeaderHandler() {
super(Phase.PRE_LOGICAL);
}
@Override
public void handleMessage(org.apache.cxf.binding.soap.SoapMessage message) throws org.apache.cxf.interceptor.Fault {
try {
message.getHeaders().add(new Header(new QName("MyCustomHeader"),"value", new JAXBDataBinding(String.class)));
} catch (JAXBException e) {
e.printStackTrace();
}
};
}
}
回答4:
Yes, I did the same that Rangappa Tungal, following this example:
Service w = new ServiceLocator();
ServiceSoap ws = new ServiceSoapStub(new URL(w.getServiceSoapAddress()),w); Stub mystub = (Stub) ws;
AuthHeader up = new AuthHeader("user","pass");
mystub.setHeader("namespace", "AuthHeader", up);
ws.get***();
Link to the example!
来源:https://stackoverflow.com/questions/11956562/how-to-add-soap-header-when-making-a-soap-request-using-the-java-objects-generat