Обнаружение прерывания HTTP в Java

Я делаю вызов REST для внешней системы с Java. Если есть какие-либо прерывания соединения, например, если внешняя система отключена, мне нужен прослушиватель, чтобы обнаружить это и выполнить соответствующие действия. Пожалуйста, дайте мне знать, смогу ли я достичь этого на Java. Предпочтительно в Java 8.

В настоящее время я не получаю никаких исключений, если попаду в такую ​​ситуацию. У меня есть код ниже

    Client client = ClientBuilder.newClient();
    WebTarget target = client.target(HOSTNAME);
    Invocation.Builder requestBuilder;

    requestBuilder = target.path(URL).request(MediaType.APPLICATION_JSON)
                                                .header(HEADER_AUTHORIZATION, AUTH_TOKEN);      
    Response response = null;
    if (HTTP_POST.equalsIgnoreCase(method)) {
        try{
        response = requestBuilder.post(Entity.entity(message, MediaType.APPLICATION_JSON_TYPE));
        }catch(Exception ex ){
            ex.printStackTrace();
        }
    } else if (HTTP_GET.equalsIgnoreCase(method)) {
        response = requestBuilder.get();
    } 

    String executeMessage = null;
    if(response != null){
        if (response.getStatus() == 200) {
            executeMessage = response.readEntity(String.class);         
            return new JSONObject(executeMessage);
        } else {
            executeMessage = response.readEntity(String.class);
            final JSONObject status = new JSONObject();
            status.put(STATUS_CODE, response.getStatus());
            status.put(STATUS_INFO, response.getStatusInfo());
            status.put("response", executeMessage);
            final JSONObject error = new JSONObject();
            error.put(ERROR, status);
            return error;
        }
    }

Ответы

Ответ 1

Если вы используете Spring Boot, вы можете попробовать декларативный клиент REST под названием Feign:

@FeignClient(url = "example.com", fallback = YourTestFeignClient.YourTestFeignClientFallback.class)
public interface YourTestFeignClient {

    @RequestMapping(method = RequestMethod.POST, value = "/example/path/to/resource/{id}")
    YourTestResponse requestExternalResource(@RequestParam("id") Long id, SomeRequestDTO requestDTO);

    @Component
    public static class YourTestFeignClientFallback implements YourTestFeignClient {

        @Override
        public YourTestResponse requestExternalResource(Long id, SomeRequestDTO requestDTO) {
            YourTestResponse testResponse = new YourTestResponse();
            testResponse.setMessage("Service unavailable");
            return testResponse;
        }

    }
}

Все, что вам нужно сделать, это ввести YourTestFeignClient в свой код и вызвать метод requestExternalResource на нем. Это вызовет POST example.com/example/path/to/resource/34 с телом JSON, взятым из SomeRequestDTO. В случае, если запрос не выполнен, возвращается метод возврата внутри YourTestFeignClientFallback, который затем возвращает некоторые данные по умолчанию.

Ответ 2

Вы можете создать свой собственный прослушиватель и сделать асинхронные вызовы Http с результатами, переданными обратно вызывающему классу, когда HTTP-ответ/ошибка будет готова. Например (с опечатками):

Создайте интерфейс, который будет реализован вашим основным классом, и ваш Http-клиент будет использовать...

public interface MyHttpListener {
  public httpComplete(MyHttpResults results);
}

Реализовать в своем основном классе.

public MyClass implements MyHttpListener {

  public void processHttpRequests(){
      for(int i=0; i<10; i++){
        // instantiate your Http Client class 
        HttpClient client = new HttpClient();

        // register the listener
        client.addHttpListener(this);

        // execute whatever URL you want and you are notified later when complete
        client.executeRequest("http://whatever");
     }
  }

  public httpRequestComplete(MyHttpResults results) {
    // do something with the results   
    results.getResponseCode();
    results.getRawResponse();
    results.whatever();
  }  

}

Добавить метод в ваш HttpClient для приема слушателей

public class MyHttpClient {
    List<MyHttpListener> httpListenerList = new ArrayList();   

   // register listeners
   public void addHttpListener(MyHttpListener listener){
     httpListenerList.add(listener);
   }   

   // this is the method that processes the request
   public void executeRequest(String url) {

     // do whatever you were doing previously here   

     // optional POJO to wrap the results and/or exceptions
     MyHttpResults results = new MyHttpResults();
     results.withResponseCode(response.getResponseCode());
     results.withResponse(responseAsString);
     results.withException(ex);
     results.withWhatever(whatever);

     // notify listeners
     notify(results);

   }

  public void notify(MyHttpResults results){
      // notify listeners
      for(MyHttpListener listener : httpListenerList){
         listener.httpComplete(results);
      }
  }


 }

Ответ 3

Если вы хотите постоянно проверять внешнюю службу REST, независимо от того, находится ли она в автономном режиме, вам нужно настроить какой-то периодический запрос ping. Любой ответ будет означать, что услуга находится в режиме онлайн. Отсутствие ответа в течение некоторого периода времени будет означать, что что-то не так.

Проблема, с которой вы сталкиваетесь, возникает из-за того, что метод java TCP Socket connect блокируется и время ожидания подключения по умолчанию java socket равно 0, что на самом деле бесконечно, как сказано в javadoc.

Таким образом, это означает, что вы не получите никакого ответа по умолчанию, если служба отключена.

Единственный правильный и простой вариант - установить тайм-аут. В вашем случае самым простым способом было бы использовать настройку свойств Jersey Client, например:

Client client = ClientBuilder.newClient();
// One second timeout may not be a really good choice unless your network is really fast
client.property(ClientProperties.CONNECT_TIMEOUT, 1000); 

И только в этом случае вы получите исключение, которое укажет, что служба REST, которую вы пытаетесь выполнить ping, не принимает соединения.

Установите тайм-аут с осторожностью в соответствии с реальными возможностями сети, в некоторых случаях это должно быть более 5 или даже 15 секунд (например, WiFi и GPRS-соединения).