Миграция axis2 httpclient4 не так проста, как это видно из «документации».
В процессе работы я использую последнюю версию Axis 2 1.7.8.
Замечания по выпуску оси 2 1.7.0 содержит один вкладыш для интеграции HttpClient v4:
Axis2 1.7.0 supports Apache HttpClient 4.x in addition to the no longer maintained Commons HttpClient 3.x. To enable the support for HttpClient 4.x, use org.apache.axis2.transport.http.impl.httpclient4.HTTPClient4TransportSender instead of org.apache.axis2.transport.http.CommonsHTTPTransportSender in axis2.xml. Please note that the code was written for HttpClient 4.2.x and should work with 4.3.x and 4.4.x, but is incompatible with 4.5.x.
Следите за последними словами.Файл Axis 2 1.7.8 pom, и бинарный дистрибутив содержит httpclient-4.5.3.jar, но не работает с ним.Поэтому вместо этого используйте httpclient 4.4.1 .
Включить ведение журнала
До обновления, я полагаю, у вас уже есть рабочий проект оси 2.Я рекомендую включить журнал отладки оси 2, чтобы посмотреть, что произойдет.Чтобы включить ведение журнала, определите пользовательский файл свойств log4j с аргументом jvm:
-Dlog4j.configuration=file:/c:/work/sources/debug_log4j.properties
Содержимое файла debug_log4j.properties:
log4j.rootCategory=DEBUG, CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%p] %m%n
Axis2 + Httpclient4
Если у вас нет axis2.xml, его можно найти в двоичном пакете axis2 (содержит все зависимости и примеры конфигураций)
На основе замечаний к выпускунеобходимо изменить отправителей транспорта с CommonsHTTPTransportSender на HTTPClient4TransportSender.
Если вы посмотрите (или отладите) конфигуратор axis2, вы увидите, что xml должен содержать определенные части, в противном случае axis2 не будет его читать.
Так что мое содержимое axis2.xml после настройки настроено на использование HttpClient4(и удалил неиспользуемые детали, но оставил необходимые):
<axisconfig name="AxisJava2.0">
<!-- ================================================= -->
<!-- Transport Outs -->
<!-- ================================================= -->
<parameter name="hotdeployment">true</parameter>
<parameter name="hotupdate">false</parameter>
<parameter name="enableMTOM">false</parameter>
<parameter name="enableSwA">false</parameter>
<transportSender name="local"
class="org.apache.axis2.transport.local.LocalTransportSender"/>
<transportSender name="http"
class="org.apache.axis2.transport.http.impl.httpclient4.HTTPClient4TransportSender">
<parameter name="PROTOCOL">HTTP/1.1</parameter>
<parameter name="Transfer-Encoding">chunked</parameter>
<!-- If following is set to 'true', optional action part of the Content-Type will not be added to the SOAP 1.2 messages -->
<!-- <parameter name="OmitSOAP12Action">true</parameter> -->
</transportSender>
<transportSender name="https"
class="org.apache.axis2.transport.http.impl.httpclient4.HTTPClient4TransportSender">
<parameter name="PROTOCOL">HTTP/1.1</parameter>
<parameter name="Transfer-Encoding">chunked</parameter>
</transportSender>
<!-- ================================================= -->
<!-- Phases -->
<!-- ================================================= -->
<phaseOrder type="InFlow">
<!-- System predefined phases -->
<phase name="Transport">
<handler name="RequestURIBasedDispatcher"
class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher">
<order phase="Transport"/>
</handler>
<handler name="SOAPActionBasedDispatcher"
class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher">
<order phase="Transport"/>
</handler>
</phase>
<phase name="Addressing">
<handler name="AddressingBasedDispatcher"
class="org.apache.axis2.dispatchers.AddressingBasedDispatcher">
<order phase="Addressing"/>
</handler>
</phase>
<phase name="Security"/>
<phase name="PreDispatch"/>
<phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase">
<handler name="RequestURIBasedDispatcher"
class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/>
<handler name="SOAPActionBasedDispatcher"
class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/>
<handler name="RequestURIOperationDispatcher"
class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/>
<handler name="SOAPMessageBodyBasedDispatcher"
class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/>
<handler name="HTTPLocationBasedDispatcher"
class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/>
<handler name="GenericProviderDispatcher"
class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/>
<handler name="MustUnderstandValidationDispatcher"
class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/>
</phase>
<phase name="RMPhase"/>
<!-- System predefined phases -->
<!-- After Postdispatch phase module author or service author can add any phase he want -->
<phase name="OperationInPhase">
<handler name="MustUnderstandChecker"
class="org.apache.axis2.jaxws.dispatchers.MustUnderstandChecker">
<order phase="OperationInPhase"/>
</handler>
</phase>
<phase name="soapmonitorPhase"/>
</phaseOrder>
<phaseOrder type="OutFlow">
<!-- user can add his own phases to this area -->
<phase name="soapmonitorPhase"/>
<phase name="OperationOutPhase"/>
<!--system predefined phase-->
<!--these phase will run irrespective of the service-->
<phase name="RMPhase"/>
<phase name="PolicyDetermination"/>
<phase name="MessageOut"/>
<phase name="Security"/>
</phaseOrder>
<phaseOrder type="InFaultFlow">
<phase name="Addressing">
<handler name="AddressingBasedDispatcher"
class="org.apache.axis2.dispatchers.AddressingBasedDispatcher">
<order phase="Addressing"/>
</handler>
</phase>
<phase name="Security"/>
<phase name="PreDispatch"/>
<phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase">
<handler name="RequestURIBasedDispatcher"
class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/>
<handler name="SOAPActionBasedDispatcher"
class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/>
<handler name="RequestURIOperationDispatcher"
class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/>
<handler name="SOAPMessageBodyBasedDispatcher"
class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/>
<handler name="HTTPLocationBasedDispatcher"
class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/>
<handler name="GenericProviderDispatcher"
class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/>
<handler name="MustUnderstandValidationDispatcher"
class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/>
</phase>
<phase name="RMPhase"/>
<!-- user can add his own phases to this area -->
<phase name="OperationInFaultPhase"/>
<phase name="soapmonitorPhase"/>
</phaseOrder>
<phaseOrder type="OutFaultFlow">
<!-- user can add his own phases to this area -->
<phase name="soapmonitorPhase"/>
<phase name="OperationOutFaultPhase"/>
<phase name="RMPhase"/>
<phase name="PolicyDetermination"/>
<phase name="MessageOut"/>
<phase name="Security"/>
</phaseOrder>
</axisconfig>
На стороне Java вам нужно создать пользовательский контекст конфигурации axis2, чтобы использовать наш пользовательский axis2.xml.Axis2 предлагает несколько конфигураторов, я предпочитаю один на основе файлов:
final ConfigurationContext ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem(
"c:\\work\\sources\\axis2conf",
"c:\\work\\sources\\axis2conf\\axis2.xml");
Вы можете назначить контекст конфигурации для заглушки клиента во время конструктора:
FileNet_UploadDocumentWSStub stub = new FileNet_UploadDocumentWSStub(ctx, "https://testserver/test.asp");
Итак, если вы неЕсли вы не хотите использовать пользовательские настройки ssl, обновление завершено.
Axis2 + Httpclient4 + SSL
После обновления до httpclient4 реализация больше не использует свойство обработчика настраиваемого протокола (HTTPConstants.CUSTOM_PROTOCOL_HANDLER).
Старая реализация в org / apache / axis2 / transport / http / impl / httpclient3 / HTTPSenderImpl.java: 524:
// one might need to set his own socket factory. Let's allow that case
// as well.
Protocol protocolHandler = (Protocol) msgCtx.getOptions().getProperty(
HTTPConstants.CUSTOM_PROTOCOL_HANDLER);
Новая реализация org / apache / axis2 / transport / http / impl/httpclient4/HTTPSenderImpl.java:583:
// TODO : one might need to set his own socket factory. We have to allow that case as well.
Вам необходимо настроить контекст ssl на стороне httpclient4.Это не проблема, потому что ось позволяет вам определить httpclient для ws-вызова со свойством HTTPConstants.CACHED_HTTP_CLIENT:
options.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
Но если вы создаете httpclient4 для стандартного способа:
...
HttpClientBuilder builder = HttpClientBuilder.create();
...
и назначив его клиентской заглушке axis2, вы получите ClassCastException, поскольку все новые методы httpclient Builder, factory и т. д. создают «современную» реализацию httpclient, основанную на ClosableHttpClient.Но реализация axis2 зависит от устаревшего AbstractHttpClient.Поэтому вам нужно создать старую версию httpclient.
Полный пример:
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.Security;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.httpclient.contrib.ssl.AuthSSLProtocolSocketFactory;
import org.apache.http.client.HttpClient;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicClientConnectionManager;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SingleClientConnManager;
import org.apache.http.ssl.SSLContexts;
public class SslTest {
public SslTest() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) throws Exception {
File keyFile = new File("c:\\work\\sources\\ConsoleApp25\\avp-pc.jks");
final ConfigurationContext ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem(
"c:\\work\\sources\\axis2conf",
"c:\\work\\sources\\axis2conf\\axis2.xml");
FileNet_UploadocumentWSStub stub = new FileNet_UploadDocumentWSStub(ctx, "https://testserver/test.asp");
FileNet_UploadDocument wsMethodReq = new FileNet_UploadDocument();
ServiceClient serviceClient = stub._getServiceClient();
Options options = serviceClient.getOptions();
//keystore types: https://docs.oracle.com/javase/9/docs/specs/security/standard-names.html#keystore-types
KeyStore keyStore = KeyStore.getInstance("jks");
InputStream in = null;
try {
in = new FileInputStream(keyFile);
keyStore.load(in, "changeit".toCharArray());
} finally {
if (in != null) {
in.close();
}
}
//Factory instance types: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#T5
//on IBM servers use IbmX509 instead of SunX509
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, "changeit".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
SSLSocketFactory sf = new SSLSocketFactory(sslContext);
Scheme httpsScheme = new Scheme("https", 443, sf);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(httpsScheme);
ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);
HttpClient httpClient = new DefaultHttpClient(cm);
options.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
stub.fileNet_UploadDocument(wsMethodReq);
System.out.println("done");
}