2013-04-09 23 views
12

Ho provato a implementare il sistema di notifica di base per un social network base con p:poll sul livello di visualizzazione e una semplice classe NotificationService che ottiene le nuove notifiche dal DB e aggiorna l'elenco di notifiche di NotificationBean che è viewcoped per ogni utente. Flusso di processo simile a questo:Sistema di notifica con p: poll/push

-Poll calls NotificationBean.getNewNotifications for example every 15 sec. 
--getNewNotifications calls NotificationService and DAO methods 
---notificationList of user is refreshed 
----DataTable on view layer shows new notifications 

Ma la preoccupazione di p:poll è di circa la sua prestazione perché invia una query ad ogni scadenza dell'intervallo.

PrimeFaces ha PrimePush basato su Atmosphere Framework, apre socket Web e sembra più adatto alla creazione di un sistema di notifiche.

Ma non so quali componenti e quali proprietà debbano essere utilizzate. Ha il componente p:socket con la proprietà channel. Devo usare nomi utente come valori channel? Qui di seguito il codice proveniente da primefaces vetrina e riassume le ultime frasi:

<p:socket onMessage="handleMessage" channel="/notifications" /> 

Per quanto ho capito da questa this showcase examplep:socket ascolta notifications canale. E il codice pusher frammento è:

PushContext pushContext = PushContextFactory.getDefault().getPushContext();  
pushContext.push("/notifications", new FacesMessage(summary, detail)); 

Ma questo informerà tutte le pagine utente, ho bisogno di una spinta che notifica utente specifico. Diciamo che ci sono 2 utenti e supponiamo che Utente1 aggiunga Utente2 come amico. Ci deve essere sth. così:

pushContext.push("User2/notifications", new FacesMessage("friendship request", "from User1")); 

Ma non sono sicuro che questo sia l'uso corretto per questo tipo di requisito funzionale o meno. Considerando la scalabilità dell'app possono esserci costi costosi per l'apertura di così tanti canali per un processo.

Grazie per l'aiuto.

+0

Si desidera che un utente invii un messaggio immediato ad un altro utente? –

+0

@RongNK che dipende da come si capisce 'messaggio'. Nella domanda, ho menzionato gli elenchi che includono le notifiche. Se user1 aggiunge user2 come amico o commenta il suo stato, una notifica dovrebbe essere aggiunta all'elenco di notifica di user2 che può essere una semplice lista di stringhe o un elenco di classi di modelli che è più appropriato per la mia implementazione. Quindi sì, deve essere immediato. –

+0

(scusate il mio inglese) ok, penso che non vogliate usare il sondaggio, quindi il server trasmetterà il massaggio e ogni client verrà filtrato, o il server deve memorizzare l'indirizzo del cliente e inviarlo a un indirizzo specifico, che penso. Lascia che un professionista risolva il tuo problema :) –

risposta

8

PrimeFaces push supporta uno o più canali da premere. Essere in grado di creare canali privati ​​per ragioni specifiche; ad esempio per utente come nel tuo caso, puoi creare più di un canale. Avevo usato id unici per questo scopo.

Fondamentalmente, ho implementato un bean gestito che è ambito dell'applicazione che gestisce la corrispondenza dei canali utente che dovrebbe essere considerata. Puoi mantenerlo in diversi modi.

@ManagedBean 
@ApplicationScoped 
public class ChannelsBean { 

    Map<String, String> channels = new HashMap<String, String>(); 

    public void addChannel(String user, String channel) { 
     channels.put(user, channel); 
    } 

    public String getChannel(String user) { 
     return channels.get(user); 
    } 

} 

Quindi iniettare questo bean nel proprio backing bean che invia le notifiche.

@ManagedBean 
@SessionScoped 
public class GrowlBean { 

    private String channel; 

    @ManagedProperty(value = "#{channelsBean}") 
    private ChannelsBean channels; 

    private String sendMessageUser; 

    private String user; 

    @PostConstruct 
    public void doPostConstruction() { 
     channel = "/" + UUID.randomUUID().toString(); 
     channels.addChannel(user, channel); 
    } 

    public void send() { 
     PushContext pushContext = PushContextFactory.getDefault().getPushContext(); 

     pushContext.push(channels.getChannel(sendMessageUser), new FacesMessage("Hi ", user)); 
    } 

    //Getter Setters 
} 

È necessario assegnare il valore del canale a p: socket. Ecco l'esempio di kickoff della pagina;

<p:growl widgetVar="growl" showDetail="true" /> 

<h:form> 
    <p:panel header="Growl"> 
     <h:panelGrid columns="2"> 
      <p:outputLabel for="user" value="User: " /> 
      <p:inputText id="user" value="#{growlBean.sendMessageUser}" required="true" /> 


     </h:panelGrid> 

     <p:commandButton value="Send" actionListener="#{growlBean.send}" /> 
    </p:panel> 
</h:form> 

<p:socket onMessage="handleMessage" channel="#{growlBean.channel}" /> 

<script type="text/javascript"> 
function handleMessage(facesmessage) { 
    facesmessage.severity = 'info'; 

    growl.show([facesmessage]); 
} 
</script> 

Per problemi di scalabilità, è necessario mantenere i canali attivi o inattivi. È possibile rimuovere quello che non è in sessione o inattivo per qualche tempo. Rimuovi i canali usando l'annotazione @PreDestroy quando i bean stanno distruggendo. C'è un canale per una sessione utente nella mia soluzione.

Il mio suggerimento è; non usare nomi utente esplicitamente sulle pagine. Non va bene per ragioni di sicurezza.

+0

Sembra corretto, tuttavia ho ancora qualche dubbio sulla sua prestazione, ci sono altre precauzioni? Tra l'altro, grazie per aver risposto, come puoi immaginare, aspetterò la scadenza della taglia, che sicuramente prenderà la torta. –

+0

Sono a conoscenza dei problemi di prestazioni dello stesso JSF, molte persone con problemi di memorizzazione dello stato di visualizzazione degli utenti riducono le prestazioni. Ma fornisce molte funzionalità, in realtà voglio assaggiarlo da solo e quando lo faccio, dovrebbe essere implementato in modo ordinato per poter ottenere prestazioni massime. Ecco perché ho fatto questa domanda ed è per questo che volevo sbarazzarmi di "p: poll". –

+0

@erencan è questo bean con scope dell'applicazione _thread safe_? a causa di più utenti simultanei, dovresti esserne a conoscenza. – oko

Problemi correlati