Part-1: Tying in with the Java EE Platform
Last updated
Was this helpful?
Last updated
Was this helpful?
The Java WebSocket API baked into the Java EE Platform (Java EE 7 and above). This chapter talks about other Java EE technologies which the WebSocket API integrates with. We will explore interoperability with the following Java EE specifications.
Enterprise Java Beans (EJB)
Context and Dependency Injection (CDI)
Before we dive in, please note that
container managed injection features are not available to WebSocket endpoints which override the container implemented initialization (using the
ServerEndpointConfig.Configurator
)
In this section, we'll look at how WebSocket endpoints can integrate with EJBs. The following aspects will be explored
Decorating WebSocket endpoints with annotations
in WebSocket endpoints
Using in WebSocket endpoints
Important: Please note that support for EJB annotations on WebSocket endpoints is not a standard (specification mandated) feature
@Singleton
By default, the container creates a new WebSocket (server) endpoint instance per client. In case you need a single instance, you can implement this using a custom ServerEndpointConfig.Configurator
(override the to be specific and return the same instance). As mentioned in the Configuration chapter, this means that you might have to sacrifice some of the (Java EE) platform related services like dependency injection
Alternate solution - A similar behavior can be achieved by decorating the WebSocket endpoint with @Singleton
Concurrency semantics
In case of a @Singleton
, all the clients will interact with one server endpoint instance. Here is a quick summary of how the EJB as well as WebSocket threading semantics are applied
The above mentioned semantics are with respect to ALL the WebSocket clients. From the point of view of a single client, the default strategy of one thread at a time, per endpoint instance per client continues to apply (more in the Concurrency chapter)
@Stateful
It's only possible to have one @Stateful
EJB instance per WebSocket client - this is in tune with the default behavior outlined by the WebSocket specification. Things would get interesting from a state management perspective
passivation capabilities of Stateful
beans can be leveraged if needed (be careful about not storing references to non java.io.Serializable
objects)
EJB containers also support replication of Stateful beans across clusters which means that client state can be saved across multiple JVMs. With some custom logic (since javax.websocket.Session
is not Serializable
), it might be possible to implement a highly availabile (HA) setup for WebSocket applications
In the above example
userId
and (chat) history
are user specific state which can be passivated, restored and replicated (across JVMs)
Session
is marked transient
since we do not intend to serialize it to disk not over network (other JVMs in cluster)
@Stateless
Using @Stateless
style endpoints can prove to be useful as well. Here are some of the noteworthy points
Once allocated, the same bean instance is used throughtout the lifecycle of the Session
All EJB flavors (except MessageDriven
) Stateless
, Stateful
and Singleton
can be injected into WebSocket endpoints. A good strategy would be to implement core business logic using EJBs which can be then invoked from within WebSocket endpoint lifecycle (callback) methods
@Stateful
EJBThere is a one-to-one association between the WebSocket client & endpoint (which is by default) as well as the injected Stateful
EJB instance, which makes it an ideal candidate for storing client specific state. It offers advanced semantics as compared to simple java.util.Map
interface exposed by getUserProperties
method in javax.websocket.Session
)
@Stateless
and @Singleton
EJBs@Stateless
and @Singleton
EJBs can also be injected seamlessly. All the EJB features like transactions, simpler concurrency model, lifecycle management etc. can be leveraged
The table below summarizes the behavior when EJBs are injected into WebSocket endpoints
Injected EJB type
Behavior
@Stateless
a random instance is picked up from the pool
@Singleton
the same instance is injected
@Stateful
the bean is tied to the endpoint instance
beans.xml (in WEB-INF) is required in order to leverage Dependency Injection support
Apply the interceptor
Although CDI integration offers features similar to that of the EJB ones i.e. Dependency Injection and Interceptors, it's worth noting that these are officialy supported by the specification (Section 7.1.1)
As part of the the DI support, @javax.inject.Inject
can be used (on constructor, method, field) to inject CDI managed beans
CDI Interceptors introduce an additional layer of abstraction. Let's look at a simple example
First up, we need to define an Interceptor binding
Implement our interceptor and bind it
Apply the interceptor where needed (via the binding)
Oh, and don't forget to specify the interceptor in beans.xml (compulsory)
The CDI based interceptor works for EJB based WebSocket endpoints as well
Here is a quick review of what's supported for WebSocket in terms of CDI and EJB integration. Everything works.. Awesome!
Feature
Supported in EJB Annotated WebSocket Endpoint ?
Supported in Plain WebSocket endpoint ?
Inject CDI managed beans
yes
yes
Inject EJBs with @Inject
yes
yes
Inject EJBs with @EJB
yes
yes
Use CDI interceptors
yes
yes
Use EJB interceptors
yes
yes
This concludes part I of this chapter. The second (and final) part will cover Servlet and Security related integration points
The Singleton
bean default approach () ensures single threaded access across all connected clients
If thread-safety is not a concern (e.g. in case where you do not deal with client specific data/state in your logic) and you do not want the single-threaded access model to be a bottleneck, override the default behavior by switching to a which allows concurrent threads to access the methods (unless of course a WRITE lock is not already in effect)
Instance creation: A random instance is picked up from the (as per availability). It's possible to fine tune the pool in order to extract maximum performance (e.g. deploy time initilization if EJBs etc.)
Tip: Implement a in the Stateful
EJB and call it from the @OnClose
callback method. This will ensure that the EJB is removed from the memory immediately rather than depending upon
Just like EJB based injection support, Interceptor support in not officially supported by the WebSocket specification. You can implement cross-cutting business logic and then tie them to specific classes/methods using the @Interceptors
. You should employ the annotation for the type of interceptor i.e. @AroundInvoke
, @AroundConstruct
etc.