]> git.basschouten.com Git - openhab-addons.git/commitdiff
[robonect] Fix `NullPointerException` on reinitialization (#15003)
authorJacob Laursen <jacob-github@vindvejr.dk>
Sun, 18 Jun 2023 07:06:19 +0000 (09:06 +0200)
committerGitHub <noreply@github.com>
Sun, 18 Jun 2023 07:06:19 +0000 (09:06 +0200)
* Fix NullPointerException on reinitialization

Fixes #15001

bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectBindingConstants.java
bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectHandlerFactory.java
bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/handler/RobonectHandler.java
bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/handler/RobonectHandlerTest.java

index 13e808321261d75728ffb6ffdb6c1152df84ac4a..0334f1bcf5d45aba41ade594f39461d1b2d3fde8 100644 (file)
@@ -22,7 +22,7 @@ import org.openhab.core.thing.ThingTypeUID;
  */
 public class RobonectBindingConstants {
 
-    private static final String BINDING_ID = "robonect";
+    public static final String BINDING_ID = "robonect";
 
     // List of all Thing Type UIDs
     public static final ThingTypeUID THING_TYPE_AUTOMOWER = new ThingTypeUID(BINDING_ID, "mower");
index ad0780032192a8fc15eb45d5c05847b13f04045f..525afb547f787ec95aedf1e89a223547ad4317fc 100644 (file)
  */
 package org.openhab.binding.robonect.internal;
 
-import static org.openhab.binding.robonect.internal.RobonectBindingConstants.THING_TYPE_AUTOMOWER;
+import static org.openhab.binding.robonect.internal.RobonectBindingConstants.*;
 
-import java.util.Collections;
 import java.util.Set;
 
-import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.robonect.internal.handler.RobonectHandler;
 import org.openhab.core.i18n.TimeZoneProvider;
 import org.openhab.core.io.net.http.HttpClientFactory;
@@ -36,18 +36,19 @@ import org.osgi.service.component.annotations.Reference;
  *
  * @author Marco Meyer - Initial contribution
  */
+@NonNullByDefault
 @Component(service = ThingHandlerFactory.class, configurationPid = "binding.robonect")
 public class RobonectHandlerFactory extends BaseThingHandlerFactory {
 
-    private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_AUTOMOWER);
+    private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_AUTOMOWER);
 
-    private HttpClient httpClient;
+    private HttpClientFactory httpClientFactory;
     private TimeZoneProvider timeZoneProvider;
 
     @Activate
     public RobonectHandlerFactory(@Reference HttpClientFactory httpClientFactory,
             @Reference TimeZoneProvider timeZoneProvider) {
-        this.httpClient = httpClientFactory.getCommonHttpClient();
+        this.httpClientFactory = httpClientFactory;
         this.timeZoneProvider = timeZoneProvider;
     }
 
@@ -57,11 +58,11 @@ public class RobonectHandlerFactory extends BaseThingHandlerFactory {
     }
 
     @Override
-    protected ThingHandler createHandler(Thing thing) {
+    protected @Nullable ThingHandler createHandler(Thing thing) {
         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
 
         if (thingTypeUID.equals(THING_TYPE_AUTOMOWER)) {
-            return new RobonectHandler(thing, httpClient, timeZoneProvider);
+            return new RobonectHandler(thing, httpClientFactory, timeZoneProvider);
         }
 
         return null;
index 35ca401dc5df634a1ff04492d7bc30cb07239bc6..ebf18a9d4bde08d801cedd793e01e45a1bc88ff9 100644 (file)
@@ -38,6 +38,7 @@ import org.openhab.binding.robonect.internal.model.RobonectAnswer;
 import org.openhab.binding.robonect.internal.model.VersionInfo;
 import org.openhab.binding.robonect.internal.model.cmd.ModeCommand;
 import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.core.io.net.http.HttpClientFactory;
 import org.openhab.core.library.types.DateTimeType;
 import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.library.types.OnOffType;
@@ -50,6 +51,7 @@ import org.openhab.core.thing.Thing;
 import org.openhab.core.thing.ThingStatus;
 import org.openhab.core.thing.ThingStatusDetail;
 import org.openhab.core.thing.binding.BaseThingHandler;
+import org.openhab.core.thing.util.ThingWebClientUtil;
 import org.openhab.core.types.Command;
 import org.openhab.core.types.RefreshType;
 import org.openhab.core.types.State;
@@ -80,9 +82,10 @@ public class RobonectHandler extends BaseThingHandler {
 
     private RobonectClient robonectClient;
 
-    public RobonectHandler(Thing thing, HttpClient httpClient, TimeZoneProvider timeZoneProvider) {
+    public RobonectHandler(Thing thing, HttpClientFactory httpClientFactory, TimeZoneProvider timeZoneProvider) {
         super(thing);
-        this.httpClient = httpClient;
+        httpClient = httpClientFactory
+                .createHttpClient(ThingWebClientUtil.buildWebClientConsumerName(thing.getUID(), null));
         this.timeZoneProvider = timeZoneProvider;
     }
 
@@ -243,7 +246,7 @@ public class RobonectHandler extends BaseThingHandler {
             if (info.getHealth() != null) {
                 updateState(CHANNEL_HEALTH_TEMP,
                         new QuantityType<>(info.getHealth().getTemperature(), SIUnits.CELSIUS));
-                updateState(CHANNEL_HEALTH_HUM, new QuantityType(info.getHealth().getHumidity(), Units.PERCENT));
+                updateState(CHANNEL_HEALTH_HUM, new QuantityType<>(info.getHealth().getHumidity(), Units.PERCENT));
             }
             if (info.getTimer() != null) {
                 if (info.getTimer().getNext() != null) {
@@ -364,11 +367,12 @@ public class RobonectHandler extends BaseThingHandler {
 
         try {
             httpClient.start();
-            robonectClient = new RobonectClient(httpClient, endpoint);
         } catch (Exception e) {
-            logger.error("Exception while trying to start http client", e);
-            throw new RuntimeException("Exception while trying to start http client", e);
+            logger.error("Exception while trying to start HTTP client", e);
+            throw new IllegalStateException("Could not create HttpClient");
         }
+
+        robonectClient = new RobonectClient(httpClient, endpoint);
         Runnable runnable = new MowerChannelPoller(TimeUnit.SECONDS.toMillis(robonectConfig.getOfflineTimeout()));
         int pollInterval = robonectConfig.getPollInterval();
         pollingJob = scheduler.scheduleWithFixedDelay(runnable, 0, pollInterval, TimeUnit.SECONDS);
@@ -376,12 +380,17 @@ public class RobonectHandler extends BaseThingHandler {
 
     @Override
     public void dispose() {
+        ScheduledFuture<?> pollingJob = this.pollingJob;
         if (pollingJob != null) {
             pollingJob.cancel(true);
-            pollingJob = null;
+            this.pollingJob = null;
         }
 
-        httpClient = null;
+        try {
+            httpClient.stop();
+        } catch (Exception e) {
+            logger.warn("Exception while trying to stop HTTP client", e);
+        }
     }
 
     /**
index 58c6e9c34d9897aa1a0efd1be2c4e289ba222440..8f29c4f6cf4f4addce0a05c9c36cd2e236a7387d 100644 (file)
@@ -20,7 +20,6 @@ import java.time.Month;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 
-import org.eclipse.jetty.client.HttpClient;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -42,6 +41,7 @@ import org.openhab.binding.robonect.internal.model.Status;
 import org.openhab.binding.robonect.internal.model.Timer;
 import org.openhab.binding.robonect.internal.model.Wlan;
 import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.core.io.net.http.HttpClientFactory;
 import org.openhab.core.library.types.DateTimeType;
 import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.library.types.OnOffType;
@@ -69,16 +69,17 @@ public class RobonectHandlerTest {
     private @Mock Thing robonectThingMock;
     private @Mock RobonectClient robonectClientMock;
     private @Mock ThingHandlerCallback callbackMock;
-    private @Mock HttpClient httpClientMock;
+    private @Mock HttpClientFactory httpClientFactoryMock;
     private @Mock TimeZoneProvider timezoneProvider;
 
     @BeforeEach
     public void setUp() {
-        subject = new RobonectHandler(robonectThingMock, httpClientMock, timezoneProvider);
+        Mockito.when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
+        Mockito.when(timezoneProvider.getTimeZone()).thenReturn(ZoneId.of("Europe/Berlin"));
+
+        subject = new RobonectHandler(robonectThingMock, httpClientFactoryMock, timezoneProvider);
         subject.setCallback(callbackMock);
         subject.setRobonectClient(robonectClientMock);
-
-        Mockito.when(timezoneProvider.getTimeZone()).thenReturn(ZoneId.of("Europe/Berlin"));
     }
 
     @Test
@@ -97,7 +98,6 @@ public class RobonectHandlerTest {
 
         // when
         when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
-        when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
 
         subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_TIMER_NEXT_TIMER),
                 RefreshType.REFRESH);
@@ -141,7 +141,6 @@ public class RobonectHandlerTest {
         // when
         when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
         when(robonectClientMock.errorList()).thenReturn(errorList);
-        when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
 
         subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
                 RefreshType.REFRESH);
@@ -192,7 +191,6 @@ public class RobonectHandlerTest {
 
         // when
         when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
-        when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
 
         subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
                 RefreshType.REFRESH);
@@ -223,7 +221,6 @@ public class RobonectHandlerTest {
 
         // when
         when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
-        when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
 
         subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
                 RefreshType.REFRESH);
@@ -259,7 +256,6 @@ public class RobonectHandlerTest {
         // when
         when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
         when(robonectClientMock.errorList()).thenReturn(errorList);
-        when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
 
         subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
                 RefreshType.REFRESH);