2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.fronius.internal.api;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.util.Properties;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.eclipse.jetty.http.HttpMethod;
22 import org.openhab.core.io.net.http.HttpUtil;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * A version of HttpUtil implementation that retries on failure.
29 * @author Jimmy Tanagra - Initial contribution
32 public class FroniusHttpUtil {
33 private static final Logger logger = LoggerFactory.getLogger(FroniusHttpUtil.class);
36 * Issue a HTTP request and retry on failure.
38 * @param httpMethod the HTTP method to use
39 * @param url the url to execute
40 * @param timeout the socket timeout in milliseconds to wait for data
41 * @return the response body
42 * @throws FroniusCommunicationException when the request execution failed or interrupted
44 public static synchronized String executeUrl(HttpMethod httpMethod, String url, int timeout)
45 throws FroniusCommunicationException {
46 return executeUrl(httpMethod, url, null, null, null, timeout);
50 * Issue a HTTP request and retry on failure.
52 * @param httpMethod the {@link HttpMethod} to use
53 * @param url the url to execute
54 * @param httpHeaders optional http request headers which has to be sent within request
55 * @param content the content to be sent to the given <code>url</code> or <code>null</code> if no content should be
57 * @param contentType the content type of the given <code>content</code>
58 * @param timeout the socket timeout in milliseconds to wait for data
59 * @return the response body
60 * @throws FroniusCommunicationException when the request execution failed or interrupted
62 public static synchronized String executeUrl(HttpMethod httpMethod, String url, @Nullable Properties httpHeaders,
63 @Nullable InputStream content, @Nullable String contentType, int timeout)
64 throws FroniusCommunicationException {
68 Throwable lastException = null;
71 result = HttpUtil.executeUrl(httpMethod.asString(), url, httpHeaders, content, contentType,
73 } catch (IOException e) {
74 // HttpUtil::executeUrl wraps InterruptedException into IOException.
75 // Unwrap and rethrow it so that we don't retry on InterruptedException
76 Throwable cause = e.getCause();
77 if (cause instanceof InterruptedException interruptException) {
78 throw interruptException;
84 if (attemptCount > 1) {
85 logger.debug("Attempt #{} successful {}", attemptCount, url);
90 if (attemptCount >= 3) {
91 logger.debug("Failed connecting to {} after {} attempts.", url, attemptCount, lastException);
92 throw new FroniusCommunicationException("Unable to connect", lastException);
95 logger.debug("HTTP error on attempt #{} {}", attemptCount, url);
96 Thread.sleep(500 * attemptCount);
99 } catch (InterruptedException e) {
100 Thread.currentThread().interrupt();
101 throw new FroniusCommunicationException("Interrupted", e);