Four Ways to Call WebServices from Java: Axis2, RPC, HttpURLConnection & HttpClient Compared
This article compares four Java approaches for calling WebServices — Axis2 code generation, RPC, HttpURLConnection, and HttpClient — detailing pros, cons, code samples, and a real-world namespace mismatch issue when integrating with C-based services.
Introduction
WebService is a cross-language, cross-platform remote invocation technology that has existed for many years. Many interfaces are published via WebService. This article summarizes four methods for Java to call WebService services, using a C-language WebService as the example for comparison. Java-to-Java communication rarely needs WebService unless one side is fixed to that format (common with demanding clients). WebService is primarily used for data exchange between services written in different languages because it is based on WSDL.
Overview of Four Methods
1. Axis2 WSDL-to-Java Code Generation
Pros: Simple invocation, minimal manual code.
Cons: Generated service address is fixed and hard to change; generated code is bloated and hard to read; requires the WSDL file, which reduces control.
2. RPC Invocation (Recommended)
Pros: Flexible endpoint URL, suitable for distributed deployment; only need method name, namespace, and parameters.
Cons: In some special cases the call succeeds but the return value cannot be retrieved.
3. HttpURLConnection
Pros: Complements RPC shortcomings; relatively little code.
Cons: For C-language WebServices, must manually construct SOAP request headers and parse responses; requires prior packet capture to inspect messages.
4. HttpClient
Same principle as HttpURLConnection, different implementation. Pros and cons are similar.
Detailed Analysis
Method 1: Axis2 wsdl2java
Download Axis2 JARs. The wsdl2java.bat command (in <Axis2_HOME>/bin) generates client stubs from a WSDL file.
%AXIS2_HOME%\bin\wsdl2java -uri d:demo.wsdl -p client -s -o stubKey parameters: -o: output path -s: synchronous mode -p: package name -a: async mode -d: databinding (adb, xmlbean, jibx, jaxme, jaxbri) -l: language (Java/C) default Java -t: generate test cases -ss: generate server-side code (default no) -sd: generate services.xml (only with -ss) -g: generate both server and client code -pn: specify a port when WSDL has multiple ports -sn: select a service from WSDL -u: unpack data-binding classes -r: specify a repository for generated code -ssi: generate interface class for server implementation -S: specify source output path -R: specify resources output path --noBuildXML: do not generate build.xml --noWSDL: do not generate WSDL in resources --noMessageReceiver: do not generate MessageReceiver class
Generated code is voluminous and the endpoint URL is hard-coded. The author dislikes this approach because the generated classes are huge, the URL is fixed, and many C-language WSDLs fail to generate correctly.
Method 2: RPC (Strongly Recommended)
Example: querying device online count.
public String getOnline(String url) {
int errCode = 0;
JSONObject resultJson = new JSONObject();
String result = "";
Service service = new Service();
Call call;
try {
call = (Call) service.createCall();
QName opAddEntry = new QName("urn:demo", "GetOnlineInfo");
call.setTargetEndpointAddress(url);
call.setOperationName("GetNcgOnlineInfo");
call.setTimeout(2000);
call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);
result = (String) call.invoke(opAddEntry, new Object[]{});
} catch (ServiceException e) {
System.out.println("查询在线状态1:" + e.getMessage());
errCode = 1;
} catch (RemoteException e) {
System.out.println("查询在线状态2:" + e.getMessage());
errCode = 2;
}
resultJson.put("errCode", errCode);
resultJson.put("data", result);
return resultJson.toString();
}Real-world issue: The counterpart provided two WebServices with overlapping parts, merged under two namespaces. One namespace worked; the other returned no value. Error indicated namespace mismatch. Wireshark capture showed the request used ns1="urn:ncg" but the response contained three namespaces: xmlns:dag="http://tempuri.org/dag.xsd", xmlns:dag="urn:dag", xmlns:ncg="urn:ncg". RPC's default parser expected ns1="urn:ncg" and failed. This forced a fallback to manual SOAP handling (methods 3 or 4).
Method 3: HttpURLConnection with Manual SOAP Construction
Same query method, but building the SOAP envelope manually based on captured packets.
public String ncgConnection(String url, String method) {
URL wsUrl;
int errCode = 0;
JSONObject resultJson = new JSONObject();
String result = "";
try {
wsUrl = new URL(url + "/" + method);
HttpURLConnection conn = (HttpURLConnection) wsUrl.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
conn.setConnectTimeout(2000);
conn.setReadTimeout(2000);
OutputStream os = conn.getOutputStream();
String soap = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body><ns1:"
+ method + " soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:ns1=\"urn:ncg\" /></soapenv:Body></soapenv:Envelope>";
os.write(soap.getBytes());
InputStream is = conn.getInputStream();
byte[] b = new byte[1024];
int len = 0;
String s = "";
while ((len = is.read(b)) != -1) {
String ss = new String(b, 0, len, "UTF-8");
s += ss;
}
result = s.split("<response xsi:type=\"xsd:string\">")[1].split("</response>")[0];
is.close();
os.close();
conn.disconnect();
} catch (MalformedURLException e) {
System.out.println("通讯模块1:" + e.getMessage());
errCode = 1;
} catch (IOException e) {
System.out.println("通讯模块2:" + e.getMessage());
errCode = 2;
}
resultJson.put("errCode", errCode);
resultJson.put("data", result);
return resultJson.toString();
}The request body follows the WSDL structure captured via Wireshark. Response parsing uses string splitting on the known SOAP response tags. This works around the RPC namespace parsing failure.
Method 4: HttpClient
HttpClient is a more feature-rich, stable alternative to HttpURLConnection, though less lightweight. Implementation logic mirrors method 3.
public void demo(String url) {
HttpClient httpClient = new HttpClient();
PostMethod postMethod = new PostMethod();
postMethod.setPath(url + "/ncg.wsdl");
String soap = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body><ns1:GetNcgOnlineInfo soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:ns1=\"urn:ncg\" /></soapenv:Body></soapenv:Envelope>";
try {
byte[] b = soap.getBytes("utf-8");
InputStream is = new ByteArrayInputStream(b, 0, b.length);
RequestEntity re = new InputStreamRequestEntity(is, b.length, "application/soap+xml; charset=utf-8");
postMethod.setRequestEntity(re);
int statusCode = httpClient.executeMethod(postMethod);
String soapResponseData = postMethod.getResponseBodyAsString();
postMethod.releaseConnection();
System.out.println(soapResponseData.split("<response xsi:type=\"xsd:string\">")[1].split("</response>")[0]);
} catch (UnsupportedEncodingException | HttpException | IOException e) {
e.printStackTrace();
}
}Packet capture would show identical traffic to HttpURLConnection.
Summary
Calling WebServices heavily depends on how rigorously the provider implemented the service. If the implementation is strict, RPC is recommended. Otherwise, choose based on actual circumstances — HttpURLConnection or HttpClient with manual SOAP construction can handle non-standard responses.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
