2016-11-21 1 views
0

Je suis confronté au problème suivant et je n'ai trouvé aucune solution de travail pour le moment. j'ai 3 applications différentes qui doivent communiquer entre eux:Java Websocket/MessageHandler retourner à la portée globale?

  • la partie de l'interface utilisateur (1)
  • l'application d'arrière-plan (2)
  • la Microservice "dans le nuage" (3)

L'application principale fournit un service Web (REST) ​​à l'interface utilisateur pour obtenir et mettre des informations de/vers le microservice. Tout ce que je veux récupérer du microservice fonctionne bien, mais: Si je veux mettre des données dans le microservice, les spécifications requièrent une connexion websocket. Cela fonctionne bien aussi, mais le Microservice retourne un message après le (dé) commande avec succès, comme

{"statusCode":200,"messageId":"1234567890"} 

Le problème est maintenant: Comment puis-je saisir ce message dans ma demande et le renvoyer à l'interface utilisateur, si l'utilisateur sait si la commande a réussi?

Pour le moment j'ai essayé ceci:

WebSocketClient.java

@OnMessage 
public void onMessage(Session session, String msg) { 
    if (this.messageHandler != null) { 
     this.messageHandler.handleMessage(msg); 
    } 
} 
public void addMessageHandler(MessageHandler msgHandler) { 
    this.messageHandler = msgHandler; 
} 
public static interface MessageHandler { 

    public String handleMessage(String message); 
} 

MyTotalAwesomeController.java

public class MyTotalAwesomeController { 

    WebSocketClient wsc = new WebSocketClient(); 
    ... 


    @RequestMapping(value="/add", method={RequestMethod.POST, RequestMethod.OPTIONS}) 
    public ResponseEntity<Object> putDataToMicroservice(@RequestBody Map<String, Object> payload, @RequestHeader(value = "authorization") String authorizationHeader) throws Exception { 
    ... 

    wsc.addMessageHandler(new WebSocketClient.MessageHandler() { 
     public String handleMessage(String message) { 

      System.out.println("RETURN MSG FROM WSS : " + message); 
      return message; 
     } 
    }); 

    return ResponseEntity.ok("worked"); 
} 

Je peux voir la sortie de la console du retour de MessageHandler, mais je ne sais pas comment je peux passer cela à la méthode parente pour ret urn insta de juste renvoyer le ResponseEntity.ok().

Je ne suis pas très utilisé pour les connexions WebSocket en Java encore, alors s'il vous plaît ne me jugez pas ;-)

Merci pour votre aide.

+0

Votre contrôleur dispose-t-il d'une méthode init? – nandsito

+0

Il a, avec l'annotation '@ PostContruct'. – sebastian

Répondre

1

Le code ci-dessous fonctionnera sous l'hypothèse que la méthode @OnMessage est exécutée dans un thread géré par le client WebSocket Runtime. Veuillez inspecter le thread qui exécute la méthode @OnMessage.

Si la prémisse ci-dessus est vraie, la méthode putDataToMicroservice(), exécutée par un thread dans la portée globale, attendra que la réponse WebSocket arrive au thread client WS, qui repassera le message au thread d'étendue globale. Ensuite, l'exécution dans votre classe de contrôleur continuera.

public class MyTotalAwesomeController { 

    WebSocketClient wsc = new WebSocketClient(); 

    // Queue for communication between threads. 
    private BlockingQueue<String> queue; 

    @PostConstruct 
    void init() { 

     queue = new SynchronousQueue<>(true); 

     // This callback will be invoked by the WebSocket thread. 
     wsc.addMessageHandler(new WebSocketClient.MessageHandler() { 
      @Override 
      public String handleMessage(String message) { 
       System.out.println("RETURN MSG FROM WSS : " + message); 
       // Pass message to the controller thread. 
       queue.put(message); 
       // Note that the return value is not necessary. 
       // You can take it out of the interface as well. 
       return null; 
      } 
     }); 
    } 

    @RequestMapping(value="/add", method={RequestMethod.POST, RequestMethod.OPTIONS}) 
    public ResponseEntity<Object> putDataToMicroservice(@RequestBody Map<String, Object> payload, @RequestHeader(value = "authorization") String authorizationHeader) throws Exception { 

     // At this point you make a WebSocket request, is that right? 
     doWebSocketRequest(); 

     // This poll call will block the current thread 
     // until the WebSocket server responds, 
     // or gives up waiting after the specified timeout. 
     // 
     // When the WebSocket server delivers a response, 
     // the WS client implementation will execute the 
     // @OnMessage annotated method in a thread 
     // managed by the WS client itself. 
     // 
     // The @OnMessage method will pass the message 
     // to this thread in the queue below. 

     String message = queue.poll(30, TimeUnit.SECONDS); 

     if (message == null) { 
      // WebSocket timeout. 
     } 

     return ResponseEntity.ok("worked"); 
    } 
} 
+0

Pouvez-vous expliquer un peu plus? En attente de votre réponse mise à jour. – sebastian

+0

@sebastian maintenant j'ai mieux compris le problème, c'est un peu plus complexe que je ne le pensais avant. Cela nécessitera une synchronisation de threads. Utilisez-vous tyrus comme implémentation websocket? – nandsito

+0

Non, j'utilise juste javax.websocket. *. Le microservice n'est pas développé par moi, donc je ne peux pas définir ce qui est utilisé côté serveur. – sebastian