This document covers the sending and receiving of SOAP messages with Axis2 using HTTP as the transport mechanism.
HTTPClient4TransportSender is the transport sender that is used by default in both the Server and Client APIs. As its name implies, it is based on Apache HttpComponents. For maximum flexibility, this sender supports both the HTTP GET and POST interfaces. (REST in Axis2 also supports both interfaces.)
Axis2 uses a single HTTPClient instance per ConfigurationContext (which usually means per instance of ServiceClient). This pattern allows for HTTP 1.1 to automatically reuse TCP connections - in earlier versions of Axis2 the REUSE_HTTP_CLIENT configuration property was necessary to enable this functionality, but as of 1.5 this is no longer necessary.
Apache HttpComponents also provides HTTP 1.1, Chunking and KeepAlive support for Axis2.
The <transportSender/> element defines transport senders in the axis2.xml configuration file as follows:
<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> </transportSender>
The above code snippet shows the simplest configuration of a transport sender for common use. The <parameter/> element is used to specify additional constraints that the sender should comply with. The HTTP PROTOCOL parameter should be set as HTTP/1.0 or HTTP/1.1. The default version is HTTP/1.1. Note that chunking support is available only for HTTP/1.1. Thus, even if "chunked" is specified as a parameter, if the HTTP version is 1.0, this setting will be ignored by the transport framework. Also, KeepAlive is enabled by default in HTTP/1.1.
If you use HTTP1.1 for its Keep-Alive ability, but you need to disable chunking at runtime (some servers don't allow chunked requests to prevent denial of service), you can do so in the Stub:
options.setProperty(HTTPConstants.CHUNKED, "false");
Some absolute properties are provided at runtime instead. For example, character encoding style (UTF-8, UTF-16, etc.) is provided via MessageContext.
<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>
Please note that by default HTTPS works only when the server does not expect to authenticate the clients (1-way SSL only) and where the server has the clients' public keys in its trust store.
If you want to perform SSL client authentication (2-way SSL), you may configure your own HttpClient class and customize it as desired - see the example below.
To control the max connections per host attempted in parallel by a reused httpclient, or any other advanced parameters, you need to set the cached httpclient object when your application starts up (before any actual axis request). You can set the relevant property as shown below by using HTTPConstants.CACHED_HTTP_CLIENT.
The following code was testing Axis2 on Wildfly 20, the cert was obtained by 'openssl s_client -connect myserver:8443 -showcerts'
String wildflyserver_cert_path = "src/wildflyserver.crt"; Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream(new File(wildflyserver_cert_path))); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); keyStore.setCertificateEntry("server", certificate); TrustManagerFactory trustManagerFactory = null; trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { throw new Exception("Unexpected default trust managers:" + Arrays.toString(trustManagers)); } SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, trustManagers, new SecureRandom()); // NoopHostnameVerifier to trust self-singed cert SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslsf).build(); // This code is taken from HTTPSenderImpl, from 200 connections to 20 HttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); ((PoolingHttpClientConnectionManager)connManager).setMaxTotal(20); ((PoolingHttpClientConnectionManager)connManager).setDefaultMaxPerRoute(20); HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connManager).setConnectionManagerShared(true).build(); Options options = new Options(); options.setTo("myurl"); options.setTransportInProtocol(Constants.TRANSPORT_HTTP); options.setTimeOutInMilliSeconds(120000); options.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient); ServiceClient sender = new ServiceClient(); sender.setOptions(options);
References to the core HTTP classes used by Axis2 Stub classes can be obtained below.
TransportOutDescription transportOut = new TransportOutDescription("https"); HTTPClient4TransportSender sender = new HTTPClient4TransportSender(); sender.init(stub._getServiceClient().getServiceContext().getConfigurationContext(), transportOut); transportOut.setSender(sender); options.setTransportOut(transportOut);
For Async requests, the axis2 thread pool core size is set to 5. That can be changed as shown below.
configurationContext.setThreadPool(new ThreadPool(200, Integer.MAX_VALUE));
Two timeout instances exist in the transport level, Socket timeout and Connection timeout. These can be configured either at deployment or run time. If configuring at deployment time, the user has to add the following lines in axis2.xml.
For Socket timeout:
<parameter name="SO_TIMEOUT">some_integer_value</parameter>
For Connection timeout:
<parameter name="CONNECTION_TIMEOUT">some_integer_value</parameter>
... Options options = new Options(); options.setProperty(HTTPConstants.SO_TIMEOUT, new Integer(timeOutInMilliSeconds)); options.setProperty(HTTPConstants.CONNECTION_TIMEOUT, new Integer(timeOutInMilliSeconds)); // or options.setTimeOutInMilliSeconds(timeOutInMilliSeconds); ...
The default HTTP version is 1.1. There are two methods in which the user can change the HTTP version to 1.0
<parameter name="PROTOCOL">HTTP/1.0</parameter>
... options.setProperty(org.apache.axis2.context.MessageContextConstants.HTTP_PROTOCOL_VERSION, org.apache.axis2.transport.http.HTTPConstants.HEADER_PROTOCOL_10); ...
The Apache Httpcomponents client has built-in support for proxy authentication. Axis2 uses deployment time and runtime mechanisms to authenticate proxies. At deployment time, the user has to change the axis2.xml as follows. This authentication is available for both HTTP and HTTPS.
<transportSender name="http" class="org.apache.axis2.transport.http.impl.httpclient4.HTTPClient4TransportSender"> <parameter name="PROTOCOL">HTTP/1.1</parameter> <parameter name="PROXY" proxy_host="proxy_host_name" proxy_port="proxy_host_port">userName:domain:passWord</parameter> </transportSender>
For a particular proxy, if authentication is not available, enter the "userName:domain:passWord" as "anonymous:anonymous:anonymous".
Prior shown configuration has been deprecated after Axis2 1.2 release and we strongly recommend using the new proxy configuration as below.
New proxy configuration would require the user to add a TOP level parameter in the axis2.xml named "Proxy".
<parameter name="Proxy"> <Configuration> <ProxyHost>example.org</ProxyHost> <ProxyPort>5678</ProxyPort> <ProxyUser>EXAMPLE\saminda</ProxyUser> <ProxyPassword>ppp</ProxyPassword> </Configuration> </parameter>
Thus, if its a open proxy, user can ignore ProxyUser and ProxyPassword elements.
In addition to this, if you don't want to go through writing the above parameter you could use Java Networking Properties for open proxies, -Dhttp.proxyHost=10.150.112.254 -Dhttp.proxyPort=8080
At runtime, the user can override the PROXY settings using the HttpTransportProperties.ProxyProperties object. Within your client stub, create an instance of this object, configure proxy values for it, and then set it to the MessageContext's property bag via options.setProperty(). For example:
... Options options = new Options(); ... HttpTransportProperties.ProxyProperties proxyProperties = new HttpTransportProperties.new ProxyProperties(); proxyProperties.setProxyHostName(....); proxyProperties.setProxyPort(...); ... options.setProperty(HttpConstants.PROXY, proxyProperties); ...
The above code will override the deployment proxy configuration settings.
HttpClient supports three different types of HTTP authentication schemes: Basic, Digest and NTLM. Based on the challenge provided by the server, HttpClient automatically selects the authentication scheme with which the request should be authenticated. The most secure method is NTLM and the Basic is the least secure.
NTLM is the most complex of the authentication protocols supported by HttpClient. It requires an instance of NTCredentials to be available for the domain name of the server or the default credentials. Note that since NTLM does not use the notion of realms, HttpClient uses the domain name of the server as the name of the realm. Also note that the username provided to the NTCredentials should not be prefixed with the domain - ie: "axis2" is correct whereas "DOMAIN\axis2" is not correct.
There are some significant differences in the way that NTLM works compared with basic and digest authentication. These differences are generally handled by HttpClient, however having an understanding of these differences can help avoid problems when using NTLM authentication.
Axis2 also allows adding a custom Authentication Scheme to HttpClient.
The static inner bean Authenticator of HttpTransportProperties will hold the state of the server to be authenticated with. Once filled, it has to be set to the Options's property bag with the key as HTTPConstants.AUTHENTICATE. The following code snippet shows how to configure the transport framework to use Basic Authentication:
... Options options = new Options(); HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator(); auth.setUsername("username"); auth.setPassword("password"); // set if realm or domain is known options.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, auth); ...
By default, a new httpclient object is created for each send. It may be worthwhile to reuse the same httpclient object to take advantage of HTTP1.1 Keep-Alive, especially in HTTPS environment, where the SSL handshake may not be of negligible cost. To reuse the same httpclient object, you can set the relevant property in the Stub:
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, "true");
configurationContext.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, client);
HttpState myHttpState = new HttpState(); options.setProperty(WSClientConstants.CACHED_HTTP_STATE, myHttpState);