|
|
@ -38645,11 +38645,10 @@ for purging inactive destinations. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[websocket-stomp-appplication-context-events]] |
|
|
|
[[websocket-stomp-appplication-context-events]] |
|
|
|
==== Broker events and message interception |
|
|
|
==== Listening To ApplicationContext Events and Intercepting Messages |
|
|
|
|
|
|
|
|
|
|
|
The STOMP messaging support publishes the `ApplicationContext` events listed below. |
|
|
|
Several `ApplicationContext` events (listed below) are published and can be |
|
|
|
To subscribe to receive one or more of these events a Spring managed component can |
|
|
|
received by implementing Spring's `ApplicationListener` interface. |
|
|
|
implement Spring's `ApplicationListener` interface. The events are: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* `BrokerAvailabilityEvent` -- indicates when the broker becomes available/unavailable. |
|
|
|
* `BrokerAvailabilityEvent` -- indicates when the broker becomes available/unavailable. |
|
|
|
While the "simple" broker becomes available immediately on startup and remains so while |
|
|
|
While the "simple" broker becomes available immediately on startup and remains so while |
|
|
@ -38686,82 +38685,43 @@ will typically notice the broker is not responding within 10 seconds. Clients ne |
|
|
|
implement their own reconnect logic. |
|
|
|
implement their own reconnect logic. |
|
|
|
==== |
|
|
|
==== |
|
|
|
|
|
|
|
|
|
|
|
An application can also intercept all incoming or outgoing messages by creating a |
|
|
|
Furthermore, an application can directly intercept every incoming and outgoing message by |
|
|
|
`ChannelInterceptor` and registering it on the inbound or outbound channel. See bellow |
|
|
|
registering a `ChannelInterceptor` on the respective message channel. For example |
|
|
|
an example that filters messages based on the message destination and user: |
|
|
|
to intercept inbound messages: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0] |
|
|
|
[source,java,indent=0] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
---- |
|
|
|
---- |
|
|
|
public class AccessControlChannelInterceptor extends ChannelInterceptorAdapter { |
|
|
|
@Configuration |
|
|
|
|
|
|
|
@EnableWebSocketMessageBroker |
|
|
|
|
|
|
|
public class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer { |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Message<?> preSend(Message<?> message, MessageChannel channel) { |
|
|
|
public void configureClientInboundChannel(ChannelRegistration registration) { |
|
|
|
Principal user = SimpMessageHeaderAccessor.getUser(message.getHeaders()); |
|
|
|
registration.setInterceptors(new MyChannelInterceptor()); |
|
|
|
String destination = SimpMessageHeaderAccessor.getDestination(message.getHeaders()); |
|
|
|
|
|
|
|
if(isAllowed(destination, user)) { |
|
|
|
|
|
|
|
return message; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
throw new AccessControlException("Message to destination " + destination |
|
|
|
|
|
|
|
+ " not allowed for user " + user.getName()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean isAllowed(String destination, Principal user) { |
|
|
|
|
|
|
|
// ... |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
In Java config: |
|
|
|
A custom `ChannelInterceptor` can extend the empty method base class |
|
|
|
|
|
|
|
`ChannelInterceptorAdapter` and use `StompHeaderAccessor` or `SimpMessageHeaderAccessor` |
|
|
|
|
|
|
|
to access information about the message. |
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0] |
|
|
|
[source,java,indent=0] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
[subs="verbatim,quotes"] |
|
|
|
---- |
|
|
|
---- |
|
|
|
@Configuration |
|
|
|
public class MyChannelInterceptor extends ChannelInterceptorAdapter { |
|
|
|
@EnableWebSocketMessageBroker |
|
|
|
|
|
|
|
public class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void configureClientInboundChannel(ChannelRegistration registration) { |
|
|
|
public Message<?> preSend(Message<?> message, MessageChannel channel) { |
|
|
|
registration.setInterceptors(myInterceptor()); |
|
|
|
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); |
|
|
|
} |
|
|
|
StompCommand command = accessor.getStompCommand(); |
|
|
|
|
|
|
|
// ... |
|
|
|
@Bean |
|
|
|
return message; |
|
|
|
public AccessControlChannelInterceptor myInterceptor() { |
|
|
|
|
|
|
|
return new AccessControlChannelInterceptor(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
Or in XML config: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[source,xml,indent=0] |
|
|
|
|
|
|
|
[subs="verbatim,quotes,attributes"] |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
|
|
|
|
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
|
|
|
|
|
|
xmlns:websocket="http://www.springframework.org/schema/websocket" |
|
|
|
|
|
|
|
xsi:schemaLocation=" |
|
|
|
|
|
|
|
http://www.springframework.org/schema/beans |
|
|
|
|
|
|
|
http://www.springframework.org/schema/beans/spring-beans.xsd |
|
|
|
|
|
|
|
http://www.springframework.org/schema/websocket |
|
|
|
|
|
|
|
http://www.springframework.org/schema/websocket/spring-websocket.xsd"> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<websocket:message-broker application-destination-prefix="/app"> |
|
|
|
|
|
|
|
<websocket:stomp-endpoint path="/foo"/> |
|
|
|
|
|
|
|
<websocket:simple-broker prefix="/topic"/> |
|
|
|
|
|
|
|
<websocket:client-inbound-channel> |
|
|
|
|
|
|
|
<websocket:interceptors> |
|
|
|
|
|
|
|
<bean id="myInterceptor" class="com.foo.AccessControlChannelInterceptor" /> |
|
|
|
|
|
|
|
</websocket:interceptors> |
|
|
|
|
|
|
|
</websocket:client-inbound-channel> |
|
|
|
|
|
|
|
</websocket:message-broker> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</beans> |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[websocket-stomp-websocket-scope]] |
|
|
|
[[websocket-stomp-websocket-scope]] |
|
|
|