2012-03-29 10 views
5

Co jest najlepsze/dobra obsługa wiązania/praktyka komunikacji w następującym scenariuszu (mam nadzieję, że tytuł jest dość wymowny):Najlepsze praktyki dla komunikacji asynchronicznej pomiędzy służbami

Warstwa biznesowych (BL) zawiera kilka metod serwisowego akcję (jako wspólny punkt końcowy komunikacji) asynchroniczna usługa gniazda (SS), która może być związana tymi metodami i używana dla gniazda IO.

E.g. BL pobiera SL i wywołuje send (wiadomość), a następnie czeka na odpowiedź.

Najpierw użyłem wywołań zwrotnych i wzoru segregatora. Ponieważ miałem pewne problemy z wyraźnym projektem wykorzystującym wzorzec segregatorów (brak kolejki komunikatów i wszystkiego, co robi główny wątek), teraz próbuję wzorca komunikatu.

Więc w zasadzie, usługi BL i obsługa SL mają teraz Messenger i odpowiedniej obsługi:

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

Jednym z BLS jest podklasą AbstractAccountAuthenticator realizacji

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); 
...} 

który również używa SL aby uzyskać authToken. Metoda addAccount() wymaga natychmiastowego zwrócenia wyniku (authToken) w pakiecie lub w celu wywołania metod zwrotnych odpowiedzi. Teraz, jeśli zażądam tokena autoryzacji wewnątrz funkcji addAccount za pośrednictwem SL, jak mogę obsłużyć, aby przekazać wynik ponownie?

Głównym problemem jest to, że wynik nie jest zwracany do metody wywołania (addAccount()), ale do obsługi programu messengerReceiver.

Jedyny sposób, jaki mogłem wymyślić, to BlockingQueue, w którym oferowana jest odpowiedź przez program obsługi komunikatów, a który jest następnie pobierany wewnątrz metody addAccount(), ale to naprawdę wydaje się uciążliwe. Inne pomysły? Właściwe podejście w ogóle?

Odpowiedz

0

Twój problem pojawia się tylko wtedy, gdy przedstawisz założenie, że reakcja jest problemem obsługi wiadomości.

Niedawno miałem ten sam problem w pracy. Rozwiązaliśmy go poprzez rozszerzenie wykazu argument operatora komunikatów

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

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

interface Message {} 

Oczywiście można wprowadzić zmienną użytkownika w każdej instancji MessageHandler, ale to by usunąć bezpaństwowości - w końcu zasada tyłu obu podejść jest podobnie.

Nadal istnieje inna możliwość.

Oddzielenie obawy

Jak powiedziałem przed przypisaniem dodatkowej odpowiedzialności odpowiadając odpowiedź do obsługi komunikatów pozostawia niesmak. Obsługa wiadomości ma już obowiązek odbierania wiadomości przychodzących.

Obsługuje przychodzące wiadomości, co powinno być krótkim procesem wyodrębniania odpowiednich parametrów i przekazywania wiadomości do zainteresowanych stron lub wywoływania odpowiednich metod na modelu lub na kontrolerze.

Powinien to być krótki i niewyczerpujący proces, ponieważ procedury obsługi komunikatów nie są logiczne, nie są częścią składnika wysyłającego/odbierającego, ale są tam zarejestrowane i dzielą wątek lub pulę wątków ze wszystkimi innymi programami obsługi wiadomości i ich wywołaniami .

Jak zatem należy obsługiwać odpowiedzi? Wynika z tego, że jeśli nie leży to w zakresie odpowiedzialności handlera, strony, które zostały powiadomione przez osobę odpowiedzialną za obsługę, powinny podjąć działanie.

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

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

interface Message { 
    public String getUser(); 
}