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.

Java Captain
Java Captain
Java Captain
Four Ways to Call WebServices from Java: Axis2, RPC, HttpURLConnection & HttpClient Compared

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 stub

Key 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaRPCHttpClientSOAPHttpURLConnectionWSDLAxis2WebService
Java Captain
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.