Skip to main content
Create Client & Test

Create Client & Test

A CXF client can be built dynamically from the WSDL or statically from an interface. The dynamic approach needs no generated code, which makes it useful for a quick test of a POJO endpoint.

Dynamic client

package com.example.pojo;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

public class DynamicClient {

    public static void main(String[] args) throws Exception {
        JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
        Client client = factory.createClient("http://localhost:8080/greeting?wsdl");

        Object[] reply = client.invoke("greet", "Ada");
        System.out.println(reply[0]);
    }
}

The operation name comes from the WSDL. Arguments are passed in declaration order and the result is returned as an object array. Run it with Maven while the server is still running:

mvn -q compile exec:java -Dexec.mainClass=com.example.pojo.DynamicClient

Expected output: Hello, Ada.

Interface-based client

For maintained code, define an interface that matches the service and let CXF create a proxy. This gives compile-time checking and avoids string-based operation names.

import jakarta.jws.WebService;

@WebService(targetNamespace = "http://pojo.example.com/")
public interface GreetingPort {
    String greet(String name);
}
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(GreetingPort.class);
factory.setAddress("http://localhost:8080/greeting");

GreetingPort port = (GreetingPort) factory.create();
System.out.println(port.greet("Grace"));

The interface must use the same namespace and operation names as the WSDL. When the namespace is missing, CXF may create a proxy that sends a request the server does not recognize.

Test with JUnit

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

class GreetingClientTest {

    @Test
    void callsTheRemoteGreeting() {
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(GreetingPort.class);
        factory.setAddress("http://localhost:8080/greeting");

        GreetingPort port = (GreetingPort) factory.create();

        assertEquals("Hello, Lin", port.greet("Lin"));
    }
}

Integration tests that depend on a running server are slower and less reliable than unit tests. Keep a small number of them for protocol checks, and stub the service interface for business-logic tests.

Troubleshooting

  • Connection refused - the server is not running on the expected port.
  • 404 on the WSDL - the address path differs from the server's path.
  • Unmarshalling error - namespaces or element names do not match the contract.
  • Slow first call - the dynamic client is downloading and compiling the WSDL; later calls are faster.
  • Proxy cast failure - the interface is not compatible with the generated service.

Inspect the traffic

Add LoggingFeature to the proxy factory, or use SoapUI to see the exact XML. Comparing a working request with a failing one is faster than guessing which namespace is wrong.