I want to create a simple news feed feature on the front end that will automatically update through websocket push notifications.
The technologies involved are:
What I want to achieve on the front end is:
As far as the server side code:
@Scheduled
?).I think I have achieved everything so far except the last part of the server side code. The example I was following uses the websocket in full duplex mode and when a client sends something then the server immediately responds to the message queue and all subscribed clients update. But what I want is for the server itself to send something over Stomp
WITHOUT waiting for the client to make any requests.
At first I created a spring @Controller
and added a method to it with @SendTo("/my/subscribed/path")
annotation. However I have no idea how to trigger it. Also I tried adding @Scheduled
but this annotation works only on methods with void
return type (and I'm returning a NewsMessage object).
Essentially what I need is to have the client initialize a websocket connection, and after have the server start pushing messages through it at a set interval (or whenever an event is triggered it doesn't matter for now). Also, every new client should listen to the same message queue and receive the same messages.
Before starting, make sure that you have the websocket dependencies in your pom.xml
. For instance, the most important one:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework-version}</version>
</dependency>
Then, you need to have your configuration in place. I suggest you start with simple broker.
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/portfolio").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.setApplicationDestinationPrefixes("/app");
config.enableSimpleBroker("/topic", "/queue");
}
}
Then your controller should look like this. When your AngularJs
app opens a connection on /portfolio
and sends a subscription to channel /topic/greeting
, you will reach the controller and respond to all subscribed users.
@Controller
public class GreetingController {
@MessageMapping("/greeting")
public String handle(String greeting) {
return "[" + getTimestamp() + ": " + greeting;
}
}
With regard to your scheduler question, you need to enable it via configuration:
@Configuration
@EnableScheduling
public class SchedulerConfig{}
And then schedule it:
@Component
public class ScheduledUpdatesOnTopic{
@Autowired
private SimpMessagingTemplate template;
@Autowired
private final MessagesSupplier messagesSupplier;
@Scheduled(fixedDelay=300)
public void publishUpdates(){
template.convertAndSend("/topic/greetings", messagesSupplier.get());
}
}
Hope this somehow clarified the concept and steps to be taken to make things work for you.