2012-03-29 8 views
5

Was im folgenden Szenario am besten/guter Service Bindung/Kommunikation Praxis ist (ich hoffe, der Titel etwas sinnvoll ist):Best Practice für Async-Kommunikation zwischen den Diensten

Eine Business-Schicht (BL) mehrere Service-Methoden umfasst, die gemeinsam nutzen (als gemeinsamer Kommunikationsendpunkt) ein asynchroner Socket-Dienst (SS), der an diese Methoden gebunden sein kann und für Socket-IO verwendet wird.

z. der BL ergreift SL und ruft send (Nachricht) auf und wartet dann auf eine Antwort.

Ich verwendete Callbacks und das Binder-Muster zuerst. Da ich Probleme mit einem klaren Design hatte, das das Bindemuster verwendet (Fehlen einer Nachrichtenwarteschlange und alles, was im Hauptthread erledigt wurde), versuche ich jetzt das Nachrichtenmuster.

Also im Grunde, BL Dienstleistungen und der SL-Service haben jetzt eine Messenger und einen entsprechenden Handler:

private final IncomingHandler incomingHandler = new IncomingHandler(); 
private final Messenger messengerReceiver = new Messenger(incomingHandler); 
private class IncomingHandler extends Handler { 
    @Override 
    public void handleMessage(Message msg) { 
    ... 
    } 
} 

Einer des BLs ist eine AbstractAccountAuthenticator Unterklasse

addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options){ 
    ... 
    if(socketConnectionState != null){ 
     Bundle authBundle = new Bundle(); 
     authBundle.putString("password", password); 
     authBundle.putString("username", account.name); 
     Message message = Message.obtain(null, SocketConnectionHandler.SEND_REQUEST, authBundle); 
     message.replyTo = messengerReceiver; 
     socketConnectionState.getMessenger().send(message); 
...} 

Implementierung, die auch die SL verwendet um den authToken zu erhalten. Die addAccount() -Methode erfordert entweder, das Ergebnis (das authToken) sofort in einem Bundle zurückzugeben oder stattdessen die Antwort-Callback-Methoden aufzurufen. Wenn ich jetzt das Authentifizierungs-Token in addAccount via SL anfrage, wie würde ich dann das Ergebnis zurückgeben?

Das Hauptproblem hierbei ist, dass das Ergebnis nicht an die aufrufende Methode (addAccount()) zurückgegeben wird, sondern an den MessengerReceiver-Handler.

Der einzige Weg, an den ich denken könnte, ist eine BlockingQueue, die die Antwort vom Message-Handler angeboten wird und die dann innerhalb der addAccount() -Methode genommen wird, aber das fühlt sich wirklich überheblich an. Andere Ideen? Richtiger Ansatz überhaupt?

Antwort

0

Ihr Problem tritt nur auf, wenn Sie die Prämisse angeben, dass das Beantworten das Anliegen des Nachrichtenhandlers ist.

Ich hatte vor kurzem das gleiche Problem bei der Arbeit. Wir lösten es durch die Argumentliste der Nachrichtenhandler

public interface MessageHandler { 
    public void receivedMessage(Message message, ResponseChannel channel); 
} 

interface ResponseChannel { 
    public void respond(Message response); 
} 

interface Message {} 

Natürlich erstreckt man eine Elementvariable in jedem Fall von MessageHandler vorstellen könnte, aber das würde die Staatenlosigkeit entfernen - am Ende, das Prinzip hinter beiden Ansätzen ist die gleich.

Noch gibt es eine andere Möglichkeit.

Trennung von Besorgnis

Wie ich schon sagte der Beantwortung der Antwort auf die Nachrichten-Handler die zusätzliche Verantwortung zuweisen einen schlechten Geschmack hinterlässt. Der Nachrichtenhandler ist bereits für eingehende Nachrichten verantwortlich.

Er verarbeitet die eingehende Nachricht, die ein kurzer Prozess sein sollte, relevante Parameter zu extrahieren und die Nachricht an die interessierten Parteien weiterzuleiten oder die entsprechenden Methoden auf dem Modell oder einem Controller aufzurufen.

Es sollte ein kurzer und nicht erschöpfender Prozess sein, da Message-Handler logischerweise nicht Teil der Sende-/Empfangskomponente sind, aber dort registriert sind und einen Thread oder Thread-Pool mit allen anderen Message-Handlern und ihren Aufrufen teilen .

Also wie sollte man Antworten dann behandeln? Daraus folgt, dass, wenn es nicht in der Verantwortung der Sachbearbeiter liegt, die vom Tierhalter benachrichtigten Parteien Maßnahmen ergreifen sollten.

public interface MessageHandler { 
    public void receivedMessage(Message message, ApplicationContext context); 
} 

interface ApplicationContext { 
    public void notifyUserJoined(String name); 
} 

interface Message { 
    public String getUser(); 
}