2014-11-07 11 views
10

Do programowania asynchronicznego, Jersey (JAX-RS) zapewnia wywołanie zwrotne ConnectionCallback, które ma zostać wykonane, gdy połączenie zostanie zerwane. Od Jersey docs:AsyncResponse ConnectionCallback nie uruchamia się w Jersey

Ponieważ niektóre wnioski asynchroniczny może zająć dużo czasu, aby przetwarzać klient może decydują się zakończyć swoje połączenie z serwerem przed odpowiedzią zostało wznowione lub zanim został całkowicie napisany do klienta. Aby uzyskać dostęp do tych przypadków użycia, można użyć ConnectionCallback. To wywołanie zwrotne zostanie wykonane tylko wtedy, gdy połączenie zostało przedwcześnie przerwane lub utracone podczas zapisywania odpowiedzi na kliencie klienta. Zwróć uwagę, że to wywołanie zwrotne nie zostanie wywołane, gdy odpowiedź zostanie pomyślnie napisana, a połączenie z klientem zostanie zamknięte zgodnie z oczekiwaniami.

Brzmi świetnie, ale nigdy nie uda mi się tego zrobić.

Oto niektóre kodu:

@GET 
@Produces(MediaType.TEXT_PLAIN) 
@ManagedAsync 
@Path("/poll") 
public void poll(@Suspended final AsyncResponse asyncResponse) { 
    asyncResponse.register(new CompletionCallback() { 
     @Override 
     public void onComplete(Throwable throwable) { 
      logger.info("onComplete called."); 
     } 
    }); 

    asyncResponse.register(new ConnectionCallback() { 
     @Override 
     public void onDisconnect(AsyncResponse disconnected) { 
      logger.info("onDisconnect called."); 
     } 
    }); 

    asyncResponse.setTimeout(POLL_TIMEOUT_SECONDS, TimeUnit.SECONDS); 
    asyncResponse.setTimeoutHandler(new TimeoutHandler() { 
     @Override 
     public void handleTimeout(AsyncResponse asyncResponse) { 
      logger.info("handleTimeout called."); 
      asyncResponse.resume(Response.status(Response.Status.OK).entity("TIMEOUT").build()); 
     } 
    }); 
} 

Pozostałe dwie callbacks pokazano CompletionCallback i TimeoutHandler, ogień dobrze, bezbłędnie. Jeśli zostanie osiągnięty określony czas oczekiwania, uruchomi się TimeoutHandler. Jeśli instancja AsyncResponse zostanie wznowiona, uruchomiona zostanie funkcja CompletionCallback.

Jednak z funkcją ConnectionCallback mogę zamknąć, zabić lub w inny sposób zatrzymać klienta, który jest podłączony do usługi sieciowej pokazanej powyżej, a ConnectionCallback nigdy nie zostanie wyrzucony.

Czy brakuje mi czegoś? Czy usługa ConnectionCallback została zaimplementowana w Jersey? (Jest to opcjonalne w specyfikacji JAX-RS, ale dokumentacja firmy Jersey mówi o tym, jakby była zaimplementowana.)

Wszelkie dane wejściowe będą mile widziane.

Odpowiedz

4

ConnectionCallback jest rzeczywiście zaimplementowany w Jersey. Ponadto wywoływane jest również wywołanie zwrotne "onDisconnect". Można również zapoznać się z poniższym kodzie w Jersey:

https://github.com/jersey/jersey/blob/a6ff4d50da13d45ad90fd7375a15a31afa02e489/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java#L723

https://github.com/jersey/jersey/blob/b7907e279010e7035a7a3e529993d22f77a21e08/core-server/src/main/java/org/glassfish/jersey/server/ChunkedOutput.java#L246-L252

Są wyrzucane w przypadku IOException podczas pisania odpowiedzi. Tak więc, aby odpowiedzieć na twoje pytanie, nie ma mechanizmu odpytywania lub podobnego mechanizmu, który stale sprawdza, czy klient jest podłączony, a metoda onDisconnect jest wywoływana tylko wtedy, gdy istnieje wyjątek IOException, który zwykle występuje podczas pisania odpowiedzi.

Aktualizacja 1:

Również chciałbym przytoczyć własne pytanie:

„Ta funkcja zwrotna zostanie wykonany tylko wtedy, gdy połączenie było przedwcześnie rozwiązana lub utracone podczas gdy odpowiedź jest bycie napisany na odwrotnej klienta”

Więc chyba spróbować napisać do stream, Twój callback nigdy nie zostanie uruchomiony.Aby było jasne, nie należy go wywoływać, gdy nie ma odpowiedzi na zapis lub gdy odpowiedź wynosi 202, raczej ma być wywołana, gdy połączenie zostało przedwcześnie zakończone podczas gdy odpowiedź jest zapisywana.

Obawiam się, że nie ma obejścia tego problemu, chyba że napiszesz jakieś niskopoziomowe programowanie sieciowe z pewnego rodzaju sondowaniem. Ale nie poleciłbym ci tego.

Sugeruję, abyś ponownie przemyślał sposób, w jaki chcesz poradzić sobie z tym niepowodzeniem.

+0

Cześć, dziękuję za odpowiedź. Ustaliłem już, że jest on zaimplementowany w Jersey, chociaż w moim debugowaniu nigdy nie byłem w stanie wyzwolić 'onDisconnect' poprzez różne sposoby zakończenia połączenia klienta, chociaż może to być specyficzne dla środowiska. Ponadto, dla nagrody, muszę wiedzieć, jak sobie poradzić z faktem, że onDisconnect zdarzyłoby się tylko po próbie napisania odpowiedzi, tj. Po rozpatrzeniu wniosku kompletnie i dlaczego nie jest on przywoływany, gdy nie ma jednostki pisać (spróbuj złapać tylko pisanie encji, nie dla 204) – James

+0

Cześć dzięki za aktualizację, bez względu na to, czy powinna być wywołana podczas pisania odpowiedzi 202, ponieważ wciąż wysyła odpowiedź do klienta, nawet bez ciała. Jawadok stwierdza: "Ta metoda powiadomienia zwrotnego jest wywoływana w przypadku, gdy kontener wykryje, że zdalne połączenie klienta powiązane z odpowiedzią asynchroniczną zostało odłączone.". Więc nawet jeśli zadzwoni onDisconnect po wypełnieniu żądania (co jest w porządku, jak sądzę), nie byłoby, gdyby pisano odpowiedź inną niż ciało. – James

+0

Myślę, że masz rację mówiąc, że będę potrzebował innego sposobu, aby o tym pomyśleć ... Naprawdę staram się obejść narzucone z zewnątrz ograniczenia, które powodują zły projekt interfejsu API! : S – James

Powiązane problemy