Introduction

The JAX-RS 2.1 introduced the support of server-sent events (SSE).

Since 3.2.5 release

Thanks to the community contribution, the SSE implementation has been revamped significantly in 3.2.5 release and does not depend on any additional transport or/and library.

Configuration

In most cases the SSE providers are going to be activated automatically, either though SseProvidersExtension or SseTransportCustomizationExtension. However, in case there is a need to manually add SSE support, it could be done by including SseFeature, for example:

final JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint(<application>, JAXRSServerFactoryBean.class);
factory.setFeatures(Arrays.asList(new SseFeature()));
...
return factory.create();

Additional Properties

There are a couple of contextual properties which allow to fine-tune the Apache CXF SSE implementation to a particular context.

PropertyDescriptionDefault
org.apache.cxf.sse.sink.buffer.size

By default, the SSE events are scheduled in batches and than flushed one by one.
If the buffer overflows, no more events are going to be accepted (and consequently, the error is returned).
The size of the buffer could be controlled using this property (if default is not suitable).

10000

OSGi

For the deployments inside OSGi containers (like Apache Karaf), Apache CXF provides a dedicated cxf-sse feature (which depends on cxf-http and cxf-jaxrs).

karaf@root()> feature:install cxf-sse 

 Once installed, the dependent bundles could benefit from SSE capabilities by specifying desired transport in the Blueprint configuration, for example.

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cxf="http://cxf.apache.org/blueprint/core"
       xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"

       xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
                           http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
                           http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd">

    <bean id="sseFeature" class="org.apache.cxf.jaxrs.sse.SseFeature" />

    <cxf:bus>
        <cxf:features>
            <cxf:logging />
        </cxf:features>
    </cxf:bus>

    <jaxrs:server id="sseSampleService" address="/">
        <jaxrs:serviceBeans>
            <ref component-id="..." />
        </jaxrs:serviceBeans>
        <jaxrs:providers>
            <ref component-id="..." />
        </jaxrs:providers>
        <jaxrs:features>
            <ref component-id="sseFeature" />
        </jaxrs:features>
 </jaxrs:server>
</blueprint>

Before 3.2.5 release

Although SSE in general works on top of HTTP transport, the SSE implementation in CXF uses the dedicated one, based on Atmosphere framework. This transport only required on the server-side (client side works over normal HTTP) and is fully compatible with HTTP transport.

Configuration

There are several ways to configure SSE transport (and as the consequence, SSE support). The most straightforward one is to pass the init parameter "transportId" to the CXF servlet in question, for example:

final CXFNonSpringServlet cxfServlet = new CXFNonSpringServlet();
final ServletHolder holder = new ServletHolder(cxfServlet);
holder.setInitParameter(CXFCdiServlet.TRANSPORT_ID, SseHttpTransportFactory.TRANSPORT_ID);
...

In this case the JAXRSServerFactoryBean instances should also specify the SSE transport during construction time, for example:

final JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint(<application>, JAXRSServerFactoryBean.class);
factory.setTransportId(SseHttpTransportFactory.TRANSPORT_ID);
...
return factory.create();

Advanced Configuration

Since Apache CXF 3.2.3 release, it is possible to use alternative means to configure transports, including SSE one, by passing it through the Bus property "org.apache.cxf.preferred.transport.id" (also available as AbstractTransportFactory.PREFERRED_TRANSPORT_ID constant). With this property set to preferred transport, CXF servlet in question is going to pick it up instead of using the default one. SSE implementation benefits from that and in many cases setting the "transportId" init parameter on the servlet level could be omitted.

OSGi

For the deployments inside OSGi containers (like Apache Karaf), Apache CXF provides a dedicated cxf-sse feature (which depends on cxf-http and cxf-jaxrs).

karaf@root()> feature:install cxf-sse 

Once installed, the dependent bundles could benefit from SSE capabilities by specifying desired transport in the Blueprint configuration, for example.

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cxf="http://cxf.apache.org/blueprint/core"
       xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"

       xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
                           http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
                           http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd">

    <cxf:bus>
        <cxf:features>
            <cxf:logging />
        </cxf:features>
    </cxf:bus>

    <jaxrs:server id="sseSampleService" address="/" transportId="http://cxf.apache.org/transports/http/sse">
        <jaxrs:serviceBeans>
            <ref component-id="..." />
        </jaxrs:serviceBeans>
        <jaxrs:providers>
            <ref component-id="..." />
        </jaxrs:providers>
    </jaxrs:server>

</blueprint>