Service endpoints and paths

Let’s explain how a service endpoint can be exposed under a certain URL path.

Set the endpoint path via application.properties

In the First SOAP Web service chapter, we explained how to expose a service using application.properties:

application.properties
# The context path under which all services will be available
quarkus.cxf.path = /soap

# Publish "HelloService" under the context path /${quarkus.cxf.path}/hello
quarkus.cxf.endpoint."/hello".implementor = io.quarkiverse.cxf.it.server.HelloServiceImpl
quarkus.cxf.endpoint."/hello".features = org.apache.cxf.ext.logging.LoggingFeature

With this setup in place, the io.quarkiverse.cxf.it.server.HelloServiceImpl will be accessible under http://localhost:8080/soap/hello.

This is the traditional way that worked since the very beginning of Quarkus CXF.

Set the endpoint path using @CXFEndpoint annotation

Since Quarkus CXF 3.11.0, there is a new way to expose an endpoint under a specific path: the @io.quarkiverse.cxf.annotation.CXFEndpoint annotation. The path is set through its non-optional attribute value and it is relative to quarkus.cxf.path much like when this is done via application.properties.

Let’s have a look at an example.

The sample code snippet shown in this section comes from the Client and server integration test in the source tree of Quarkus CXF. You may want to use it as a runnable example.

PathAnnotationHelloServiceImpl.java
package io.quarkiverse.cxf.it.annotation.cxfendpoint;

import jakarta.jws.WebService;

import io.quarkiverse.cxf.annotation.CXFEndpoint;
import io.quarkiverse.cxf.it.HelloService;

@CXFEndpoint("/path-annotation") (1)
@WebService(serviceName = "HelloService", targetNamespace = HelloService.NS)
public class PathAnnotationHelloServiceImpl implements HelloService {
    @Override
    public String hello(String person) {
        return "Hello " + person + " from PathAnnotationHelloServiceImpl!";
    }
}
1 If the value of quarkus.cxf.path in application.properties is /soap, then this service will be accessible under http://localhost:8080/soap/path-annotation.

@CXFEndpoint("/my-path") annotation on MyServiceImpl type is equivalent to the quarkus.cxf.endpoint."/my-path".implementor = org.acme.MyServiceImpl line in application.properties. Therefore it is enough to use just one of them.

Other options set in application.properties for the /my-path endpoint will combine just fine with @CXFEndpoint("/my-path").

Use the @CXFEndpoint annotation on producer methods

The @CXFEndpoint annotation can also be used on producer methods. This comes in handy especially when testing clients, because the returned implementation can be a mock.

Here is an example:

MockedEndpointTest.java
package io.quarkiverse.cxf.it.annotation.cxfendpoint;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import io.quarkiverse.cxf.annotation.CXFClient;
import io.quarkiverse.cxf.annotation.CXFEndpoint;
import io.quarkiverse.cxf.it.HelloService;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class MockedEndpointTest {

    @CXFEndpoint("/helloMock") (1)
    HelloService helloMockService() {
        final HelloService result = Mockito.mock(HelloService.class);
        Mockito.when(result.hello("Mock")).thenReturn("Hello Mock!");
        return result;
    }

    @CXFClient("helloMock") (2)
    HelloService helloMockClient;

    @Test
    void helloMock() {
        Assertions.assertThat(helloMockClient.hello("Mock")).isEqualTo("Hello Mock!"); (3)
    }

}
1 Here we use the @CXFEndpoint annotation on a method that returns a mock of the HelloService interface. The @jakarta.enterprise.inject.Produces annotation is not required, because Quarkus CXF declares @CXFEndpoint as a bean defining annotation.
2 The client is configured in application.properties to connect to http://localhost:8080/soap/helloMock
3 The assertion makes sure that the service implementation works as expected.