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...

Другие вопросы по тегам