Wire OpenFlowPluginProviderImpl via OSGi DS 05/111805/6
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 21 May 2024 13:40:53 +0000 (15:40 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 22 May 2024 18:16:51 +0000 (20:16 +0200)
OpenFlowPluginProviderImpl has interactions with injected
SwitchConnectionProviders which get interacted with during shutdown.

This is problematic if Blueprint fails to notice it is shutting down
and there is no point in listening for dependencies showing up in the
proxy interfaces.

While the SwitchConnectionProvider lifecycle needs a deep look, take
advantage of the fact that OPNFLWPLUG-1129 laid the SCR ground work
and move OpenFlowPluginProviderImpl to SCR as well.

This takes Blueprint out of the picture, with SCR guaranteeing we are
looking at a live SwitchConnectionProvider when shutting down.

Unfortunately we still have one more service in Blueprint, hence we need
to manually specify Provides manifest header. That part will be
addressed in a follow-up patch.

JIRA: OPNFLWPLUG-1132
Change-Id: I5329c3209342f52caf7b4403f5c0bcff65c9f669
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginProvider.java [deleted file]
openflowplugin-impl/pom.xml
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java
openflowplugin-impl/src/main/resources/OSGI-INF/blueprint/openflowplugin-impl.xml
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImplTest.java

diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginProvider.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginProvider.java
deleted file mode 100644 (file)
index 9451934..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.openflowplugin.api.openflow;
-
-import org.opendaylight.mdsal.binding.api.BindingService;
-
-/**
- * Plugin services provider.
- */
-public interface OpenFlowPluginProvider extends AutoCloseable, BindingService {
-
-    /**
-     * Method initializes all DeviceManager, RpcManager and related contexts.
-     */
-    void initialize();
-
-}
index 5b8fc1f46a05ebd1229611e7c15c3ae9d086decd..5055d89438585fafc150201a17a6a046ce9067ee 100644 (file)
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <extensions>true</extensions>
-                 <configuration>
-                     <instructions>
-                         <Karaf-Commands>org.opendaylight.openflowplugin.impl.karaf</Karaf-Commands>
-                     </instructions>
+                <configuration>
+                    <instructions>
+                        <Karaf-Commands>org.opendaylight.openflowplugin.impl.karaf</Karaf-Commands>
+                        <!-- FIXME: remove this block when we do not have Blueprint components -->
+                        <Provide-Capability>
+                            osgi.service;objectClass:List&lt;String&gt;="org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager";uses:="org.opendaylight.openflowplugin.api.openflow",
+                            osgi.service;objectClass:List&lt;String&gt;="org.opendaylight.openflowplugin.api.openflow.FlowGroupInfoHistories,org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegistratorProvider";uses:="org.opendaylight.openflowplugin.api.openflow,org.opendaylight.openflowplugin.extension.api",
+                            osgi.service;objectClass:List&lt;String&gt;="org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationServiceFactory";uses:="org.opendaylight.openflowplugin.api.openflow.configuration",
+                            osgi.service;objectClass:List&lt;String&gt;="org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeServiceManager";uses:="org.opendaylight.openflowplugin.api.openflow.mastership",
+                            osgi.service;objectClass:List&lt;String&gt;="org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency";uses:="org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific",
+                            osgi.service;objectClass:List&lt;String&gt;="org.opendaylight.openflowplugin.impl.DiagStatusProvider";uses:="org.opendaylight.openflowplugin.impl",
+
+                            osgi.service;objectClass:List&lt;String&gt;="org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService";uses:="org.opendaylight.openflowplugin.api.openflow.configuration"
+                        </Provide-Capability>
+                    </instructions>
                 </configuration>
             </plugin>
         </plugins>
index bc59a99103fc24f0de4c540df1c0f42e91412272..95246cc6266b1ad26315c01b8c68198a9c1872c9 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.openflowplugin.impl;
 
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
@@ -15,7 +17,6 @@ import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.SettableFuture;
 import io.netty.util.HashedWheelTimer;
 import io.netty.util.Timer;
-import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
@@ -25,7 +26,6 @@ import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.stream.Collectors;
-import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -40,7 +40,6 @@ import org.opendaylight.mdsal.singleton.api.ClusterSingletonServiceProvider;
 import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
 import org.opendaylight.openflowplugin.api.openflow.FlowGroupInfoHistories;
 import org.opendaylight.openflowplugin.api.openflow.FlowGroupInfoHistory;
-import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider;
 import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionManager;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
@@ -49,7 +48,6 @@ import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
-import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderKeeper;
 import org.opendaylight.openflowplugin.extension.api.ExtensionConverterRegistrator;
 import org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegistratorProvider;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterManager;
@@ -72,16 +70,23 @@ import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorM
 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
-public class OpenFlowPluginProviderImpl implements
-        OpenFlowPluginProvider,
-        OpenFlowPluginExtensionRegistratorProvider,
-        FlowGroupInfoHistories,
-        SystemReadyListener {
-
+@Component(immediate = true, service = {
+    OpenFlowPluginExtensionRegistratorProvider.class,
+    FlowGroupInfoHistories.class
+})
+public final class OpenFlowPluginProviderImpl
+        implements OpenFlowPluginExtensionRegistratorProvider, FlowGroupInfoHistories, SystemReadyListener,
+                   AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(OpenFlowPluginProviderImpl.class);
 
     private static final int TICKS_PER_WHEEL = 500; // 0.5 sec.
@@ -92,56 +97,106 @@ public class OpenFlowPluginProviderImpl implements
     //       that worth the complications?
     private final HashedWheelTimer hashedWheelTimer =
             new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, TICKS_PER_WHEEL);
-    private final NotificationPublishService notificationPublishService;
     private final ExtensionConverterManager extensionConverterManager;
-    private final DataBroker dataBroker;
-    private final Collection<SwitchConnectionProvider> switchConnectionProviders;
+    private final List<SwitchConnectionProvider> switchConnectionProviders;
     private final DeviceInitializerProvider deviceInitializerProvider;
     private final ConvertorManager convertorManager;
-    private final RpcProviderService rpcProviderRegistry;
-    private final ClusterSingletonServiceProvider singletonServicesProvider;
     private final OpenflowProviderConfig config;
-    private final EntityOwnershipService entityOwnershipService;
-    private final MastershipChangeServiceManager mastershipChangeServiceManager;
-    private DeviceManager deviceManager;
-    private RpcManager rpcManager;
-    private StatisticsManager statisticsManager;
-    private RoleManager roleManager;
-    private ConnectionManager connectionManager;
-    private ExecutorService executorService;
-    private ContextChainHolderImpl contextChainHolder;
-    private final MessageIntelligenceAgency messageIntelligenceAgency;
+    private final DeviceManager deviceManager;
+    private final RpcManager rpcManager;
+    private final StatisticsManager statisticsManager;
+    private final RoleManager roleManager;
+    private final ExecutorService executorService;
+    private final ContextChainHolderImpl contextChainHolder;
     private final DiagStatusProvider diagStatusProvider;
-    private final SystemReadyMonitor systemReadyMonitor;
     private final SettableFuture<Void> fullyStarted = SettableFuture.create();
-    private static final String OPENFLOW_SERVICE_NAME = "OPENFLOW";
+
+    private ConnectionManager connectionManager;
 
     @Inject
-    public OpenFlowPluginProviderImpl(final ConfigurationService configurationService,
-                               final List<SwitchConnectionProvider> switchConnectionProviders,
-                               final DataBroker dataBroker,
-                               final RpcProviderService rpcProviderRegistry,
-                               final NotificationPublishService notificationPublishService,
-                               final ClusterSingletonServiceProvider singletonServiceProvider,
-                               final EntityOwnershipService entityOwnershipService,
-                               final MastershipChangeServiceManager mastershipChangeServiceManager,
-                               final MessageIntelligenceAgency messageIntelligenceAgency,
-                               final DiagStatusProvider diagStatusProvider,
-                               final SystemReadyMonitor systemReadyMonitor) {
-        this.switchConnectionProviders = switchConnectionProviders;
-        this.dataBroker = new PingPongDataBroker(dataBroker);
-        this.rpcProviderRegistry = rpcProviderRegistry;
-        this.notificationPublishService = notificationPublishService;
-        singletonServicesProvider = singletonServiceProvider;
-        this.entityOwnershipService = entityOwnershipService;
+    @Activate
+    public OpenFlowPluginProviderImpl(@Reference final ConfigurationService configurationService,
+            @Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE, policyOption = ReferencePolicyOption.GREEDY)
+            final List<SwitchConnectionProvider> switchConnectionProviders,
+            @Reference final DataBroker dataBroker, @Reference final RpcProviderService rpcProviderRegistry,
+            @Reference final NotificationPublishService notificationPublishService,
+            @Reference final ClusterSingletonServiceProvider singletonServiceProvider,
+            @Reference final EntityOwnershipService entityOwnershipService,
+            @Reference final MastershipChangeServiceManager mastershipChangeServiceManager,
+            @Reference final MessageIntelligenceAgency messageIntelligenceAgency,
+            @Reference final DiagStatusProvider diagStatusProvider,
+            @Reference final SystemReadyMonitor systemReadyMonitor) {
+        config = new OpenFlowProviderConfigImpl(configurationService);
+        this.switchConnectionProviders = List.copyOf(switchConnectionProviders);
+        final var ppdb = new PingPongDataBroker(dataBroker);
+        this.diagStatusProvider = requireNonNull(diagStatusProvider);
+
         convertorManager = ConvertorManagerFactory.createDefaultManager();
         extensionConverterManager = new ExtensionConverterManagerImpl();
         deviceInitializerProvider = DeviceInitializerProviderFactory.createDefaultProvider();
-        config = new OpenFlowProviderConfigImpl(configurationService);
-        this.mastershipChangeServiceManager = mastershipChangeServiceManager;
-        this.messageIntelligenceAgency = messageIntelligenceAgency;
-        this.diagStatusProvider = diagStatusProvider;
-        this.systemReadyMonitor = systemReadyMonitor;
+
+        // TODO: copied from OpenFlowPluginProvider (Helium) misusesing the old way of distributing extension converters
+        // TODO: rewrite later!
+        OFSessionUtil.getSessionManager().setExtensionConverterProvider(extensionConverterManager);
+
+        // Creates a thread pool that creates new threads as needed, but will reuse previously
+        // constructed threads when they are available.
+        // Threads that have not been used for x seconds are terminated and removed from the cache.
+        executorService = new ThreadPoolLoggingExecutor(
+                config.getThreadPoolMinThreads().toJava(),
+                config.getThreadPoolMaxThreads().getValue().toJava(),
+                config.getThreadPoolTimeout().toJava(),
+                TimeUnit.SECONDS, new SynchronousQueue<>(), POOL_NAME);
+
+        final var devMgr = new DeviceManagerImpl(
+                config,
+                ppdb,
+                messageIntelligenceAgency,
+                notificationPublishService,
+                hashedWheelTimer,
+                convertorManager,
+                deviceInitializerProvider,
+                executorService);
+        deviceManager = devMgr;
+
+        TranslatorLibraryUtil.injectBasicTranslatorLibrary(deviceManager, convertorManager);
+        devMgr.setExtensionConverterProvider(extensionConverterManager);
+
+        rpcManager = new RpcManagerImpl(
+                config,
+                rpcProviderRegistry,
+                extensionConverterManager,
+                convertorManager,
+                notificationPublishService);
+
+        statisticsManager = new StatisticsManagerImpl(
+                config,
+                rpcProviderRegistry,
+                convertorManager,
+                executorService);
+
+        roleManager = new RoleManagerImpl(hashedWheelTimer, config, executorService);
+
+        contextChainHolder = new ContextChainHolderImpl(
+                executorService,
+                singletonServiceProvider,
+                entityOwnershipService,
+                mastershipChangeServiceManager,
+                config);
+
+        contextChainHolder.addManager(deviceManager);
+        contextChainHolder.addManager(statisticsManager);
+        contextChainHolder.addManager(rpcManager);
+        contextChainHolder.addManager(roleManager);
+
+        connectionManager = new ConnectionManagerImpl(config, executorService, ppdb, notificationPublishService);
+        connectionManager.setDeviceConnectedHandler(contextChainHolder);
+        connectionManager.setDeviceDisconnectedHandler(contextChainHolder);
+
+        deviceManager.setContextChainHolder(contextChainHolder);
+        deviceManager.initialize();
+        systemReadyMonitor.registerListener(this);
+        LOG.info("registered onSystemBootReady() listener for OpenFlowPluginProvider");
     }
 
     @Override
@@ -209,72 +264,6 @@ public class OpenFlowPluginProviderImpl implements
         return listListenableFuture;
     }
 
-    @Override
-    @PostConstruct
-    public void initialize() {
-        // TODO: copied from OpenFlowPluginProvider (Helium) misusesing the old way of distributing extension converters
-        // TODO: rewrite later!
-        OFSessionUtil.getSessionManager().setExtensionConverterProvider(extensionConverterManager);
-
-        // Creates a thread pool that creates new threads as needed, but will reuse previously
-        // constructed threads when they are available.
-        // Threads that have not been used for x seconds are terminated and removed from the cache.
-        executorService = new ThreadPoolLoggingExecutor(
-                config.getThreadPoolMinThreads().toJava(),
-                config.getThreadPoolMaxThreads().getValue().toJava(),
-                config.getThreadPoolTimeout().toJava(),
-                TimeUnit.SECONDS, new SynchronousQueue<>(), POOL_NAME);
-
-        deviceManager = new DeviceManagerImpl(
-                config,
-                dataBroker,
-                messageIntelligenceAgency,
-                notificationPublishService,
-                hashedWheelTimer,
-                convertorManager,
-                deviceInitializerProvider,
-                executorService);
-
-        TranslatorLibraryUtil.injectBasicTranslatorLibrary(deviceManager, convertorManager);
-        ((ExtensionConverterProviderKeeper) deviceManager).setExtensionConverterProvider(extensionConverterManager);
-
-        rpcManager = new RpcManagerImpl(
-                config,
-                rpcProviderRegistry,
-                extensionConverterManager,
-                convertorManager,
-                notificationPublishService);
-
-        statisticsManager = new StatisticsManagerImpl(
-                config,
-                rpcProviderRegistry,
-                convertorManager,
-                executorService);
-
-        roleManager = new RoleManagerImpl(hashedWheelTimer, config, executorService);
-
-        contextChainHolder = new ContextChainHolderImpl(
-                executorService,
-                singletonServicesProvider,
-                entityOwnershipService,
-                mastershipChangeServiceManager,
-                config);
-
-        contextChainHolder.addManager(deviceManager);
-        contextChainHolder.addManager(statisticsManager);
-        contextChainHolder.addManager(rpcManager);
-        contextChainHolder.addManager(roleManager);
-
-        connectionManager = new ConnectionManagerImpl(config, executorService, dataBroker, notificationPublishService);
-        connectionManager.setDeviceConnectedHandler(contextChainHolder);
-        connectionManager.setDeviceDisconnectedHandler(contextChainHolder);
-
-        deviceManager.setContextChainHolder(contextChainHolder);
-        deviceManager.initialize();
-        systemReadyMonitor.registerListener(this);
-        LOG.info("registered onSystemBootReady() listener for OpenFlowPluginProvider");
-    }
-
     @Override
     public ExtensionConverterRegistrator getExtensionConverterRegistrator() {
         return extensionConverterManager;
@@ -292,6 +281,7 @@ public class OpenFlowPluginProviderImpl implements
 
     @Override
     @PreDestroy
+    @Deactivate
     @SuppressWarnings("checkstyle:IllegalCatch")
     public void close() {
         try {
index 3e5078e05f5b24c6e899adeea442d975f7358683..c89df82dd10dfd716be3c3fa83a1e3c13aede71d 100644 (file)
@@ -3,38 +3,11 @@
            xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
            xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
            odl:use-default-for-reference-types="true">
-
-  <bean id="openFlowPluginProviderImpl"
-        class="org.opendaylight.openflowplugin.impl.OpenFlowPluginProviderImpl"
-        init-method="initialize"
-        destroy-method="close">
-    <argument ref="configurationService"/>
-    <argument>
-        <list>
-            <ref component-id="defaultSwitchConnProvider"/>
-            <ref component-id="legacySwitchConnProvider"/>
-        </list>
-    </argument>
-    <argument ref="dataBroker"/>
-    <argument ref="rpcProviderService"/>
-    <argument ref="notificationPublishService"/>
-    <argument ref="clusterSingletonServiceProvider"/>
-    <argument ref="entityOwnershipService"/>
-    <argument ref="mastershipChangeServiceManager"/>
-    <argument ref="messageIntelligenceAgency"/>
-    <argument ref="diagStatusProvider"/>
-    <argument ref="systemReadyMonitor"/>
-  </bean>
-  <service ref="openFlowPluginProviderImpl">
-    <interfaces>
-      <value>org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider</value>
-      <value>org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegistratorProvider</value>
-      <value>org.opendaylight.openflowplugin.api.openflow.FlowGroupInfoHistories</value>
-    </interfaces>
-  </service>
-
+  <reference id="configurationServiceFactory"
+             interface="org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationServiceFactory"/>
   <odl:clustered-app-config id="openflowProviderConfig"
                             binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig"/>
+
   <bean id="configurationService"
         factory-ref="configurationServiceFactory"
         factory-method="newInstance"
   </bean>
   <service ref="configurationService"
            interface="org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService"/>
-
-  <reference id="dataBroker"
-             interface="org.opendaylight.mdsal.binding.api.DataBroker"/>
-  <reference id="defaultSwitchConnProvider"
-             interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider"
-             odl:type="openflow-switch-connection-provider-default-impl"/>
-  <reference id="legacySwitchConnProvider"
-             interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider"
-             odl:type="openflow-switch-connection-provider-legacy-impl"/>
-  <reference id="rpcProviderService"
-             interface="org.opendaylight.mdsal.binding.api.RpcProviderService"/>
-  <reference id="notificationPublishService"
-             interface="org.opendaylight.mdsal.binding.api.NotificationPublishService"/>
-  <reference id="clusterSingletonServiceProvider"
-             interface="org.opendaylight.mdsal.singleton.api.ClusterSingletonServiceProvider"/>
-  <reference id="entityOwnershipService"
-             interface="org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService"/>
-  <reference id="diagStatusProvider"
-             interface="org.opendaylight.openflowplugin.impl.DiagStatusProvider"/>
-  <reference id="systemReadyMonitor"
-             interface="org.opendaylight.infrautils.ready.SystemReadyMonitor"/>
-  <reference id="mastershipChangeServiceManager"
-             interface="org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeServiceManager"/>
-  <reference id="messageIntelligenceAgency"
-             interface="org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency"/>
-  <reference id="configurationServiceFactory"
-             interface="org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationServiceFactory"/>
 </blueprint>
index cba8d9b03f8fac963987b93a728a7dfac3a4f2dd..2c421e6ff49b352e69d055b3ecf33128a3aded43 100644 (file)
@@ -96,24 +96,14 @@ public class OpenFlowPluginProviderImplTest {
 
     @Test
     public void testInitializeAndClose() {
-        final OpenFlowPluginProviderImpl provider = new OpenFlowPluginProviderImpl(
-                configurationService,
-                List.of(switchConnectionProvider),
-                dataBroker,
-                rpcProviderRegistry,
-                notificationPublishService,
-                clusterSingletonServiceProvider,
-                entityOwnershipService,
-                mastershipChangeServiceManager,
-                messageIntelligenceAgency,
-                ofPluginDiagstatusProvider,
-                systemReadyMonitor);
-
-        provider.initialize();
-        // Calling the onSystemBootReady() callback
-        provider.onSystemBootReady();
-        verify(switchConnectionProvider).startup();
-        provider.close();
+        try (var provider = new OpenFlowPluginProviderImpl(configurationService, List.of(switchConnectionProvider),
+                dataBroker, rpcProviderRegistry, notificationPublishService, clusterSingletonServiceProvider,
+                entityOwnershipService, mastershipChangeServiceManager, messageIntelligenceAgency,
+                ofPluginDiagstatusProvider, systemReadyMonitor)) {
+            // Calling the onSystemBootReady() callback
+            provider.onSystemBootReady();
+            verify(switchConnectionProvider).startup();
+        }
         verify(switchConnectionProvider).shutdown();
     }
 }