Skip to main content
Apache CXF With POJO

Apache CXF With POJO

A plain old Java object (POJO) is the quickest way to expose a CXF endpoint. You annotate a normal class with @WebService, point a server factory at it, and CXF generates the WSDL and SOAP binding for you. No interface, no XML, and no application server are required.

The service class

package com.example.pojo;

import jakarta.jws.WebService;

@WebService
public class GreetingService {

    public String greet(String name) {
        return "Hello, " + name;
    }
}

The annotation makes the class a service endpoint. Public methods become operations, and their parameters become message parts. Return types must be XML-serializable: primitives, strings, dates, arrays, and JavaBeans with a no-argument constructor.

Publishing the endpoint

package com.example.pojo;

import org.apache.cxf.feature.LoggingFeature;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

public class PojoServer {

    public static void main(String[] args) {
        JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
        factory.setServiceClass(GreetingService.class);
        factory.setServiceBean(new GreetingService());
        factory.setAddress("http://localhost:8080/greeting");
        factory.getFeatures().add(new LoggingFeature());

        factory.create();
        System.out.println("WSDL: http://localhost:8080/greeting?wsdl");
    }
}

create() publishes the endpoint and starts the embedded Jetty server. The JVM stays alive until it is stopped. Visit the printed URL to see the generated contract.

What CXF generated

  • A portType with one operation for greet.
  • An XSD describing the request and response elements.
  • A SOAP binding using document/literal style.
  • A service element with the endpoint address.

The default target namespace is derived from the Java package, usually reversed. If clients depend on a stable namespace, set it explicitly with @WebService(targetNamespace = "...").

When a POJO is enough

POJO endpoints work well for internal tools, demos, and small services where one team owns both sides. They become awkward when the contract must be reviewed independently, when overloaded methods are needed, or when several clients generate code from the WSDL. At that point, move to an explicit JAX-WS interface or a contract-first workflow.

Design tips

  • Keep operations small and free of side effects that are hard to retry.
  • Return DTOs rather than JPA entities so the XML shape does not depend on database mappings.
  • Avoid overloaded method names; SOAP operations are matched by name.
  • Add @WebParam when you need meaningful element names instead of arg0.
public String greet(@WebParam(name = "firstName") String firstName) {
    return "Hello, " + firstName;
}