Я использую CXF в контексте разработки SOA.
Мне интересно, есть ли у моей проблемы решение с CXF. Вот моя потребность. Мы разработали веб-приложение, обслуживающее конечные точки JAXWS, реализации конечных точек заключаются в анализе запроса через перехватчики, сохранении данных из запроса в базу данных из сервисного уровня на Java и повторной отправке исходного запроса на другой сервер через клиент CXF. Дело в том, что некоторые наши запросы содержат подпись DSIG (https://www.w3.org/TR/xmldsig-core/) или подписанное утверждение SAML. Нам нужно повторно отправлять запросы без их изменения (например, прокси) из CXFClient. CXF использует для отправки упорядоченного объекта на сервер, но таким образом исходный поток не отправляется
Есть ли способ повторно отправить входящий запрос с сервисного уровня из Java CXFClient без его изменения (подписи зависят от формата запроса: пробелы, префиксы пространств имен, возврат каретки…)? Мы предпочитаем CXFClient, потому что хотели бы повторно использовать наш самодельный перехватчик CXF, который регистрирует исходящий запрос.
Мы протестировали перехватчик, намеревающийся заменить outputStream исходным запросом перед его отправкой на сервер, мы использовали этот ответ: Как изменить необработанное XML-сообщение исходящего запроса CXF?, но мы по-прежнему нокаутируем, CXF по-прежнему отправляет поток, созданный из маршалируемого объекта. См. код ниже.
Контекст: - CXF 2.7.18 (JDK 6) и 3.1.10 (JDK 8) - Платформа: Windows 7 64-битная/rhel 7 64-битная - Apache Tomcat 7 - Tcpdump для анализа входящего трафика
Пример кода нашего клиента:
final Client cxfClient = org.apache.cxf.frontend.ClientProxy.getClient( portType );
cxfClient.getInInterceptors().clear();
cxfClient.getOutInterceptors().clear();
cxfClient.getOutFaultInterceptors().clear();
cxfClient.getRequestContext().put(CustomStreamerInterceptor.STREAM_TO_SEND,
PhaseInterceptorChain.getCurrentMessage().getContent( InputStream.class ) );
cxfClient.getOutInterceptors().add( new CustomStreamerInterceptor() );
org.apache.cxf.transport.http.HTTPConduit http = (org.apache.cxf.transport.http.HTTPConduit) cxfClient.getConduit();
...
port.doSomething(someRequest);
CustomStreamerInterceptor:
package test;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.io.IOUtils;
import org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.SoapOutEndingInterceptor;
import org.apache.cxf.helpers.LoadingByteArrayOutputStream;
import org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.CacheAndWriteOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.Phase;
public class CustomStreamerInterceptor extends AbstractOutDatabindingInterceptor {
public static final String STREAM_TO_SEND = "STREAM_TO_SEND";
public CustomStreamerInterceptor () {
super( Phase.WRITE_ENDING );
addAfter( SoapOutEndingInterceptor.class.getName() );
}
@Override
public void handleMessage( Message message ) throws Fault {
try {
InputStream toSend = (InputStream) message.get( STREAM_TO_SEND );
if ( toSend != null ) {
toSend.reset();
LoadingByteArrayOutputStream lBos = new LoadingByteArrayOutputStream();
IOUtils.copy( toSend, lBos );
CacheAndWriteOutputStream cawos = (CacheAndWriteOutputStream) message.getContent( OutputStream.class );
cawos.resetOut( lBos, false );//fail !
}
}
catch ( Exception e ) {
throw new Fault( e );
}
}
}
Спасибо вам за любую помощь, это было бы очень полезно.