import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
-import javax.ws.rs.client.ClientBuilder;
-
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpStatus;
import org.openhab.binding.neeo.internal.models.ExecuteResult;
import org.openhab.binding.neeo.internal.models.NeeoBrain;
/** The {@link HttpRequest} used for making requests */
private final AtomicReference<HttpRequest> request;
- /** The {@link ClientBuilder} to use */
- private final ClientBuilder clientBuilder;
+ private final HttpClient httpClient;
/** The IP address of the neeo brain */
private final NeeoUrlBuilder urlBuilder;
*
* @param ipAddress the non-empty ip address
*/
- public NeeoBrainApi(String ipAddress, ClientBuilder clientBuilder) {
+ public NeeoBrainApi(String ipAddress, HttpClient httpClient) {
NeeoUtil.requireNotEmpty(ipAddress, "ipAddress cannot be empty");
this.urlBuilder = new NeeoUrlBuilder(
NeeoConstants.PROTOCOL + ipAddress + ":" + NeeoConstants.DEFAULT_BRAIN_PORT);
- this.clientBuilder = clientBuilder;
+ this.httpClient = httpClient;
- request = new AtomicReference<>(new HttpRequest(clientBuilder));
+ request = new AtomicReference<>(new HttpRequest(httpClient));
}
/**
@Override
public void close() throws Exception {
- NeeoUtil.close(request.getAndSet(new HttpRequest(clientBuilder)));
+ NeeoUtil.close(request.getAndSet(new HttpRequest(httpClient)));
}
/**
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.servlet.ServletException;
-import javax.ws.rs.client.ClientBuilder;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.neeo.internal.NeeoBrainApi;
import org.openhab.binding.neeo.internal.NeeoBrainConfig;
import org.openhab.binding.neeo.internal.NeeoConstants;
/** The {@link NetworkAddressService} to use */
private final NetworkAddressService networkAddressService;
- /** The {@link ClientBuilder} to use */
- private final ClientBuilder clientBuilder;
+ private final HttpClient httpClient;
/** GSON implementation - only used to deserialize {@link NeeoAction} */
private final Gson gson = new Gson();
* @param networkAddressService the non-null {@link NetworkAddressService}
*/
NeeoBrainHandler(Bridge bridge, int servicePort, HttpService httpService,
- NetworkAddressService networkAddressService, ClientBuilder clientBuilder) {
+ NetworkAddressService networkAddressService, HttpClient httpClient) {
super(bridge);
Objects.requireNonNull(bridge, "bridge cannot be null");
this.servicePort = servicePort;
this.httpService = httpService;
this.networkAddressService = networkAddressService;
- this.clientBuilder = clientBuilder;
+ this.httpClient = httpClient;
}
/**
"Brain IP Address must be specified");
return;
}
- final NeeoBrainApi api = new NeeoBrainApi(ipAddress, clientBuilder);
+ final NeeoBrainApi api = new NeeoBrainApi(ipAddress, httpClient);
final NeeoBrain brain = api.getBrain();
final String brainId = getNeeoBrainId();
final NeeoAction action = Objects.requireNonNull(gson.fromJson(json, NeeoAction.class));
getThing().getThings().stream().map(Thing::getHandler).filter(NeeoRoomHandler.class::isInstance)
.forEach(h -> ((NeeoRoomHandler) h).processAction(action));
- }, config.getForwardChain(), clientBuilder);
+ }, config.getForwardChain(), httpClient);
NeeoUtil.checkInterrupt();
try {
- servletPath = NeeoConstants.WEBAPP_FORWARDACTIONS.replace("{brainid}", brainId);
+ String servletPath = NeeoConstants.WEBAPP_FORWARDACTIONS.replace("{brainid}", brainId);
+ this.servletPath = servletPath;
- httpService.registerServlet(servletPath, forwardActionServlet, new Hashtable<>(),
+ Hashtable<Object, Object> initParams = new Hashtable<>();
+ initParams.put("servlet-name", servletPath);
+
+ httpService.registerServlet(servletPath, forwardActionServlet, initParams,
httpService.createDefaultHttpContext());
final URL callbackURL = createCallbackUrl(brainId, config);
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.client.ClientBuilder;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpStatus;
import org.openhab.binding.neeo.internal.net.HttpRequest;
import org.openhab.binding.neeo.internal.net.HttpResponse;
/** The forwarding chain */
private final @Nullable String forwardChain;
- /** The {@link ClientBuilder} to use */
- private final ClientBuilder clientBuilder;
+ private final HttpClient httpClient;
/** The scheduler to use to schedule recipe execution */
private final ScheduledExecutorService scheduler;
* @param forwardChain a possibly null, possibly empty forwarding chain
*/
NeeoForwardActionsServlet(ScheduledExecutorService scheduler, Consumer<String> callback,
- @Nullable String forwardChain, ClientBuilder clientBuilder) {
+ @Nullable String forwardChain, HttpClient httpClient) {
super();
this.scheduler = scheduler;
this.callback = callback;
this.forwardChain = forwardChain;
- this.clientBuilder = clientBuilder;
+ this.httpClient = httpClient;
}
/**
callback.accept(json);
+ String forwardChain = this.forwardChain;
if (forwardChain != null && !forwardChain.isEmpty()) {
scheduler.execute(() -> {
- try (final HttpRequest request = new HttpRequest(clientBuilder)) {
+ try (final HttpRequest request = new HttpRequest(httpClient)) {
for (final String forwardUrl : forwardChain.split(",")) {
if (!forwardUrl.isEmpty()) {
final HttpResponse httpResponse = request.sendPostJsonCommand(forwardUrl, json);
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import javax.ws.rs.client.ClientBuilder;
-
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.neeo.internal.NeeoConstants;
import org.openhab.binding.neeo.internal.discovery.NeeoDeviceDiscoveryService;
import org.openhab.binding.neeo.internal.discovery.NeeoRoomDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryService;
+import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.net.HttpServiceUtil;
import org.openhab.core.net.NetworkAddressService;
import org.openhab.core.thing.Bridge;
/** The {@link NetworkAddressService} used for ip lookup */
private final NetworkAddressService networkAddressService;
- /** The {@link ClientBuilder} used in HttpRequest */
- private final ClientBuilder clientBuilder;
+ private final HttpClient httpClient;
/** The discovery services created by this class (one per room and one for each device) */
private final ConcurrentMap<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new ConcurrentHashMap<>();
@Activate
public NeeoHandlerFactory(@Reference HttpService httpService,
- @Reference NetworkAddressService networkAddressService, @Reference ClientBuilder clientBuilder) {
+ @Reference NetworkAddressService networkAddressService, @Reference HttpClientFactory httpClientFactory) {
this.httpService = httpService;
this.networkAddressService = networkAddressService;
- this.clientBuilder = clientBuilder;
+ this.httpClient = httpClientFactory.getCommonHttpClient();
}
@Override
final int port = HttpServiceUtil.getHttpServicePort(this.bundleContext);
final NeeoBrainHandler handler = new NeeoBrainHandler((Bridge) thing,
port < 0 ? NeeoConstants.DEFAULT_BRAIN_HTTP_PORT : port, httpService, networkAddressService,
- clientBuilder);
+ httpClient);
registerRoomDiscoveryService(handler);
return handler;
} else if (thingTypeUID.equals(NeeoConstants.BRIDGE_TYPE_ROOM)) {
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.Invocation.Builder;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.util.StringContentProvider;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
-import org.glassfish.jersey.filter.LoggingFilter;
import org.openhab.binding.neeo.internal.NeeoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final Logger logger = LoggerFactory.getLogger(HttpRequest.class);
/** The client to use */
- private final Client client;
+ private final HttpClient httpClient;
/**
* Instantiates a new request
*/
- public HttpRequest(ClientBuilder clientBuilder) {
- client = clientBuilder.build();
-
- if (logger.isDebugEnabled()) {
- client.register(new LoggingFilter(new Slf4LoggingAdapter(logger), true));
- }
+ public HttpRequest(HttpClient httpClient) {
+ this.httpClient = httpClient;
}
/**
public HttpResponse sendGetCommand(String uri) {
NeeoUtil.requireNotEmpty(uri, "uri cannot be empty");
try {
- final Builder request = client.target(uri).request();
-
- final Response content = request.get();
-
- try {
- return new HttpResponse(content);
- } finally {
- content.close();
- }
+ final org.eclipse.jetty.client.api.Request request = httpClient.newRequest(uri);
+ request.method(HttpMethod.GET);
+ request.timeout(10, TimeUnit.SECONDS);
+ ContentResponse refreshResponse = request.send();
+ return new HttpResponse(refreshResponse);
} catch (IOException | IllegalStateException e) {
return new HttpResponse(HttpStatus.SERVICE_UNAVAILABLE_503, e.getMessage());
+ } catch (InterruptedException | TimeoutException | ExecutionException e) {
+ logger.debug("An exception occurred while invoking a HTTP request: '{}'", e.getMessage());
+ String message = e.getMessage();
+ return new HttpResponse(HttpStatus.SERVICE_UNAVAILABLE_503, message != null ? message : "");
}
}
logger.warn("Absolute URI required but provided URI '{}' is non-absolute. ", uriString);
return new HttpResponse(HttpStatus.NOT_ACCEPTABLE_406, "Absolute URI required");
}
- final Builder request = client.target(targetUri).request(MediaType.APPLICATION_JSON);
-
- final Response content = request.post(Entity.entity(body, MediaType.APPLICATION_JSON));
-
- try {
- return new HttpResponse(content);
- } finally {
- content.close();
- }
+ final org.eclipse.jetty.client.api.Request request = httpClient.newRequest(targetUri);
+ request.content(new StringContentProvider(body));
+ request.header(HttpHeader.CONTENT_TYPE, "application/json");
+ request.method(HttpMethod.POST);
+ request.timeout(10, TimeUnit.SECONDS);
+ ContentResponse refreshResponse = request.send();
+ return new HttpResponse(refreshResponse);
// IllegalArgumentException/ProcessingException catches issues with the URI being invalid
// as well
} catch (IOException | IllegalStateException | IllegalArgumentException | ProcessingException e) {
return new HttpResponse(HttpStatus.SERVICE_UNAVAILABLE_503, e.getMessage());
} catch (URISyntaxException e) {
return new HttpResponse(HttpStatus.NOT_ACCEPTABLE_406, e.getMessage());
+ } catch (InterruptedException | TimeoutException | ExecutionException e) {
+ logger.debug("An exception occurred while invoking a HTTP request: '{}'", e.getMessage());
+ String message = e.getMessage();
+ return new HttpResponse(HttpStatus.SERVICE_UNAVAILABLE_503, message != null ? message : "");
}
}
@Override
public void close() {
- client.close();
}
}
package org.openhab.binding.neeo.internal.net;
import java.io.IOException;
-import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.api.ContentResponse;
/**
* This class represents an {@link HttpRequest} response
/**
* Instantiates a new http response from the {@link Response}.
*
- * @param response the non-null response
+ * @param refreshResponse the non-null response
* @throws IOException Signals that an I/O exception has occurred.
*/
- HttpResponse(Response response) throws IOException {
- Objects.requireNonNull(response, "response cannot be null");
+ HttpResponse(ContentResponse refreshResponse) throws IOException {
+ Objects.requireNonNull(refreshResponse, "response cannot be null");
- httpStatus = response.getStatus();
- httpReason = response.getStatusInfo().getReasonPhrase();
+ httpStatus = refreshResponse.getStatus();
+ httpReason = refreshResponse.getReason();
+ contents = refreshResponse.getContent();
- if (response.hasEntity()) {
- InputStream is = response.readEntity(InputStream.class);
- contents = is.readAllBytes();
- } else {
- contents = null;
- }
-
- for (String key : response.getHeaders().keySet()) {
- headers.put(key, response.getHeaderString(key));
+ for (String key : refreshResponse.getHeaders().getFieldNamesCollection()) {
+ headers.put(key, refreshResponse.getHeaders().getField(key).toString());
}
}
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.ServletException;
-import javax.ws.rs.client.ClientBuilder;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
import org.openhab.core.addon.AddonInfoRegistry;
import org.openhab.core.config.core.ConfigurableService;
import org.openhab.core.events.Event;
import org.openhab.core.events.EventFilter;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.events.EventSubscriber;
+import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.io.transport.mdns.MDNSClient;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.items.events.ItemStateChangedEvent;
private final MDNSClient mdnsClient;
private final EventPublisher eventPublisher;
private final NetworkAddressService networkAddressService;
- private final ClientBuilder clientBuilder;
+ private final HttpClientFactory httpClientFactory;
+ private final HttpClient httpClient;
/** The main dashboard servlet. Only created in the activate method (and disposed of in the deactivate method) */
private @Nullable NeeoDashboardServlet dashboardServlet;
@Reference AddonInfoRegistry addonInfoRegistry, @Reference ChannelTypeRegistry channelTypeRegistry,
@Reference ThingTypeRegistry thingTypeRegistry, @Reference ItemChannelLinkRegistry itemChannelLinkRegistry,
@Reference MDNSClient mdnsClient, @Reference EventPublisher eventPublisher,
- @Reference NetworkAddressService networkAddressService, @Reference ClientBuilder clientBuilder) {
+ @Reference NetworkAddressService networkAddressService, @Reference HttpClientFactory httpClientFactory) {
this.httpService = httpService;
this.itemRegistry = itemRegistry;
this.bindingInfoRegistry = addonInfoRegistry;
this.mdnsClient = mdnsClient;
this.eventPublisher = eventPublisher;
this.networkAddressService = networkAddressService;
- this.clientBuilder = clientBuilder;
+ this.httpClientFactory = httpClientFactory;
+ this.httpClient = httpClientFactory.getCommonHttpClient();
logger.debug("Neeo Service activated");
final ServiceContext localContext = new ServiceContext(componentContext, validate(httpService, "httpService"),
validate(eventPublisher, "eventPublisher"), validate(networkAddressService, "networkAddressService"));
context = localContext;
- discovery = new MdnsBrainDiscovery(localContext, clientBuilder);
+ discovery = new MdnsBrainDiscovery(localContext, httpClient);
discovery.addListener(discoveryListener);
try {
servletUrl);
try {
final NeeoBrainServlet newServlet = NeeoBrainServlet.create(localContext, servletUrl,
- sysInfo.getHostname(), ipAddress, clientBuilder);
+ sysInfo.getHostname(), ipAddress, httpClient, httpClientFactory);
servlets.add(newServlet);
Hashtable<Object, Object> initParams = new Hashtable<>();
import java.net.URL;
import java.util.Map;
import java.util.Objects;
+import java.util.Stack;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
-import javax.ws.rs.client.ClientBuilder;
-
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpStatus;
import org.openhab.core.common.ThreadPoolManager;
import org.openhab.core.id.InstanceUUID;
+import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.net.HttpServiceUtil;
import org.openhab.io.neeo.internal.models.NeeoAdapterRegistration;
import org.openhab.io.neeo.internal.models.NeeoRecipe;
/** The brain's IP address */
private final String brainIpAddress;
- private final ClientBuilder clientBuilder;
+ private final HttpClient httpClient;
+
+ private final HttpClientFactory httpClientFactory;
+
+ private Stack httpClientStack = new Stack<HttpClient>();
+
+ private int httpClientId = 0;
/** The URL of the brain */
private final String brainUrl;
* @param context the non-null {@link ServiceContext}
* @throws IOException if an exception occurs connecting to the brain
*/
- public NeeoApi(String ipAddress, String brainId, ServiceContext context, ClientBuilder clientBuilder)
- throws IOException {
+ public NeeoApi(String ipAddress, String brainId, ServiceContext context, HttpClient httpClient,
+ HttpClientFactory httpClientFactory) throws IOException {
NeeoUtil.requireNotEmpty(ipAddress, "ipAddress cannot be empty");
NeeoUtil.requireNotEmpty(brainId, "brainId cannot be empty");
Objects.requireNonNull(context, "context cannot be null");
this.brainIpAddress = ipAddress;
this.brainId = brainId;
- this.clientBuilder = clientBuilder;
+ this.httpClient = httpClient;
+ this.httpClientFactory = httpClientFactory;
this.brainUrl = NeeoConstants.PROTOCOL + (ipAddress.startsWith("/") ? ipAddress.substring(1) : ipAddress) + ":"
+ NeeoConstants.DEFAULT_BRAIN_PORT;
- deviceKeys = new NeeoDeviceKeys(brainUrl, clientBuilder);
+ deviceKeys = new NeeoDeviceKeys(brainUrl, httpClient);
- request = new AtomicReference<>(new HttpRequest(clientBuilder));
+ request = new AtomicReference<>(new HttpRequest(httpClient));
- this.systemInfo = getSystemInfo(ipAddress, clientBuilder);
+ this.systemInfo = getSystemInfo(ipAddress, httpClient);
String name = brainId;
- try (HttpRequest request = new HttpRequest(clientBuilder)) {
+ try (HttpRequest request = new HttpRequest(httpClient)) {
logger.debug("Getting existing device mappings from {}{}", brainUrl, NeeoConstants.PROJECTS_HOME);
final HttpResponse resp = request.sendGetCommand(brainUrl + NeeoConstants.PROJECTS_HOME);
if (resp.getHttpCode() != HttpStatus.OK_200) {
* @return the non-null {@link NeeoSystemInfo} for the address
* @throws IOException Signals that an I/O exception has occurred or the URL is not a brain
*/
- public static NeeoSystemInfo getSystemInfo(String ipAddress, ClientBuilder clientBuilder) throws IOException {
+ public static NeeoSystemInfo getSystemInfo(String ipAddress, HttpClient httpClient) throws IOException {
NeeoUtil.requireNotEmpty(ipAddress, "ipAddress cannot be empty");
final String sysInfo = NeeoConstants.PROTOCOL + (ipAddress.startsWith("/") ? ipAddress.substring(1) : ipAddress)
+ ":" + NeeoConstants.DEFAULT_BRAIN_PORT + NeeoConstants.SYSTEMINFO;
- try (HttpRequest req = new HttpRequest(clientBuilder)) {
+ try (HttpRequest req = new HttpRequest(httpClient)) {
final HttpResponse res = req.sendGetCommand(sysInfo);
if (res.getHttpCode() == HttpStatus.OK_200) {
return Objects.requireNonNull(GSON.fromJson(res.getContent(), NeeoSystemInfo.class));
try {
setConnected(false);
- NeeoUtil.close(request.getAndSet(new HttpRequest(clientBuilder)));
+ NeeoUtil.close(request.getAndSet(new HttpRequest(httpClient)));
NeeoUtil.checkInterrupt();
registerApi();
return deviceKeys;
}
+ private synchronized HttpClient getHttpClient() {
+ int stackSize = httpClientStack.size();
+ if (stackSize == 0) {
+ int httpClientId = this.httpClientId + 1;
+ this.httpClientId = httpClientId;
+ String httpClientIdString = "neeo-" + brainId + "-" + httpClientId;
+ logger.debug("getHttpClient created new client {} for brain {}", httpClientIdString, brainId);
+ HttpClient httpClient = httpClientFactory.createHttpClient(httpClientIdString);
+ try {
+ httpClient.start();
+ } catch (Exception e) {
+ logger.debug("Exception while starting HttpClient: {}", e.getMessage(), e);
+ }
+ return httpClient;
+ } else {
+ logger.debug("getHttpClient popped a client from the stack for brain {} depth {}", brainId, stackSize);
+ return (HttpClient) httpClientStack.pop();
+ }
+ }
+
+ private synchronized void returnHttpClient(HttpClient httpClient) {
+ int stackSize = httpClientStack.size();
+ if (stackSize <= NeeoConstants.HTTPCLIENT_POOL_SIZE) {
+ logger.debug("getHttpClient returned a client for brain {} depth {}", brainId, stackSize);
+ httpClientStack.push(httpClient);
+ } else {
+ try {
+ logger.debug("getHttpClient destroyed a client for brain {}", brainId);
+ httpClient.stop();
+ } catch (Exception e) {
+ logger.debug("Exception while stopping HttpClient: {}", e.getMessage(), e);
+ }
+ }
+ }
+
/**
* Send a notification to the brain
*
*/
public void notify(String msg) throws IOException {
if (isConnected()) {
- final HttpRequest rqst = request.get();
+ HttpClient httpClient = getHttpClient();
+ final HttpRequest rqst = new HttpRequest(httpClient);
logger.debug("Sending Notification to brain ({}): {}", brainId, msg);
final HttpResponse resp = rqst.sendPostJsonCommand(brainUrl + NeeoConstants.NOTIFICATION, msg);
if (resp.getHttpCode() != HttpStatus.OK_200) {
+ returnHttpClient(httpClient);
throw resp.createException();
+ } else {
+ logger.debug("Response from brain ({}): {} - {}", brainId, resp.getHttpCode(), resp.getContent());
}
+ returnHttpClient(httpClient);
} else {
logger.debug("Notification ignored - brain not connected");
}
NeeoUtil.cancel(connect.getAndSet(null));
try {
+ int stackSize = httpClientStack.size();
+ while (stackSize > 0) {
+ HttpClient httpClient = (HttpClient) httpClientStack.pop();
+ httpClient.stop();
+ httpClient = null;
+ stackSize--;
+ }
deregisterApi();
- } catch (IOException e) {
+ } catch (Exception e) {
logger.debug("Exception while deregistring api during close - ignoring: {}", e.getMessage(), e);
} finally {
// Do this regardless if a runtime exception was thrown
import java.net.InetAddress;
import java.util.Objects;
-import javax.ws.rs.client.ClientBuilder;
-
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jetty.client.HttpClient;
+import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.io.neeo.internal.models.BrainStatus;
import org.openhab.io.neeo.internal.servletservices.NeeoBrainSearchService;
import org.openhab.io.neeo.internal.servletservices.NeeoBrainService;
* @param servletUrl the non-null, non-empty servlet URL
* @param api the non-null API
*/
- private NeeoBrainServlet(ServiceContext context, String servletUrl, NeeoApi api, ClientBuilder clientBuilder) {
- super(context, servletUrl, new NeeoBrainSearchService(context),
- new NeeoBrainService(api, context, clientBuilder));
+ private NeeoBrainServlet(ServiceContext context, String servletUrl, NeeoApi api, HttpClient httpClient,
+ HttpClientFactory httpClientFactory) {
+ super(context, servletUrl, new NeeoBrainSearchService(context), new NeeoBrainService(api, context, httpClient));
Objects.requireNonNull(context, "context cannot be null");
NeeoUtil.requireNotEmpty(servletUrl, "servletUrl cannot be empty");
* @throws IOException when an exception occurs contacting the brain
*/
public static NeeoBrainServlet create(ServiceContext context, String servletUrl, String brainId,
- InetAddress ipAddress, ClientBuilder clientBuilder) throws IOException {
+ InetAddress ipAddress, HttpClient httpClient, HttpClientFactory httpClientFactory) throws IOException {
Objects.requireNonNull(context, "context cannot be null");
NeeoUtil.requireNotEmpty(servletUrl, "servletUrl cannot be empty");
NeeoUtil.requireNotEmpty(brainId, "brainId cannot be empty");
Objects.requireNonNull(ipAddress, "ipAddress cannot be null");
- final NeeoApi api = new NeeoApi(ipAddress.getHostAddress(), brainId, context, clientBuilder);
+ final NeeoApi api = new NeeoApi(ipAddress.getHostAddress(), brainId, context, httpClient, httpClientFactory);
api.start();
- return new NeeoBrainServlet(context, servletUrl, api, clientBuilder);
+ return new NeeoBrainServlet(context, servletUrl, api, httpClient, httpClientFactory);
}
/**
/** Constant used to identify thread pool name */
public static final String THREAD_POOL_NAME = "neeoio";
+ public static final int HTTPCLIENT_POOL_SIZE = 5;
/** Constants used for the Web APP */
public static final String WEBAPP_PREFIX = "/neeo";
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
-import javax.ws.rs.client.ClientBuilder;
-
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpStatus;
import org.openhab.core.thing.ThingUID;
import org.openhab.io.neeo.internal.models.NeeoThingUID;
/** The brain's url */
private final String brainUrl;
- private final ClientBuilder clientBuilder;
+ private final HttpClient httpClient;
/**
* Creates the object from the context and brainUrl
*
* @param brainUrl the non-empty brain url
*/
- NeeoDeviceKeys(String brainUrl, ClientBuilder clientBuilder) {
+ NeeoDeviceKeys(String brainUrl, HttpClient httpClient) {
NeeoUtil.requireNotEmpty(brainUrl, "brainUrl cannot be empty");
this.brainUrl = brainUrl;
- this.clientBuilder = clientBuilder;
+ this.httpClient = httpClient;
}
/**
* @throws IOException Signals that an I/O exception has occurred.
*/
void refresh() throws IOException {
- try (HttpRequest request = new HttpRequest(clientBuilder)) {
+ try (HttpRequest request = new HttpRequest(httpClient)) {
logger.debug("Getting existing device mappings from {}{}", brainUrl, NeeoConstants.PROJECTS_HOME);
final HttpResponse resp = request.sendGetCommand(brainUrl + NeeoConstants.PROJECTS_HOME);
if (resp.getHttpCode() != HttpStatus.OK_200) {
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;
-import javax.ws.rs.client.ClientBuilder;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
import org.openhab.core.common.ThreadPoolManager;
import org.openhab.core.io.transport.mdns.MDNSClient;
import org.openhab.io.neeo.internal.NeeoApi;
/** The file we store definitions in */
private final File file = new File(NeeoConstants.FILENAME_DISCOVEREDBRAINS);
- private final ClientBuilder clientBuilder;
+ private final HttpClient httpClient;
/**
* Creates the MDNS brain discovery from the given {@link ServiceContext}
*
* @param context the non-null service context
*/
- public MdnsBrainDiscovery(ServiceContext context, ClientBuilder clientBuilder) {
+ public MdnsBrainDiscovery(ServiceContext context, HttpClient httpClient) {
Objects.requireNonNull(context, "context cannot be null");
this.context = context;
- this.clientBuilder = clientBuilder;
+ this.httpClient = httpClient;
}
/**
NeeoSystemInfo sysInfo;
try {
- sysInfo = NeeoApi.getSystemInfo(brainInfo.getValue().toString(), clientBuilder);
+ sysInfo = NeeoApi.getSystemInfo(brainInfo.getValue().toString(), httpClient);
} catch (IOException e) {
// We can get an MDNS notification BEFORE the brain is ready to process.
// if that happens, we'll get an IOException (usually bad gateway message), schedule another attempt to get
try {
final InetAddress addr = InetAddress.getByName(ipAddress);
- final NeeoSystemInfo sysInfo = NeeoApi.getSystemInfo(ipAddress, clientBuilder);
+ final NeeoSystemInfo sysInfo = NeeoApi.getSystemInfo(ipAddress, httpClient);
logger.debug("Manually adding brain ({}) with system information: {}", ipAddress, sysInfo);
systemsLock.lock();
import java.io.IOException;
import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.Invocation.Builder;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.util.StringContentProvider;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
-import org.glassfish.jersey.filter.LoggingFilter;
import org.openhab.io.neeo.internal.NeeoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * This class represents an HTTP session with a client
+ * This class represents an HTTP session with a httpClient
*
* @author Tim Roberts - Initial Contribution
*/
/** the logger */
private final Logger logger = LoggerFactory.getLogger(HttpRequest.class);
- /** The client to use */
- private final Client client;
+ /** The httpClient to use */
+ private final HttpClient httpClient;
/**
* Instantiates a new request
*/
- public HttpRequest(ClientBuilder clientBuilder) {
- client = clientBuilder.build();
-
- if (logger.isDebugEnabled()) {
- client.register(new LoggingFilter(new Slf4LoggingAdapter(logger), true));
- }
+ public HttpRequest(HttpClient httpClient) {
+ this.httpClient = httpClient;
}
/**
public HttpResponse sendGetCommand(String uri) {
NeeoUtil.requireNotEmpty(uri, "uri cannot be empty");
try {
- final Builder request = client.target(uri).request();
-
- final Response content = request.get();
-
- try {
- return new HttpResponse(content);
- } finally {
- content.close();
- }
+ final org.eclipse.jetty.client.api.Request request = httpClient.newRequest(uri);
+ request.method(HttpMethod.GET);
+ request.timeout(10, TimeUnit.SECONDS);
+ ContentResponse refreshResponse = request.send();
+ return new HttpResponse(refreshResponse);
} catch (IOException | IllegalStateException | ProcessingException e) {
String message = e.getMessage();
return new HttpResponse(HttpStatus.SERVICE_UNAVAILABLE_503, message != null ? message : "");
+ } catch (InterruptedException | TimeoutException | ExecutionException e) {
+ logger.debug("An exception occurred while invoking a HTTP request: '{}'", e.getMessage());
+ String message = e.getMessage();
+ return new HttpResponse(HttpStatus.SERVICE_UNAVAILABLE_503, message != null ? message : "");
}
}
Objects.requireNonNull(body, "body cannot be null");
try {
- final Builder request = client.target(uri).request(MediaType.APPLICATION_JSON);
-
- final Response content = request.post(Entity.entity(body, MediaType.APPLICATION_JSON));
-
- try {
- return new HttpResponse(content);
- } finally {
- content.close();
- }
+ final org.eclipse.jetty.client.api.Request request = httpClient.newRequest(uri);
+ request.content(new StringContentProvider(body));
+ request.header(HttpHeader.CONTENT_TYPE, "application/json");
+ request.method(HttpMethod.POST);
+ request.timeout(10, TimeUnit.SECONDS);
+ ContentResponse refreshResponse = request.send();
+ return new HttpResponse(refreshResponse);
} catch (IOException | IllegalStateException | ProcessingException e) {
String message = e.getMessage();
return new HttpResponse(HttpStatus.SERVICE_UNAVAILABLE_503, message != null ? message : "");
+ } catch (InterruptedException | TimeoutException | ExecutionException e) {
+ logger.debug("An exception occurred while invoking a HTTP request: '{}'", e.getMessage());
+ String message = e.getMessage();
+ return new HttpResponse(HttpStatus.SERVICE_UNAVAILABLE_503, message != null ? message : "");
}
}
@Override
public void close() {
- client.close();
}
}
package org.openhab.io.neeo.internal.net;
import java.io.IOException;
-import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.api.ContentResponse;
/**
* This class represents an {@link HttpRequest} response
* @param response the non-null response
* @throws IOException Signals that an I/O exception has occurred.
*/
- HttpResponse(Response response) throws IOException {
+ HttpResponse(ContentResponse response) throws IOException {
Objects.requireNonNull(response, "response cannot be null");
httpStatus = response.getStatus();
- httpReason = response.getStatusInfo().getReasonPhrase();
+ httpReason = response.getReason();
+ contents = response.getContent();
- if (response.hasEntity()) {
- contents = response.readEntity(InputStream.class).readAllBytes();
- } else {
- contents = null;
- }
-
- for (String key : response.getHeaders().keySet()) {
- headers.put(key, response.getHeaderString(key));
+ for (String key : response.getHeaders().getFieldNamesCollection()) {
+ headers.put(key, response.getHeaders().getField(key).toString());
}
}
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.client.ClientBuilder;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
import org.openhab.core.common.ThreadPoolManager;
import org.openhab.core.events.Event;
import org.openhab.core.events.EventFilter;
* @param api the non-null api
* @param context the non-null context
*/
- public NeeoBrainService(NeeoApi api, ServiceContext context, ClientBuilder clientBuilder) {
+ public NeeoBrainService(NeeoApi api, ServiceContext context, HttpClient httpClient) {
Objects.requireNonNull(api, "api cannot be null");
Objects.requireNonNull(context, "context cannot be null");
scheduler.execute(() -> {
resendState();
});
- request = new HttpRequest(clientBuilder);
+ request = new HttpRequest(httpClient);
}
/**