суббота, 21 июля 2012 г.

Клиент Spring ws 2.1.0 + http components 4.2.1

В данном заметке я напишу о том, как мне удалось заставить работать связку из Spring ws 2.1.0 и http components 4.2.1.

Итак, начну с конфига:

    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">  
   <property name="messageSenders"> 
      <list> 
       <ref bean="httpSender" /> 
      </list> 
     </property>
 </bean>

 <!-- http sender configuration -->
 <bean id="httpSender" class="org.springframework.ws.transport.http.HttpComponentsMessageSender"> 
    <constructor-arg> 
     <ref bean="httpClient"/> 
    </constructor-arg> 
   </bean>   
  <!-- http client definition -->
   <bean id="httpClient" class="ru.chernykh.MyDefaultHttpClient">
   <constructor-arg>
    <ref bean="connmanager"/>
   </constructor-arg> 
    <property name="params" ref="httpParams" />
   </bean>
 <!-- http params definition -->
   <bean id="httpParams" class="org.apache.http.params.SyncBasicHttpParams"/>

   <!-- setup thread-safe connection manager -->
   <bean id="connmanager" class="org.apache.http.impl.conn.PoolingClientConnectionManager" destroy-method="shutdown">
    <property name="maxTotal" value="100"></property>
    <property name="defaultMaxPerRoute" value="100"></property>
   </bean>  
   <!--  connection manager params  --> 
  <bean id="connParams" class="org.apache.http.params.HttpConnectionParamBean">
   <constructor-arg>
    <ref bean="httpParams"/>
   </constructor-arg>
    <property name="soTimeout" value="10000"></property>
  </bean>
  
Здесь всё стандартно за исключением бина httpClient. По умолчанию, если мы будем использовать DefaultHttpClient, то получим ошибку исполнения:
"Content-Length header already present".  Это означает, что httpclient пытается поставить заголовок в надежде что его нет, но это не так, поэтому получаем исключение.

Класс ru.chernykh.MyDefaultHttpClient выглядит так:
public class MyDefaultHttpClient extends DefaultHttpClient{

    protected BasicHttpProcessor createHttpProcessor() {
        BasicHttpProcessor processor = super.createHttpProcessor();
        processor.addInterceptor(new RemoveHttpHeadersInterceptor(), 0);
        return processor;
    }

    public MyDefaultHttpClient(org.apache.http.impl.conn.PoolingClientConnectionManager connManager){
        super(connManager);
    }
}
А класс RemoveHttpHeadersInterceptor следующим образом:
public class RemoveHttpHeadersInterceptor implements HttpRequestInterceptor{

    public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
        if (request instanceof HttpEntityEnclosingRequest) {
            if (request.containsHeader(HTTP.TRANSFER_ENCODING)) {
                request.removeHeaders(HTTP.TRANSFER_ENCODING);
            }
            if (request.containsHeader(HTTP.CONTENT_LEN)) {
                request.removeHeaders(HTTP.CONTENT_LEN);
            }
        }
    }
}
После этого, клиент заработал, и ошибок не было.

Хочу обратить внимание, что по умолчанию в классе
org.springframework.ws.transport.http.HttpComponentsMessageSender используется deprecated API http components(рекомендую взглянуть в исходниках). Поэтому лучше потратить время на ручную установку параметров httpClient, как это сделал я.

Комментариев нет:

Отправить комментарий