I have created a SOAP client to an external web service using CXF 2.7.6
with a WSDL-first approach. I've generated my client classes and used
Spring to instantiate my SOAP client.
I am required to pass a username and password for injection into the
SOAP headers, and it is necessary to pick up that username and password
dynamically for each web service call. In the client code the SOAP
headers are not yet accessible. I wrote an Interceptor to populate the
SOAP headers and used DOM to do it.
To make the parameters available to my Interceptor, I used the CXF
Request Context. According to the documentation this can be made thread
safe by setting thread.local.request.context to true.
My question is whether this could result in a performance bottlekneck.
Does this result in all messages synchronizing against the same request
context object? If so, is there another approach in CXF that would
avoid this?
In the CXF client I put the user name and password into the CXF context
like this:
private void passUserNameAndPassword(String userName, String password) {
Client cxfClient = ClientProxy.getClient(myClient);
// Per CXF documentation the following setting will make the context
thread safe:
if(!"true".equals(cxfClient.getRequestContext().get("thread.local.reques
t.context"))) {
cxfClient.getRequestContext().put("thread.local.request.context",
"true");
}
// Now we can pass the credentials safely
cxfClient.getRequestContext().put("userName", userName);
cxfClient.getRequestContext().put("password", password);
}
My interceptor then pulls it out and puts it into the SOAP headers. I
include the whole thing here in case it is useful to others.
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import
org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class SoapHeadersInterceptor extends AbstractSoapInterceptor
{
private final static org.slf4j.Logger logger = org.slf4j.LoggerFactory
.getLogger(SoapHeadersInterceptor.class);
public SoapHeadersInterceptor()
{
super(Phase.PRE_STREAM);
addBefore(SoapPreProtocolOutInterceptor.class.getName());
}
@Override
public void handleMessage(SoapMessage msg) throws Fault
{
logger.info("Called SoapHeadersInterceptor.handleMessage()!");
logger.info("SoapMessage enumeration");
Set<Entry<String,Object>> entrySet =msg.entrySet();
Iterator <Entry<String,Object>> sit = entrySet.iterator();
String userName=null;
String password=null;
while(sit.hasNext()) {
Entry<String,Object> nextEntry= sit.next();
logger.info("Entry key: "+nextEntry.getKey()+", value:
"+nextEntry.getValue());
if("userName".equals(nextEntry.getKey())) {
userName=(String)nextEntry.getValue();
}
if("password".equals(nextEntry.getKey())) {
password=(String)nextEntry.getValue();
}
}
List<Header> headers = msg.getHeaders();
Document d = DOMUtils.createDocument();
Element userNameElement = d.createElement("wsse:Username");
userNameElement.setTextContent(userName);
logger.info("Setting userName to " + userName);
Element passwordElement = d.createElement("wsse:Password");
passwordElement.setTextContent(password);
logger.debug("Setting password to " + password);
Element token = d.createElement("wsse:UsernameToken");
Element security = d.createElementNS(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-sece
xt-1.0.xsd",
"wsse:Security");
security.appendChild(token);
token.appendChild(userNameElement);
token.appendChild(passwordElement);
SoapHeader securityHeader = new SoapHeader(new QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-sece
xt-1.0.xsd",
"wsse:Security"), security);
securityHeader.setMustUnderstand(true);
headers.add(securityHeader);
}
}
Thanks for any insight you can offer.
David
--
WARNING
-------
This electronic message and its attachments may contain confidential,
proprietary or legally privileged information, which is solely for the use of
the intended recipient. No privilege or other rights are waived by any
unintended transmission or unauthorized retransmission of this message. If you
are not the intended recipient of this message, or if you have received it in
error, you should immediately stop reading this message and delete it and all
attachments from your system. The reading, distribution, copying or other use
of this message or its attachments by unintended recipients is unauthorized and
may be unlawful. If you have received this e-mail in error, please notify the
sender.
AVIS IMPORTANT
--------------
Ce message electronique et ses pieces jointes peuvent contenir des
renseignements confidentiels, exclusifs ou legalement privilegies destines au
seul usage du destinataire vise. L'expediteur original ne renonce a aucun
privilege ou a aucun autre droit si le present message a ete transmis
involontairement ou s'il est retransmis sans son autorisation. Si vous n'etes
pas le destinataire vise du present message ou si vous l'avez recu par erreur,
veuillez cesser immediatement de le lire et le supprimer, ainsi que toutes ses
pieces jointes, de votre systeme. La lecture, la distribution, la copie ou
tout autre usage du present message ou de ses pieces jointes par des personnes
autres que le destinataire vise ne sont pas autorises et pourraient etre
illegaux. Si vous avez recu ce courrier electronique par erreur, veuillez en
aviser l'expediteur.