Apache CXF/MTOM повреждает файл при запуске через Weblogic 12c
Я использую клиент веб-службы на основе CXF (использует веб-службу со стороны.net). Все работает отлично, кроме передачи файлов PDF.
Если я запускаю ту же конфигурацию через junit (подпружиненный контекст и cxf) или использую тот же веб-сервис через soap-ui, файл pdf передается правильно.
Когда я запускаю его через Weblogic 12c (12.1.3), бинарное содержимое pdf будет повреждено. Вот пример:
* Good File (transferred via CXF standalone / junit) *
%PDF-1.3
1 0 obj
[/PDF /Text /ImageB /ImageC /ImageI]
endobj
9 0 obj
<< /Length 1659 /Filter /FlateDecode >> stream
xœXÛnÛ8}_
* Bad File (transferred via WLS/CXF) *
%PDF-1.3
1 0 obj
[/PDF /Text /ImageB /ImageC /ImageI]
endobj
9 0 obj
<< /Length 1659 /Filter /FlateDecode >> stream
xœ�XÛnÛ8}_
Вы можете видеть, что секция потока получает дополнительный байт там (это только начало файла... дополнительный байт показывает много раз после этого). Запуск этого окна или Linux приведет к повреждению передачи. Java 8. CXF 2.7 и 3.1.
Я все еще изучаю эту проблему, но любые идеи, которые вам не нравятся, будут оценены по достоинству.
- Это кодировка, которая должна быть где-то установлена / не установлена?
- Это какие-то предпочтительные библиотеки в веб-модуле, которые следует использовать?
- Возможно, отсутствует только патч сервера приложений? -
...
1 ответ
Как я объяснил в комментариях, виновником искажения был пользовательский обработчик логов, внедренный как перехватчик входящего сообщения. Он кодировал все сообщение в UTF-8, включая двоичный контент.
Client client = ClientProxy.getClient(port);
client.getInInteceptors().add(inLogger);
Однако я не нашел, почему этот регистратор не вызывал проблем за пределами контейнера weblogic. Обращение в службу поддержки Oracle не сильно помогло, так как они хотели, чтобы я представил работоспособный контрольный пример, который повторяет проблему... которая граничит с невозможной (т. Е. Веб-служба размещена в другой компании).
Я также хотел упомянуть способ легко обработать сообщение до того, как конвейер сообщений сработает. Все, что нужно, это пользовательское сообщение наблюдателя, введенное в конечную точку. Как это:
Endpoint endpoint = client.getEndpoint();
HTTPConduit conduit = (HTTPConduit) client.getConduit();
conduit.setMessageObserver(new MyMessageObserver(client));
Помните, что при работе с содержимым сообщения входной поток всегда должен быть сброшен (в одну сторону) после использования. В вашем обозревателе сообщений вы можете сохранить содержимое сообщения, затем передать его и сбросить, возможно, на обратном пути. В том же духе:
@Override public void onMessage(Message message) {
InputStream is = message.getContent(InputStream.class);
InputStream mis = save(is);
is.reset();
client.onMessage(message);
message.setContent(InputStream.class, mis);
}
Другие очевидные инъекции обработчиков сообщений выполняются через In/OutInterceptors(), и если вы посмотрите на конвейер, вы можете внедрить их в любое место в соответствии с определенными фазами обработки сообщений. ON-RECEIVE, PRE-STREAM и т. Д.... согласно http://cxf.apache.org/docs/interceptors.html. Они будут частью конвейера, но после запуска клиента. MyMessageObserver находится перед конвейером.
Надеюсь, это поможет с отладкой Apache CXF...