2012-11-30 2 views
4

J'utilise Atmosphere dans mon application Spring MVC pour faciliter le push, en utilisant un transport streaming.Atmosphère: Plusieurs abonnements sur un seul HttpConnection

Tout au long du cycle de vie de mon application, le client s'abonne et se désinscrit pour de nombreux sujets différents.

L'atmosphère semble utiliser une seule connexion http par abonnement, c'est-à-dire que chaque appel à $.atmosphere.subscribe(request) crée une nouvelle connexion. Cela épuise rapidement le nombre de connexions autorisées depuis le navigateur vers le serveur atmosphère. Au lieu de créer une nouvelle ressource à chaque fois, j'aimerais pouvoir ajouter et supprimer le AtmosphereResource aux diffuseurs après sa création initiale.

Cependant, comme AtmosphereResource est une à une représentation de la demande entrante, chaque fois que le client envoie une requête au serveur, il arrive sur un nouveau AtomsphereResource, ce qui signifie que je n'ai pas moyen de référencer la ressource originale et l'ajouter au Broadcaster du sujet.

J'ai essayé d'utiliser à la fois $.atmosphere.subscribe(request) et d'appeler atmosphereResource.push(request) sur la ressource renvoyée par l'appel subscribe() d'origine. Cependant, cela n'a fait aucune différence.

Quelle est la bonne façon d'aborder cela?

+0

J'ai exactement la même question: le client est abonné à de nombreux diffuseurs sur une connexion, avec le client ajout et la suppression des diffuseurs à volonté. Cependant, je ne suis pas allé aussi loin que vous dans mes tests. Avez-vous eu plus loin avec ça? Cela devrait sûrement être possible? Avez-vous essayé la liste de diffusion? – Fletch

+0

@Fletch Yep, ça marche, grâce à quelques conseils des gars sur le canal IRC. Posté ma solution ci-dessous. –

Répondre

9

Voici comment je l'ai eu de travail:

Tout d'abord, lorsque le client fait leur connexion initiale, assurez-vous que les en-têtes spécifiques à l'atmosphère sont acceptées par le navigateur avant d'appeler suspend():

@RequestMapping("/subscribe") 
public ResponseEntity<HttpStatus> connect(AtmosphereResource resource) 
{ 
    resource.getResponse().setHeader("Access-Control-Expose-Headers", ATMOSPHERE_TRACKING_ID + "," + X_CACHE_DATE); 
    resource.suspend(); 
} 

Ensuite, Lorsque le client envoie des demandes d'abonnement supplémentaires, bien qu'elles se trouvent sur un autre resource, elles contiennent le ATMOPSHERE_TRACKING_ID de la ressource d'origine. Cela vous permet de regarder vers le haut par le resourceFactory:

@RequestMapping(value="/subscribe", method=RequestMethod.POST) 
public ResponseEntity<HttpStatus> addSubscription(AtmosphereResource resource, @RequestParam("topic") String topic) 
{ 
    String atmosphereId = resource.getResponse().getHeader(ATMOSPHERE_TRACKING_ID); 
    if (atmosphereId == null || atmosphereId.isEmpty()) 
    { 
     log.error("Cannot add subscription, as the atmosphere tracking ID was not found"); 
     return new ResponseEntity<HttpStatus>(HttpStatus.BAD_REQUEST); 
    } 
    AtmosphereResource originalResource = resourceFactory.find(atmosphereId); 
    if (originalResource == null) 
    { 
     log.error("The provided Atmosphere tracking ID is not associated to a known resource"); 
     return new ResponseEntity<HttpStatus>(HttpStatus.BAD_REQUEST); 
    } 

    Broadcaster broadcaster = broadcasterFactory.lookup(topic, true); 
    broadcaster.addAtmosphereResource(originalResource); 
    log.info("Added subscription to {} for atmosphere resource {}",topic, atmosphereId); 

    return getOkResponse(); 
} 
+0

Fantastique, merci beaucoup. – Fletch

+0

'resource.getResponse(). GetHeader (ATMOSPHERE_TRACKING_ID)' ne semble pas fonctionner pour moi (pourrait être de ma faute). Je dois appeler 'atmosphereResource.uuid()' à la place. – TrogDor

+1

Comment avez-vous obtenu une instance de la variable 'broadcasterFactory'? – kiltek

Questions connexes