Вот еще один способ наблюдать сообщения SOAP:
Предположим, сгенерированные клиентские классы выглядят так:
// generated service class
public class MyWebServiceClient extends javax.xml.ws.Service {
// ...
private final QName portName = "...";
// ...
public RetrieveMyObjects getRetrieveMyObjects() {
return super.getPort(portName, RetrieveMyObject.class);
}
// ...
}
// generated port interface
// annotations here
public interface RetrieveMyObjects {
// annotations here
List<MyObject> getAll();
}
Теперь, после выполнения следующего кода:
MyWebServiceClient wsClient = new MyWebServiceClient("wsdl/location/url/here.wsdl");
RetrieveMyObjectsPort retrieveMyObjectsPort = wsClient.getRetrieveMyObjects();
wsClient
должен возвращать экземпляр, который является экземпляром интерфейсов RetrieveMyObjects
и javax.xml.ws.BindingProvider
. Это не указано нигде на поверхности JAX-WS, но кажется, что большая часть кода основана на этом факте. Можно заверить его, выполнив что-то вроде:
if(!(retrieveMyObjectsPort instanceof javax.xml.ws.BindingProvider)) {
throw new RuntimeException("retrieveMyObjectsPort is not instance of " + BindingProvider.class + ". Redirect following as well as authentication is not possible");
}
Теперь, когда мы уверены, что retrieveMyObjectsPort
является экземпляром javax.xml.ws.BindingProvider
, мы можем включить ведение журнала SOAPMessage
, вызвав следующий метод для каждого требуемого интерфейса порта веб-службы:
/**
* Enables logging of send and received SOAP messages on the specified {@link BindingProvider}s
*/
private static void enableSoapMessageLogging(final Logger logger, final BindingProvider... bindingProviders) {
for(final BindingProvider bindingProvider : bindingProviders) {
final List<Handler> handlerChain = bindingProvider.getBinding().getHandlerChain();
handlerChain.add(new SOAPHandler<SOAPMessageContext>() {
@Override
public boolean handleMessage(final SOAPMessageContext context) {
try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
context.getMessage().writeTo(baos);
logger.trace(new String(baos.toByteArray()));
} catch(final Exception e) {
logger.error("", e);
}
return true;
}
@Override
public boolean handleFault(final SOAPMessageContext context) {
return true;
}
@Override
public void close(final MessageContext context) {
}
@Override
public Set<QName> getHeaders() {
return null;
}
});
bindingProvider.getBinding().setHandlerChain(handlerChain);
}
}
// and somewhere at the beginning of application ...
enableSoapMessageLogging(logger, (BindingProvider) retrieveMyObjectsPort);
Надеюсь, это поможет