2013-08-01 2 views
6

У меня есть WSDL-файл из-за пределов WS, к которому я подключаюсь. И я пытаюсь заставить его работать с CXF (отлично работает с JAX-WS). Но я получаю ошибку от другой системы. Поэтому я решил взглянуть на данные, которые мы отправляем в эту систему, и только различие заключается в том, что CXF устанавливает пустой HTTP-заголовок SOAPAction.Заголовок SoapAction отсутствует при использовании CXF

Я прочитал немного и выглядит так, что только известные решения прямо указывают на WSDL. Но я уже это сделал.

У кого-нибудь есть ключ к этому поводу?

<bean id="object" class="xxx.XxxObject" factory-bean="objectFActory" 
     factory-method="create"/> 

<bean id="objectFActory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> 
    <property name="serviceClass" value="xxx.XxxObject"/> 
    <property name="wsdlLocation" value="http://blebleble"/> 
    <property name="address" value="http://blebleble"/> 
    <property name="username" value="user"/> 
    <property name="password" value="password"/> 
    <property name="properties"> 
     <map> 
      <entry key="javax.xml.ws.session.maintain" value-type="java.lang.Boolean" value="true"/> 
     </map> 
    </property> 
</bean> 

Заголовки:

POST /somepath HTTP/1.1 
Content-Type: text/xml; charset=UTF-8 
Accept: */* 
Authorization: Basic <randomhex> 
SOAPAction: "" 
User-Agent: Apache CXF 2.7.6 
Cache-Control: no-cache 
Pragma: no-cache 
Host: somehost:8080 
Connection: keep-alive 
Content-Length: 2791 
+1

Что ошибка? – kolossus

+0

_only diffrence - это то, что CXF устанавливает пустой SOAPAction http header_. Был ли запрос, который работал (JAX-WS, я предполагаю), не настроил HTTP-заголовок SOAPAction вообще или не установил его (непустое) значение? –

+0

JaxWS: SOAPAction: «Get» CXF: SOAPAction: «" – mihn

ответ

8

Ни одно из этого не CXF специфичны. Это стандартный JAX-WS.

Вы можете использовать свойство action аннотации @WebMethod для установки действия SOAP. Например

@WebMethod(operationName = "TestOperation", action="http://example.org/TestOperation") 

Если вы используете wsimport для генерации артефактов из WSDL, вы должны уже иметь этот набор в вашем @WebService аннотированный интерфейс.

+0

Он установлен, но он не соблюдается. :/ – mihn

+1

Можете ли вы разместить WSDL, который используете, и отметить операцию, которую вы пытаетесь вызвать? Кроме того, как вы создаете клиент в CXF, используя Spring config? Программный? – Patrick

+0

Эй, извините за ожидание. Я не могу опубликовать этот WSDL. Я создаю это как Spring bean, но не с пространством имен . – mihn

3

Я был в состоянии воспроизвести поведение вы описали (заголовок SOAPAction является «») с помощью вызова, как это:

MyPortService service = new MyPortService(); 
MyPort port = service.getMyPortSoap11(); 
MyRequest request = new MyRequest(); 
MyResponse response = port.subscription(request); 

здесь являются заголовки HTTP с TCP Dump, используя этот вызов:

POST /MyService/services HTTP/1.1 
Content-Type: text/xml; charset=UTF-8 
Accept: */* 
SOAPAction: "" 
User-Agent: Apache CXF 2.7.6 
Cache-Control: no-cache 
Pragma: no-cache 
Host: redacted 
Connection: keep-alive 
Content-Length: 377 

Я попытался добавить перехватчик и убедиться, что SOAPAction был установлен как заголовок, но независимо от того, что я пробовал, что не вызывало отправку SOAPAction как часть HTTP-запроса.

Я тогда нашел ведущую роль в этом thread и переформатировать мой вызов:

ClientProxyFactoryBean factory = new ClientProxyFactoryBean(); 
factory.setServiceClass(MyPort.class); 
factory.setAddress("http://www.host.com/service"); 
factory.setServiceName(new QName(targetNamespace, wsdlBindingName)); 
Object myService = factory.create(); 
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(myService); 
Map<String, List<String>> headers = new HashMap<String, List<String>>(); 
headers.put("SOAPAction", Arrays.asList("mySoapAction")); 
client.getRequestContext().put(Message.PROTOCOL_HEADERS, headers); 
client.invoke(operationName, request); 

Вот заголовки HTTP из TCP свалки призванию в этом стиле:

POST /MyService/services HTTP/1.1 
Content-Type: text/xml; charset=UTF-8 
Accept: */* 
SOAPAction: mySoapAction 
User-Agent: Apache CXF 2.7.6 
Cache-Control: no-cache 
Pragma: no-cache 
Host: redacted 
Connection: keep-alive 
Content-Length: 377 

Надеется, что это помогает.

+0

Я надеялся на что-то, что сделало бы CXF уважением настройки действия WSDL. Я уже написал все приложение, просто хочу обменять JAXWS на CXF, чтобы что-то проверить. – mihn

+0

Извините, у меня нет лучшего ответа - я отлаживал CXF через перехватчики и возможный потоковый писатель, но код беспорядок с тоннами без вызова метода + void return. Я могу сказать, что заголовок SOAPAction остается в экземпляре Message до того, как он будет записан в поток, но не смог определить, почему SOAPAction падает. – Alex

+0

Установка 'Message.PROTOCOL_HEADERS' с использованием карты - единственное программное решение, которое сработало для меня. –

1

Если это все еще актуально. Столкнулась с той же проблемой и написала перехватчик. Это довольно универсальный:

public class SoapActionInterceptor extends AbstractSoapInterceptor { 
    private static final String SLASH = "/"; 

    public SoapActionInterceptor() { 
     super(Phase.POST_LOGICAL); 
    } 

    @Override 
    public void handleMessage(SoapMessage message) throws Fault { 

     BindingOperationInfo bindingOperationInfo = message.getExchange().getBindingOperationInfo(); 
     OperationInfo operationInfo = bindingOperationInfo.getOperationInfo(); 
     InterfaceInfo interfaceInfo = operationInfo.getInterface(); 
     QName interfaceInfoNameQName = interfaceInfo.getName(); 
     QName operationQName = operationInfo.getName(); 

     Map<String, List<String>> reqHeaders = CastUtils.cast((Map<?, ?>) message.get(Message.PROTOCOL_HEADERS)); 

     if (reqHeaders == null) { 
      reqHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); 
     } 

     if (reqHeaders.size() == 0) { 
      message.put(Message.PROTOCOL_HEADERS, reqHeaders); 
     } 

     reqHeaders.put(SoapBindingConstants.SOAP_ACTION, Arrays.asList(interfaceInfoNameQName.getNamespaceURI() + SLASH + interfaceInfoNameQName.getLocalPart() + SLASH + operationQName.getLocalPart())); 
    } 
} 

Чтобы использовать его в Spring + Apache CXF:

<jaxws:client id="client" serviceClass="some.generated.webservice.Interface" 
       wsdlLocation="/META-INF/wsdl/webservice.wsdl" 
       address="http://example.address/service"> 
    <jaxws:outInterceptors> 
     <bean class="some.package.interceptor.SoapActionInterceptor"/> 
    </jaxws:outInterceptors> 
</jaxws:client> 
0

я нашел другую причину этой проблемы, поэтому я думал, что будет идти вперед и опубликовать этот ответ в случае, если это помогает кто то.

После создания службы SOAP, WSDL-first и создания интерфейса службы и связанных с ним классов из XSD, я обнаружил, что действие soap, которое я устанавливал в своем wsdl, не отображалось в WSDL, генерированном CXF (который вы можете добавить, добавив '? wsdl' к своей конечной точке обслуживания и поместив ее в свой браузер).

например: http://localhost:8080/mywar/services/myservice?wsdl

Причиной этого вопроса для меня было то, что я не правильно аннотировать класс реализации услуг. Хотя на созданном интерфейсе были соответствующие аннотации, класс внедрения был причиной моей проблемы.

я должен был добавить следующее к моей службе классу реализации для решения этой проблемы:

@WebService( targetNamespace="...", portName="...", endpointInterface="...", serviceName="...")

Надеется, что это помогает кто-то ...

Смежные вопросы