2015-12-02 1 views
0

Je suis actuellement développer simple chat multi-pièce basée sur cet exemple:Cadre Ambiance: diffuseur message diffusé plusieurs fois

https://github.com/Atmosphere/atmosphere-samples/blob/master/samples/chat-multiroom/

Mon environnement de développement:

  • Tomee plus 1.7. 2 serveur
  • Version de l'environnement d'exécution 2.4.0
  • Atmosphere-cdi version 2.4.0
  • Java EE 1.7
  • protocole long-polling utilisé

Avant d'expliquer mon problème, voici le mécanisme global de salle de chat j'ai mis en œuvre:

  1. utilisateur A est connecté à la prise " chat/tout ". Cette prise permet d'envoyer ou de recevoir des notifications entre lui et son interlocuteur.

  2. utilisateur A faire une demande de chat de la première application web et attendez (spinner pop-up) une réponse de l'utilisateur B.

  3. L'utilisateur B est également connecté à la prise "chat/all" . L'utilisateur B vérifie à chaque fois, à partir de la deuxième application Web, s'il y a une nouvelle demande de conversation (requête SQL de la base de données). S'il a trouvé une nouvelle demande, il peut ou pas accepter cette demande.

  4. utilisateur B accepte la demande de chat de l'utilisateur A. En ce moment, throught socket "chat/all", l'utilisateur B pousser un message indique qu'il a accepté cette demande . Après cela, l'utilisateur B est connecté à la seconde prise "chat/1" (identifiant aléatoire pour un salon de discussion spécifique). Il attend maintenant (spinner pop-up comme utilisateur B) pour que l'utilisateur A soit connecté à la même prise .

  5. L'utilisateur A reçoit ce message et se connecte au socket "chat/1". Depuis le serveur, l'utilisateur A est maintenant connecté à ce salon de discussion. Il ya deux utilisateurs dans cette salle de chat et je diffuser le message à seulement l'utilisateur B pour notifier que l'utilisateur A est connecté et fermer le pop-up spinner.

je n'ai aucun problème quand je diffuse un message pour une seule ressource. Mais quand je diffuse un message pour deux utilisateurs, la méthode "onMessage" est appelée plusieurs fois!

Voici mon code sur la gestion de salle de chat:

@ManagedService(path = "/chat/{id_room}") 
public final class ChatRoom { 

//many static final private attribute 

private static final Logger logger = LoggerFactory.getLogger(Chat.class); 

@PathParam("id_room") 
private String idChatRoom; 

private final static String CHAT = "/chat/"; 

private final HashMap<Integer, List<String>> users = new HashMap<Integer, List<String>>(); 

private Universe universe; 

private BroadcasterFactory broadcasterFactory = Universe.broadcasterFactory(); 

private AtmosphereResourceFactory resourceFactory = Universe.resourceFactory();  

private ChatMessageEncoderDecoder chatEncodeDecode = new ChatMessageEncoderDecoder(); 

@Message(encoders = { ChatMessageEncoderDecoder.class }, decoders = { ChatMessageEncoderDecoder.class }) 
public final void onMessage(AtmosphereResource r, final ChatMessage message) throws UnsupportedEncodingException { 
    Integer chatRoomId = !NOTIFICATION_SOCKET_ALL.equals(idChatRoom) == true ? Integer.parseInt(idChatRoom) : 0; 
    [...] 
    if(...) { 
     [...] 
    } 
    else { 
     roomsList.add(idChatRoom); 
     boolean messageEmpty = "".equals(message.getMessage()); 
     boolean chatConnectedWithTwoUsers = users.get(chatRoomId).size() > 1; 
     boolean chatConnectedWithOneUser = users.get(chatRoomId).size() == 1; 
      if(chatConnectedWithTwoUsers && MESSAGE_EVENT.equals(message.getEvent())) { //communication between two users to the chat room id 
       Users user = CDIUtil.getBean(RechercheUserService.class).getUserChat(message.getMail()); 
       if(user != null){ 
        try { 
         List<String> listUsersFromRoom = users.get(chatRoomId); 
         message.setUsers(listUsersFromRoom); 
         message.setEvent(MESSAGE_EVENT); 
         logger.info("{} a envoyé le message {}", message.getAuthor(), message.getMessage()); 

         String messageToSend = chatEncodeDecode.encode(message); 
         broadcasterFactory.lookup(CHAT + idChatRoom).broadcast(messageToSend); 

         String messageUtf8 = new String(message.getMessage().getBytes(), "UTF-8"); 
         CDIUtil.getBean(MessageRoomsService.class).createMessageContents(idChatRoom, user, messageUtf8); 
        } catch (IMException e) { 
         message.setEvent(MESSAGE_NOT_REGISTER_EVENT); 
         logger.error("Impossible d'enregistrer le message de l'utilisateur"); 
        } 
       } 
       else{ 
        message.setEvent(USER_NOT_EXIST_EVENT); 
        logger.error("Utilisateur Inconnu"); 
       } 
      } 
      else if(chatConnectedWithOneUser) { //two users connected to the chat room id 
       users.get(chatRoomId).add(r.uuid()); 
       logger.info("L'utilisateur {} a rejoint le chat {}", r.uuid(), idChatRoom); 

       AtmosphereResource resource = resourceFactory.find(users.get(chatRoomId).get(0)); //get the first user connected to the chat room 

       List<String> listUsersFromRoom = users.get(chatRoomId); 
       message.setUsers(listUsersFromRoom); 
       message.setEvent(CHAT_COMPLETE_EVENT); 

       String messageToSend = chatEncodeDecode.encode(message); 
       broadcasterFactory.lookup(CHAT + idChatRoom).broadcast(messageToSend, resource); 
      } 
     } 
    } 
} 

Ainsi, lorsque la diffusion est faite sur l'utilisateur d'interface, il y a 3 messages d'affichage. Par exemple, l'utilisateur A envoie un message "Bonjour, que puis-je faire pour vous?", L'utilisateur B voit 3 fois ce message.

Je pense qu'il y a trois messages parce que trois ressources sont actives sur deux socket.En effet, le premier socket "chat/all" est toujours actif pour une ressource (utilisateur B) et le second socket "chat/1" est actif pour deux ressources (utilisateur A et utilisateur B). Il y a trois ressources.

Y a-t-il quelqu'un qui est déjà confronté à ce problème? Ou y at-il quelqu'un qui a une idée sur la façon de le réparer?

Répondre

0

J'ai eu le même problème too..I ont résolu de lire ce lien Multiple messages arrive as single response body or message received are incomplete:

J'ai ajouté à web.xml cette init-param dans mon atmosphère Servlet

<init-param> 
    <param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name> 
    <param-value>org.atmosphere.client.TrackMessageSizeInterceptor</param-value> 
</init-param> 

et côté client J'ai ajouté le trackMessageLength : true dans la demande:

var request = { url: document.location.toString() + 'chat', 
       contentType : "application/json", 
       logLevel : 'debug', 
       transport : 'long-polling' , 
       trackMessageLength : true, 
       fallbackTransport: 'long-polling'}; 

Comme il est indiqué dans ce lien

Si vous diffusez plusieurs messages et que le serveur sous-jacent les met en mémoire tampon, votre rappel ou fonction atmopshere.js peut être appelé avec plusieurs messages au lieu d'un seul message. Cela peut ne pas être un problème si vous utilisez du texte, mais si vous utilisez JSON, l'analyse peut échouer car votre callback/fonction est appelée avec plusieurs messages JSON.

J'espère que cela fonctionnera aussi pour vous!