简体   繁体   中英

Spring - send message to websocket on event

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

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);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM