Reputation: 149
I've the following situation: I need to send a message on a websocket each time an event is triggered.
MessageController.java
@Controller
public class MessageController {
@Autowired
private SimpMessagingTemplate template;
@RequestMapping(path="/messages", method=POST)
public void send(String message) {
this.template.convertAndSend("/topic/messages", message);
}
}
KafkaConsumeEventHandler.java
@Component
public class KafkaConsumeEventHandler implements ApplicationListener<KafkaConsumeEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(KafkaConsumeEventHandler.class);
public void onApplicationEvent(final KafkaConsumeEvent event) {
LOGGER.info("event detected: publishing...");
LOGGER.info("message to be published: {}",event.getMessage());
//INVOKE CONTROLLER TO SEND MESSAGE HERE
LOGGER.info("event published to websocket.");
}
}
Is it possible to call the send()
method of the controller inside the event handler? Is there a better way to do it?
EDIT
if I perform the this.template.convertAndSend("/topic/messages", message);
inside the event handler (Autowiring the SimMessagingTemplate) I get a nullPointerException on it
Upvotes: 3
Views: 4067
Reputation: 2935
Make your own comm service class with methods that you can call at any time. What I did was creating a CommService
class with static methods to send
public class CommService {
private static SimpMessagingTemplate template;
public static void setTemplate(SimpMessagingTemplate tmplt) {
template = tmplt;
}
public static void send(String message) {
template.convertAndSend("/topic/messages", message);
}
}
Then you can initialize the CommService
via the ContextRefreshHandler
@Component
public class ContextRefreshedHandler implements ApplicationListener<ContextRefreshedEvent> {
private static Logger logger = LoggerFactory.getLogger(ContextRefreshedHandler.class);
@Autowired
private SimpMessagingTemplate template;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
//Initialize the template for web socket messages
CommService.setTemplate(template);
} catch (Exception ex) {
logger.error(getClass().getName(), ex);
}
}
}
This will initialize your template upon server start and then throughout your application where ever you need to send a message you just use CommService.send("message");
So you could then change your MessageController
to this
@Controller
public class MessageController {
@Autowired
private SimpMessagingTemplate template;
@RequestMapping(path="/messages", method=POST)
public void send(String message) {
CommService.send(message);
}
}
Upvotes: 6