2014-08-29 20 views
5

sto usando il framework Spring e ho un controller websocket di lavoro che assomiglia a questo:Invia messaggio a tutti i clienti tramite SimpMessagingTemplate in ServletContextListener

@Controller 
public class GreetingController { 

    @MessageMapping("/hello") 
    @SendTo("/topic/greetings") 
    public Greeting greeting(HelloMessage message) throws InterruptedException { 
     return new Greeting("Hello, " + message.getName() + "!"); 
    } 
} 

Ho anche questa configurazione:

@Configuration 
@EnableWebSocketMessageBroker 
public class HelloWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { 

    @Override 
    public void configureMessageBroker(MessageBrokerRegistry config) { 
     config.enableSimpleBroker("/topic"); 
     config.setApplicationDestinationPrefixes("/app"); 
    } 

    public void registerStompEndpoints(StompEndpointRegistry registry) { 
     registry.addEndpoint("/hello").withSockJS(); 
    } 
} 

Questa parte funziona alla grande! Posso inviare e ricevere messaggi con successo tra due o più browser utilizzando Stomp.js. Ecco la parte che non funziona. Ho implementato uno ServletContextListener che contiene un oggetto personalizzato che, per motivi di semplicità, ho chiamato "notifier". Il notificatore ascolta determinati eventi che si verificano sul lato server. Quindi chiama il metodo 'notify', che dovrebbe inviare dettagli sull'evento a tutti i client. Tuttavia, non funziona.

@WebListener 
public class MessageListener implements ServletContextListener, Notifiable { 

    private Notifier notifier; 

    @Autowired 
    private SimpMessagingTemplate messageSender; 


    public MessageListener() { 
     notifier = new Notifier(this); 
    } 

    public void contextInitialized(ServletContextEvent contextEvent) { 
     WebApplicationContextUtils 
     .getRequiredWebApplicationContext(contextEvent.getServletContext()) 
     .getAutowireCapableBeanFactory() 
     .autowireBean(this); 

     notifier.start(); 
    } 

    public void contextDestroyed(ServletContextEvent contextEvent) { 
     notifier.stop(); 
    } 

    public void notify(NotifyEvent event) { 
     messageSender.convertAndSend("/topic/greetings", new Greeting("Hello, " + event.subject + "!")); 
    } 
} 

non ottengo un'eccezione. Lo SimpMessagingTemplate è stato iniettato con successo da Spring, quindi non è nullo. Sono stato in grado di inserire il codice Spring e ho capito che lo subscriptionRegistrySimpleBrokerMessageHandler è vuoto quando si utilizza lo SimpMessagingTemplate. Quindi deve essere un'istanza separata da quella utilizzata dai controller. Come posso ottenere lo stesso subscriptionRegistry utilizzato dai controller?

+0

Curioso se hai trovato una risposta. Lo stesso comportamento si verifica quando si chiama da una classe ApplicationEvent di Spring. –

+0

Ci scusiamo per tornare a questo dopo tanto tempo. Ho pubblicato la mia soluzione qui sotto. – battmanz

risposta

1

La soluzione era quella di utilizzare la classe di primavera ApplicationListener invece di un ServletContextListener, e per ascoltare appositamente per il ContextRefreshedEvent.

Questo è il mio esempio di lavoro:

@Component 
public class MessagingApplicationListener implements ApplicationListener<ContextRefreshedEvent>, Notifiable { 
    private final NotifierFactor notifierFactory; 
    private final MessageSendingOperations<String> messagingTemplate; 
    private Notifier notifier; 

    @Autowired 
    public MessagingApplicationListener(NotifierFactor notifierFactory, MessageSendingOperations<String> messagingTemplate) { 
     this.notifierFactory = notifierFactory; 
     this.messagingTemplate = messagingTemplate; 
    } 

    @Override 
    public void onApplicationEvent(ContextRefreshedEvent event) { 
     if (notifier == null) { 
      notifier = notifierFactory.create(this); 
      notifier.start(); 
     } 
    } 

    public void notify(NotifyEvent event) { 
     messagingTemplate.convertAndSend("/topic/greetings", new Greeting("Hello, " + event.subject + "!")); 
    } 

    @PreDestroy 
    private void stopNotifier() { 
     if (notifier != null) { 
      notifier.stop(); 
     } 
    } 
} 
+0

cos'è Notificabile, NotifierFactor e Notifier? per favore aiuto, voglio solo chiamare il mio websocket. –

+0

Quelle sono astrazioni che ho inventato sul posto per illustrare il mio punto. Tuttavia, rappresentano servizi reali che potresti avere nella tua applicazione. Se si utilizza un WebSocket, si presume che si verifichi un evento sul lato server per il quale si desidera inviare un messaggio al client. Queste astrazioni rappresentano semplicemente quell'evento lato server. – battmanz

+0

Ho SimpMessagingTemplate nella stessa classe del controller e sto chiamando webserice per chiamare il websocket usando templet, non ci sono errori ma il mio websocket non viene chiamato. –

Problemi correlati