Отслеживание XML-запроса/ответов с помощью JAX-WS при возникновении ошибки
Я хочу записывать сырые сообщения с мыльным сообщением, если есть какие-либо ошибки, я использую JAX-WS. Любая помощь будет оценена.
Есть ли простой способ (ака: не использовать прокси), чтобы получить доступ к необработанному XML-запросу/ответу для веб-службы, опубликованной с помощью эталонной реализации JAX-WS (той, которая включена в JDK 1.5 и выше) только при возникновении исключения в ответ? Я хочу зарегистрировать сырое SOAP-обновление, чтобы я мог проверить его на любом веб-сервисе клиента на более позднем этапе
Ответы
Ответ 1
Использование
com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true
и
com.sun.xml.internal.ws.transport.http.HttpAdapter.dump=true
вместо этого (обратите внимание на "внутреннее" в имени пакета), это сделало трюк для меня.
Cheers,
Торстен
Ответ 2
Просто подумал, что упомяну это:
Вопрос, когда использовать имя свойства с internal
в нем, а когда нет?
Если вы прочитаете Metro Guide, он скажет вам использовать:
на клиенте:
com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
на сервере:
com.sun.xml.ws.transport.http.HttpAdapter.dump=true
Однако: мне кажется, что когда библиотека JAX-WS RI была включена в стандартную комплектацию с JDK (это было с Java 6), тогда Sun пришлось переименовать имя свойства, чтобы включить в него "internal". Так что, если вы используете JAX-WS RI, так как он поставляется в комплекте с JDK, вы должны обязательно добавить internal
к имени свойства. В противном случае это не будет работать. Другими словами вам нужно использовать:
на клиенте:
com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true
на сервере:
com.sun.xml.internal.ws.transport.http.HttpAdapter.dump=true
С другой стороны, если вы используете автономную версию JAX-WS RI (или Metro в целом), то я думаю, вы должны использовать имя свойства без internal
.
Я буду рад, если кто-то знает об этом и может сказать, правда это или нет.
Ответ 3
В дополнение к ответу Torsten
com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump = истина
Убедитесь, что вы установили это перед тем, как создать экземпляр объекта WebServiceClient (тот, который расширяет Service)
Ответ 4
Первое, что вы можете попробовать, это использовать один или оба следующих свойства системы:
Клиент:
com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
Сервер:
com.sun.xml.ws.transport.http.HttpAdapter.dump=true
Ответ 5
Если вы работаете с Jboss 6.1 и хотите распечатать журналы для запроса классов JAX-WS для веб-службы SOAP,
откройте файл /home/oracle/jboss-eap-6.1/bin/standalone.sh
note: перейдите туда, где вы установили jboss
Вы найдете что-то вроде этого
JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=n"
Измените его на показанное ниже.
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true -agentlib:jdwp=transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=n"
Также убедитесь, что вы включили debug
DEBUG_MODE=true
Ответ 6
Я думаю, что вам нужен обработчик, см.
http://jax-ws.java.net/articles/handlers_introduction.html
С обработчиком вы можете перехватить вызов веб-службы и получить доступ ко всему сообщению SOAP.
Ответ 7
Это сработало для меня:
-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
Ответ 8
Можно использовать системные свойства (вот Gradle DSL для test
задания):
systemProperty "com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump", "true"
systemProperty "com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump", "true"
systemProperty "com.sun.xml.ws.transport.http.HttpAdapter.dump", "true"
systemProperty "com.sun.xml.internal.ws.transport.http.HttpAdapter.dump", "true"
systemProperty "com.sun.xml.ws.transport.http.HttpAdapter.dumpTreshold", "99999"
systemProperty "com.sun.xml.internal.ws.transport.http.HttpAdapter.dumpTreshold", "99999"
но эти параметры являются глобальными и могут иметь большой объем, чтобы включить их в PROD... Не очень интересно добавлять фильтры к вашей структуре ведения журнала, привязанной к бизнес-логике, если вы хотите уменьшить объем ведения журнала XML.
Подробная информация о захвате тел req/rsp в обработчиках WS содержится в моем ответе. Как передать данные из обработчика SOAP клиенту веб-службы?
Вот важная часть:
public class MsgLogger implements SOAPHandler<SOAPMessageContext> {
public static String REQEST_BODY = "com.evil.request";
public static String RESPONSE_BODY = "com.evil.response";
@Override
public Set<QName> getHeaders() {
return null;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
SOAPMessage msg = context.getMessage();
Boolean beforeRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(32_000);
context.getMessage().writeTo(baos);
String key = beforeRequest ? REQEST_BODY : RESPONSE_BODY;
context.put(key, baos.toString("UTF-8"));
context.setScope(key, MessageContext.Scope.APPLICATION);
} catch (SOAPException | IOException e) { }
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
return handleMessage(context);
}
@Override
public void close(MessageContext context) { }
}
Чтобы зарегистрировать обработчик и использовать сохраненные свойства:
BindingProvider provider = (BindingProvider) port;
List<Handler> handlerChain = bindingProvider.getBinding().getHandlerChain();
handlerChain.add(new MsgLogger());
bindingProvider.getBinding().setHandlerChain(handlerChain);
Req req = ...;
Rsp rsp = port.serviceCall(req); // call WS Port
// Access saved message bodies:
Map<String, Object> responseContext = provider.getResponseContext();
String reqBody = (String) responseContext.get(MsgLogger.REQEST_BODY);
String rspBody = (String) responseContext.get(MsgLogger.RESPONSE_BODY);
С этим решением (это только скелет, правильная обработка ошибок/крайние случаи зависит от вас), вы решаете войти позже, когда получите ответ.