Getting Groovy with Spring and WebSockets

This month’s release of Java EE 7 delivers a finalized Java WebSocket API specification, which can be leveraged with Spring and Groovy to build robust WebSocket-driven applications. Spring 4 will come with support for WebSockets, but we can utilize existing JSR-356 reference implementations to build applications with WebSocket support with any version of Spring.

Introducing Project Tyrus

Project Tyrus is a JSR-356 reference implementation that comes to the community from Oracle. Building on the specification’s standards, application developers can easily develop WebSocket applications using Project Tyrus’ robust API. Tyrus also comes with standalone server, client, and container libraries that allow developers to build WebSocket applications outside of a normal web application stack.

The examples in this post will demonstrate WebSockets from a standalone application implementation, but the concepts and code can easily be adapted to a Spring Web-MVC application, or a Grails application context, with little effort.

Project Tyrus’ Standalone Maven coordinates are:

This includes the Java WebSocket API artifacts, which can be found here:

Getting Started

Building WebSocket endpoints on top of JSR-356 consists of a three-step process, wherein developers must register a ServerApplicationConfig that defines ServerEndpoints with a ServerApplicationContainer. The specification also defines a Builder that allows developers to easily register a ServerEndpoint for a given path.

Classes annotated with the @ServerEndpoint annotation must provide a path, and in the ServerApplicationConfig, should be returned from the getAnnotatedEndpointClasses method. Annotated classes can also use method-level annotations to handle the different phases of the request lifecycle. Available method-level annotations are: @OnOpen, @OnMessage, @OnError, and @OnClose.

Once the ServerEndpoints are written and defined within the ServerApplicationConfig, the next step is to register them with the ServerApplicationContainer. Project Tyrus’ standalone implementation provides a Server class that developers can instantiate to bootstrap the WebSocket container.

The above code will start the server on port 8025 using the context-root /context. Paths from ServerEndpoints will be derived in that context, in a similar way as regular web application containers.

From Project Tyrus’ client module, we can get access to an instance of a ClientManager, which allows for developing the client WebSocket interaction with the server. The ClientManager can either take a concrete class that is an instance of an Endpoint, or a regular POJO annotated with @ClientEndpoint.

A simple Spock test demonstrates how to build the client/server interaction with Project Tyrus.

Involving Spring

The key to involving Spring in the Tyrus container lies in the understanding that Tyrus maintains its own application container and is entirely separate from the Spring application context. In order to integrate Spring in the WebSocket request lifecycle, we must first give it an influence on the endpoint resolution process. Once we have the Tyrus container configured to allow Spring to resolve the endpoints, then the endpoints can be regular Spring beans, and therefore participate in the application context to benefit from features like dependency injection and scoping.

Tyrus makes use of the service locator pattern to help resolve ComponentProvider instances. A ComponentProvider is responsible for informing the Tyrus container if a class is supported by its resolution strategy, and if so to provide an instance that will be used as the endpoint. To make use of Spring’s application context, we’ll need to create a ComponentProvider implementation to help facilitate resolving endpoints from the Spring context.

In this example, beans that are wired properly by name will be resolved from the Spring application context. Since the ComponentProvider is also a participant in the application context, it must also be defined as a bean in the Spring configuration.

After the SpringComponentProvider is in place and wired appropriately to the Spring application context, we must then register it as a ComponentProvider in Tyrus’ service locator registry. To do this, we’ll simply create a file named org.glassfish.tyrus.spi.ComponentProvider and put it in the META-INF/services directory of the application’s resources. This should have a single line entry with the fully qualified class name of the SpringComponentProvider:

Tying it Together

Now that the necessary pieces are in place, the final thing that must be done is to wire a complete Spring application context, including the Tyrus server, the SpringComponentProvider, and each endpoint that we want resolved from the Spring context. We can make use of Spring’s Java Configuration to instantiate the Tyrus server, as well as make it an autowire candidate for beans that might find it useful.

About the Author

Object Partners profile.

One thought on “Getting Groovy with Spring and WebSockets

  1. Breaur Eugen says:

    This works for tyrus 1. But in 1.3 I don’t see the Component provider. Is there a easier way to use spring beans ?

  2. Dan Woods says:

    At a quick glance, it looks like in 1.3 the ComponentProvider was moved to the core module. Seems to be homed in org.glassfish.tyrus.core.ComponentProvider now.

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
An Exploration in Rust: Musings From a Java/C++ Developer
Why Rust? It’s fast (runtime performance) It’s small (binary size) It’s safe (no memory leaks) It’s modern (build system, language features, etc) When Is It Worth It? Embedded systems (where it is implied that interpreted […]
Getting Started with CSS Container Queries
For as long as I’ve been working full-time on the front-end, I’ve heard about the promise of container queries and their potential to solve the majority of our responsive web design needs. And, for as […]
Simple improvements to making decisions in teams
Software development teams need to make a lot of decisions. Functional requirements, non-functional requirements, user experience, API contracts, tech stack, architecture, database schemas, cloud providers, deployment strategy, test strategy, security, and the list goes on. […]
JavaScript Bundle Optimization – Polyfills
If you are lucky enough to only support a small subset of browsers (for example, you are targeting a controlled set of users), feel free to move along. However, if your website is open to […]