You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2023/01/21 17:12:19 UTC

[plc4x] branch develop updated: New Implementation of the Connection-Cache (#747)

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new b3b85132b7 New Implementation of the Connection-Cache (#747)
b3b85132b7 is described below

commit b3b85132b71e9493c4bb3ed578a2a94dcc65d8ab
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sat Jan 21 18:12:14 2023 +0100

    New Implementation of the Connection-Cache (#747)
    
    * fix(plc4j/ads): Made it possible to use an ADS connection without loading the datatypes in case of raw address queries.
    
    * feat(plc4j/examples): Added a new example, using the ADS protocol to read device telemetry from the PLC using MDP
    
    * feat(plc4j/api): Introduced a new PlcConnectionManager interface, which just contains the getConnection variants in preparation of building a drop-in replacement plc-connection cache.
    
    * fix(build): Updated the plexus-compiler-ecplise plugin
    
    * feat(plc4j/examples): Added a new example, using the ADS protocol to read device telemetry from the PLC using MDP
    
    - Added some more data to the example (now we have the memory usage in %)
    
    * feat(ams): Made it possible to decode error responses
    
    * feat(drivers): Updated vendor-ids and service ids
    
    * feat(cache): Added a new implementation of a connection cache
    
    - Mostly untested draft implementation ... tests are coming.
    
    * feat(cache): Added a new implementation of a connection cache
    
    - Added some more tests
    
    * feat(cache): Added a new implementation of a connection cache
    
    - Implemented the timeout for leases
    - Added some more tests for timeouts
    
    * feat(cache): Added a new implementation of a connection cache
    
    - Updated the rest of the project to use the new cache and deleted the old implementations.
    
    * refactor(plc4j/api): Updated the PlcDriverManager API
    
    - Created 2 new interfaces PlcConnectionManager and PlcDriverManager
    - Renamed the previous PlcDriverManager to DefaultPlcDriverManager
    
    * feat(ads): Added additional Known Group Index for ADS over EtherCAT
    
    * feat(plc4j/ads): Added a new example for reading data via AoE
    
    * chore(build): Updated types after a full build
    
    * docs(plc4j/ads):  Added a comment on the next steps with the ADS driver
    
    * chore(infra): Redirected the issue notifications to dev for testing.
---
 plc4go/protocols/ads/readwrite/model/AmsPacket.go  |  44 +--
 .../ads/readwrite/model/ReservedIndexGroups.go     |   8 +
 ...erManager.java => DefaultPlcDriverManager.java} |  18 +-
 .../{PlcDriver.java => PlcConnectionManager.java}  |  48 +--
 .../java/org/apache/plc4x/java/api/PlcDriver.java  |   9 +-
 .../apache/plc4x/java/api/PlcDriverManager.java}   |  24 +-
 .../apache/plc4x/java/PlcDriverManagerTest.java    |  10 +-
 .../apache/plc4x/java/ads/readwrite/AmsPacket.java |  65 ++--
 .../java/ads/readwrite/ReservedIndexGroups.java    |   1 +
 .../plc4x/java/ads/protocol/AdsProtocolLogic.java  |  47 ++-
 .../org/apache/plc4x/protocol/ads/Scanner.java     |   5 +-
 .../java/can/generic/GenericCANDriverTest.java     |   7 +-
 .../java/org/apache/plc4x/java/canopen/Main.java   |   4 +-
 .../apache/plc4x/java/knxnetip/ManualKnxNetIp.java |   4 +-
 .../java/modbus/ManualModbusDiscoveryTest.java     |   4 +-
 .../apache/plc4x/java/opcua/ManualPLC4XOpcua.java  |   4 +-
 .../plc4x/java/opcua/OpcuaPlcDriverTest.java       |  12 +-
 .../protocol/OpcuaSubscriptionHandleTest.java      |   4 +-
 .../apache/plc4x/java/plc4x/Plc4xReadClient.java   |   4 +-
 .../apache/plc4x/java/plc4x/Plc4xWriteClient.java  |   4 +-
 .../profinet/ManualProfinetIoDiscoveryTest.java    |   4 +-
 .../plc4x/java/profinet/ManualProfinetIoTest.java  |   4 +-
 .../plc4x/java/s7/readwrite/DatatypesTest.java     |   4 +-
 .../hello-ads-telemetry}/pom.xml                   |  39 ++-
 .../telemetry/HelloAdsEtherCatTelemetry.java       | 113 ++++++
 .../helloads/telemetry/HelloAdsTelemetry.java      | 132 +++++++
 .../src/main/resources/logback.xml}                |   2 +-
 .../cloud/azure/S7PlcToAzureIoTHubSample.java      |   4 +-
 .../cloud/google/S7PlcToGoogleIoTCoreSample.java   |   4 +-
 .../examples/connectivity/mqtt/MqttConnector.java  |   4 +-
 .../examples/hellodiscovery/HelloDiscovery.java    |   4 +-
 .../java/examples/helloinflux/HelloInflux.java     |   4 +-
 .../plc4x/java/examples/hellonats/HelloNats.java   |   1 -
 plc4j/examples/hello-opm/pom.xml                   |   2 +-
 .../plc4x/java/examples/helloopm/HelloOpm.java     |   6 +-
 .../examples/hellowebservice/HelloWebservice.java  |   4 +-
 .../java/examples/hellokotlin/ReadModbusPal.kt     |   4 +-
 .../HelloPlc4xDiscoverAndBrowse.java               |   8 +-
 .../examples/helloplc4x/read/HelloPlc4xRead.java   |   4 +-
 .../subscribe/HelloPlc4xSubscription.java          |   4 +-
 .../examples/helloplc4x/write/HelloPlc4xWrite.java |   4 +-
 .../examples/plc4j/s7event/EventSubscription.java  |   4 +-
 .../plc4x/java/examples/pollloop/PollLoop.java     |   5 +-
 plc4j/examples/pom.xml                             |   1 +
 .../java/org/apache/plc4x/kafka/Plc4xSinkTask.java |  10 +-
 .../org/apache/plc4x/kafka/Plc4xSourceTask.java    |   8 +-
 .../java/org/apache/plc4x/kafka/config/Sink.java   |   5 +-
 .../java/org/apache/plc4x/kafka/config/Source.java |   9 +-
 .../apache-nifi/nifi-plc4x-processors/pom.xml      |   2 +-
 .../org/apache/plc4x/nifi/BasePlc4xProcessor.java  |   9 +-
 .../org/apache/plc4x/nifi/Plc4xSinkProcessor.java  |   2 +-
 .../apache/plc4x/nifi/Plc4xSourceProcessor.java    |   2 +-
 .../plc4x/nifi/Plc4xSourceRecordProcessor.java     |   2 +-
 plc4j/integrations/opcua-server/pom.xml            |   2 +-
 .../opcuaserver/backend/Plc4xCommunication.java    | 114 +++---
 .../java/opcuaserver/backend/Plc4xNamespace.java   |  16 +-
 .../plc4x/java/opcuaserver/OpcuaPlcDriverTest.java |  10 +-
 plc4j/tools/connection-cache/README.md             |  51 +++
 plc4j/tools/connection-cache/pom.xml               |   9 +-
 .../utils/cache/CachedPlcConnectionManager.java    | 119 +++++++
 .../java/utils/cache/ConnectionContainer.java      |  75 ++++
 .../java/utils/cache/LeasedPlcConnection.java      | 130 +++++++
 .../utils/connectionpool2/CachedBrowseRequest.java |  60 ----
 .../CachedBrowseRequestBuilder.java                |  43 ---
 .../utils/connectionpool2/CachedDriverManager.java | 356 -------------------
 .../connectionpool2/CachedDriverManagerMBean.java  |  37 --
 .../utils/connectionpool2/CachedPlcConnection.java | 389 ---------------------
 .../utils/connectionpool2/CachedReadRequest.java   |  64 ----
 .../connectionpool2/CachedReadRequestBuilder.java  |  51 ---
 .../connectionpool2/CachedSubscriptionRequest.java |  71 ----
 .../CachedSubscriptionRequestBuilder.java          |  78 -----
 .../CachedUnsubscriptionRequest.java               |  46 ---
 .../CachedUnsubscriptionRequestBuilder.java        |  59 ----
 .../utils/connectionpool2/CachedWriteRequest.java  |  75 ----
 .../connectionpool2/CachedWriteRequestBuilder.java |  51 ---
 .../utils/connectionpool2/PooledDriverManager.java |  87 -----
 .../connectionpool2/PooledDriverManagerMBean.java  |  24 --
 .../cache/CachedPlcConnectionManagerTest.java      | 174 +++++++++
 .../apache/plc4x/java/utils/cache/ManualTest.java} |  22 +-
 .../connectionpool2/CachedDriverManagerIT.java     |  80 -----
 .../connectionpool2/CachedDriverManagerMT.java     | 125 -------
 .../connectionpool2/CachedDriverManagerTest.java   | 241 -------------
 .../connectionpool2/CachedPlcConnectionTest.java   |  92 -----
 .../connectionpool2/PooledDriverManagerTest.java   |  47 ---
 .../src/test/resources/logback-test.xml            |   4 +-
 .../plc4x/java/utils/connectionpool/PoolKey.java   |  72 ----
 .../java/utils/connectionpool/PoolKeyFactory.java  | 109 ------
 .../connectionpool/PooledPlcConnectionFactory.java |  47 ---
 .../connectionpool/PooledPlcDriverManager.java     | 180 ----------
 .../utils/connectionpool/PoolKeyFactoryTest.java   |  96 -----
 .../utils/connectionpool/PooledDummyDriver.java    |  53 ---
 .../connectionpool/PooledPlcDriverManagerTest.java | 375 --------------------
 .../services/org.apache.plc4x.java.api.PlcDriver   |  19 -
 .../plc4x/java/opm/PlcEntityInterceptor.java       |  70 ++--
 .../apache/plc4x/java/opm/PlcEntityManager.java    |  31 +-
 .../apache/plc4x/java/opm/ConnectedEntityTest.java |   6 +-
 .../plc4x/java/opm/PlcEntityInterceptorTest.java   |  23 +-
 .../java/opm/PlcEntityManagerComplexTest.java      |  10 +-
 .../plc4x/java/opm/PlcEntityManagerTest.java       |  14 +-
 .../plc4xserver/protocol/Plc4xServerAdapter.java   |  13 +-
 plc4j/tools/pom.xml                                |   2 +-
 plc4j/tools/{scraper => scraper-ng}/pom.xml        |  25 +-
 plc4j/tools/scraper/pom.xml                        |  12 +-
 .../org/apache/plc4x/java/scraper/ScraperImpl.java |  33 +-
 .../apache/plc4x/java/scraper/ScraperTaskImpl.java |  12 +-
 .../triggeredscraper/TriggeredScraperImpl.java     |  64 ++--
 .../triggeredscraper/TriggeredScraperTask.java     |  16 +-
 .../triggerhandler/TriggerConfiguration.java       |   4 +-
 .../collector/TriggerCollectorImpl.java            |  24 +-
 .../apache/plc4x/java/s7/ManualS7PlcDriverMT.java  |  28 +-
 .../apache/plc4x/java/scraper/ScraperTaskTest.java |  17 +-
 .../org/apache/plc4x/java/scraper/ScraperTest.java |  30 +-
 .../plc4x/java/scraper/TriggeredScraperRunner.java |  10 +-
 .../java/scraper/TriggeredScraperRunnerModbus.java |  10 +-
 .../triggeredscraper/TriggeredScraperImplTest.java |   6 +-
 .../org/apache/plc4x/java/ui/FxmlController.java   |   6 +-
 .../test/driver/internal/ConnectionManager.java    |   7 +-
 .../org/apache/plc4x/test/manual/ManualTest.java   |   4 +-
 pom.xml                                            |   8 +-
 .../ads/src/main/resources/protocols/ads/ads.mspec | 120 ++++---
 .../apache/plc4x/protocol/df1/EndToEndTest.java    |   4 +-
 121 files changed, 1440 insertions(+), 3662 deletions(-)

diff --git a/plc4go/protocols/ads/readwrite/model/AmsPacket.go b/plc4go/protocols/ads/readwrite/model/AmsPacket.go
index cf0ae2073b..1e794fa7dc 100644
--- a/plc4go/protocols/ads/readwrite/model/AmsPacket.go
+++ b/plc4go/protocols/ads/readwrite/model/AmsPacket.go
@@ -450,48 +450,50 @@ func AmsPacketParseWithBuffer(readBuffer utils.ReadBuffer) (AmsPacket, error) {
 	var _child AmsPacketChildSerializeRequirement
 	var typeSwitchError error
 	switch {
-	case commandId == CommandId_INVALID && response == bool(false): // AdsInvalidRequest
+	case errorCode == 0x00000000 && commandId == CommandId_INVALID && response == bool(false): // AdsInvalidRequest
 		_childTemp, typeSwitchError = AdsInvalidRequestParseWithBuffer(readBuffer)
-	case commandId == CommandId_INVALID && response == bool(true): // AdsInvalidResponse
+	case errorCode == 0x00000000 && commandId == CommandId_INVALID && response == bool(true): // AdsInvalidResponse
 		_childTemp, typeSwitchError = AdsInvalidResponseParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_READ_DEVICE_INFO && response == bool(false): // AdsReadDeviceInfoRequest
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_READ_DEVICE_INFO && response == bool(false): // AdsReadDeviceInfoRequest
 		_childTemp, typeSwitchError = AdsReadDeviceInfoRequestParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_READ_DEVICE_INFO && response == bool(true): // AdsReadDeviceInfoResponse
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_READ_DEVICE_INFO && response == bool(true): // AdsReadDeviceInfoResponse
 		_childTemp, typeSwitchError = AdsReadDeviceInfoResponseParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_READ && response == bool(false): // AdsReadRequest
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_READ && response == bool(false): // AdsReadRequest
 		_childTemp, typeSwitchError = AdsReadRequestParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_READ && response == bool(true): // AdsReadResponse
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_READ && response == bool(true): // AdsReadResponse
 		_childTemp, typeSwitchError = AdsReadResponseParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_WRITE && response == bool(false): // AdsWriteRequest
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_WRITE && response == bool(false): // AdsWriteRequest
 		_childTemp, typeSwitchError = AdsWriteRequestParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_WRITE && response == bool(true): // AdsWriteResponse
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_WRITE && response == bool(true): // AdsWriteResponse
 		_childTemp, typeSwitchError = AdsWriteResponseParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_READ_STATE && response == bool(false): // AdsReadStateRequest
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_READ_STATE && response == bool(false): // AdsReadStateRequest
 		_childTemp, typeSwitchError = AdsReadStateRequestParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_READ_STATE && response == bool(true): // AdsReadStateResponse
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_READ_STATE && response == bool(true): // AdsReadStateResponse
 		_childTemp, typeSwitchError = AdsReadStateResponseParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_WRITE_CONTROL && response == bool(false): // AdsWriteControlRequest
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_WRITE_CONTROL && response == bool(false): // AdsWriteControlRequest
 		_childTemp, typeSwitchError = AdsWriteControlRequestParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_WRITE_CONTROL && response == bool(true): // AdsWriteControlResponse
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_WRITE_CONTROL && response == bool(true): // AdsWriteControlResponse
 		_childTemp, typeSwitchError = AdsWriteControlResponseParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_ADD_DEVICE_NOTIFICATION && response == bool(false): // AdsAddDeviceNotificationRequest
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_ADD_DEVICE_NOTIFICATION && response == bool(false): // AdsAddDeviceNotificationRequest
 		_childTemp, typeSwitchError = AdsAddDeviceNotificationRequestParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_ADD_DEVICE_NOTIFICATION && response == bool(true): // AdsAddDeviceNotificationResponse
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_ADD_DEVICE_NOTIFICATION && response == bool(true): // AdsAddDeviceNotificationResponse
 		_childTemp, typeSwitchError = AdsAddDeviceNotificationResponseParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_DELETE_DEVICE_NOTIFICATION && response == bool(false): // AdsDeleteDeviceNotificationRequest
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_DELETE_DEVICE_NOTIFICATION && response == bool(false): // AdsDeleteDeviceNotificationRequest
 		_childTemp, typeSwitchError = AdsDeleteDeviceNotificationRequestParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_DELETE_DEVICE_NOTIFICATION && response == bool(true): // AdsDeleteDeviceNotificationResponse
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_DELETE_DEVICE_NOTIFICATION && response == bool(true): // AdsDeleteDeviceNotificationResponse
 		_childTemp, typeSwitchError = AdsDeleteDeviceNotificationResponseParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_DEVICE_NOTIFICATION && response == bool(false): // AdsDeviceNotificationRequest
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_DEVICE_NOTIFICATION && response == bool(false): // AdsDeviceNotificationRequest
 		_childTemp, typeSwitchError = AdsDeviceNotificationRequestParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_DEVICE_NOTIFICATION && response == bool(true): // AdsDeviceNotificationResponse
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_DEVICE_NOTIFICATION && response == bool(true): // AdsDeviceNotificationResponse
 		_childTemp, typeSwitchError = AdsDeviceNotificationResponseParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_READ_WRITE && response == bool(false): // AdsReadWriteRequest
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_READ_WRITE && response == bool(false): // AdsReadWriteRequest
 		_childTemp, typeSwitchError = AdsReadWriteRequestParseWithBuffer(readBuffer)
-	case commandId == CommandId_ADS_READ_WRITE && response == bool(true): // AdsReadWriteResponse
+	case errorCode == 0x00000000 && commandId == CommandId_ADS_READ_WRITE && response == bool(true): // AdsReadWriteResponse
 		_childTemp, typeSwitchError = AdsReadWriteResponseParseWithBuffer(readBuffer)
+	case true: // ErrorResponse
+		_childTemp, typeSwitchError = ErrorResponseParseWithBuffer(readBuffer)
 	default:
-		typeSwitchError = errors.Errorf("Unmapped type for parameters [commandId=%v, response=%v]", commandId, response)
+		typeSwitchError = errors.Errorf("Unmapped type for parameters [errorCode=%v, commandId=%v, response=%v]", errorCode, commandId, response)
 	}
 	if typeSwitchError != nil {
 		return nil, errors.Wrap(typeSwitchError, "Error parsing sub-type for type-switch of AmsPacket")
diff --git a/plc4go/protocols/ads/readwrite/model/ReservedIndexGroups.go b/plc4go/protocols/ads/readwrite/model/ReservedIndexGroups.go
index 0f969752e6..87de0e7a48 100644
--- a/plc4go/protocols/ads/readwrite/model/ReservedIndexGroups.go
+++ b/plc4go/protocols/ads/readwrite/model/ReservedIndexGroups.go
@@ -68,6 +68,7 @@ const (
 	ReservedIndexGroups_ADSIGRP_MULTIPLE_ADD_DEVICE_NOTIFICATIONS    ReservedIndexGroups = 0x0000F085
 	ReservedIndexGroups_ADSIGRP_MULTIPLE_DELETE_DEVICE_NOTIFICATIONS ReservedIndexGroups = 0x0000F086
 	ReservedIndexGroups_ADSIGRP_DEVICE_DATA                          ReservedIndexGroups = 0x0000F100
+	ReservedIndexGroups_ADS_OVER_ETHERCAT                            ReservedIndexGroups = 0x0000F302
 	ReservedIndexGroups_ADSIOFFS_DEVDATA_ADSSTATE                    ReservedIndexGroups = 0x00000000
 	ReservedIndexGroups_ADSIOFFS_DEVDATA_DEVSTATE                    ReservedIndexGroups = 0x00000002
 )
@@ -111,6 +112,7 @@ func init() {
 		ReservedIndexGroups_ADSIGRP_MULTIPLE_ADD_DEVICE_NOTIFICATIONS,
 		ReservedIndexGroups_ADSIGRP_MULTIPLE_DELETE_DEVICE_NOTIFICATIONS,
 		ReservedIndexGroups_ADSIGRP_DEVICE_DATA,
+		ReservedIndexGroups_ADS_OVER_ETHERCAT,
 		ReservedIndexGroups_ADSIOFFS_DEVDATA_ADSSTATE,
 		ReservedIndexGroups_ADSIOFFS_DEVDATA_DEVSTATE,
 	}
@@ -190,6 +192,8 @@ func ReservedIndexGroupsByValue(value uint32) (enum ReservedIndexGroups, ok bool
 		return ReservedIndexGroups_ADSIGRP_MULTIPLE_DELETE_DEVICE_NOTIFICATIONS, true
 	case 0x0000F100:
 		return ReservedIndexGroups_ADSIGRP_DEVICE_DATA, true
+	case 0x0000F302:
+		return ReservedIndexGroups_ADS_OVER_ETHERCAT, true
 	}
 	return 0, false
 }
@@ -268,6 +272,8 @@ func ReservedIndexGroupsByName(value string) (enum ReservedIndexGroups, ok bool)
 		return ReservedIndexGroups_ADSIGRP_MULTIPLE_DELETE_DEVICE_NOTIFICATIONS, true
 	case "ADSIGRP_DEVICE_DATA":
 		return ReservedIndexGroups_ADSIGRP_DEVICE_DATA, true
+	case "ADS_OVER_ETHERCAT":
+		return ReservedIndexGroups_ADS_OVER_ETHERCAT, true
 	}
 	return 0, false
 }
@@ -403,6 +409,8 @@ func (e ReservedIndexGroups) PLC4XEnumName() string {
 		return "ADSIGRP_MULTIPLE_DELETE_DEVICE_NOTIFICATIONS"
 	case ReservedIndexGroups_ADSIGRP_DEVICE_DATA:
 		return "ADSIGRP_DEVICE_DATA"
+	case ReservedIndexGroups_ADS_OVER_ETHERCAT:
+		return "ADS_OVER_ETHERCAT"
 	}
 	return ""
 }
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java b/plc4j/api/src/main/java/org/apache/plc4x/java/DefaultPlcDriverManager.java
similarity index 93%
rename from plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java
rename to plc4j/api/src/main/java/org/apache/plc4x/java/DefaultPlcDriverManager.java
index 1514b4c080..fc5a3c8274 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/PlcDriverManager.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/DefaultPlcDriverManager.java
@@ -19,9 +19,11 @@
 package org.apache.plc4x.java;
 
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
+import org.apache.plc4x.java.api.PlcDriver;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.authentication.PlcAuthentication;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.apache.plc4x.java.api.PlcDriver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -32,19 +34,19 @@ import java.util.Map;
 import java.util.ServiceLoader;
 import java.util.Set;
 
-public class PlcDriverManager {
+public class DefaultPlcDriverManager implements PlcDriverManager, PlcConnectionManager {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(PlcDriverManager.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPlcDriverManager.class);
 
     protected ClassLoader classLoader;
 
     private Map<String, PlcDriver> driverMap;
 
-    public PlcDriverManager() {
+    public DefaultPlcDriverManager() {
         this(Thread.currentThread().getContextClassLoader());
     }
 
-    public PlcDriverManager(ClassLoader classLoader) {
+    public DefaultPlcDriverManager(ClassLoader classLoader) {
         LOGGER.info("Instantiating new PLC Driver Manager with class loader {}", classLoader);
         this.classLoader = classLoader;
         driverMap = new HashMap<>();
@@ -142,4 +144,8 @@ public class PlcDriverManager {
         }
     }
 
-}
\ No newline at end of file
+    public PlcConnectionManager getConnectionManager() {
+        return this;
+    }
+
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcConnectionManager.java
similarity index 50%
copy from plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java
copy to plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcConnectionManager.java
index 8ffeb83028..98511ad75a 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcConnectionManager.java
@@ -20,42 +20,8 @@ package org.apache.plc4x.java.api;
 
 import org.apache.plc4x.java.api.authentication.PlcAuthentication;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.apache.plc4x.java.api.exceptions.PlcNotImplementedException;
-import org.apache.plc4x.java.api.exceptions.PlcUnsupportedOperationException;
-import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
-import org.apache.plc4x.java.api.metadata.PlcDriverMetadata;
-import org.apache.plc4x.java.api.model.PlcTag;
 
-/**
- * General interface defining the minimal methods required for adding a new type of driver to the PLC4J system.
- *
- * <b>Note that each driver has to add a service file called org.apache.plc4x.java.spi.PlcDriver to
- * src/main/resources/META-INF which contains the fully qualified classname in order to get loaded
- * by the PlcDriverManager instances.</b>
- */
-public interface PlcDriver {
-
-    /**
-     * @return code of the implemented protocol. This is usually a lot shorter than the String returned by @seeĀ #getProtocolName().
-     */
-    String getProtocolCode();
-
-    /**
-     * @return name of the implemented protocol.
-     */
-    String getProtocolName();
-
-    /**
-     * Provides driver metadata.
-     */
-    default PlcDriverMetadata getMetadata() {
-        return new PlcDriverMetadata() {
-            @Override
-            public boolean canDiscover() {
-                return false;
-            }
-        };
-    }
+public interface PlcConnectionManager {
 
     /**
      * Connects to a PLC using the given plc connection string.
@@ -76,16 +42,4 @@ public interface PlcDriver {
      */
     PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException;
 
-    default PlcTag prepareTag(String tagAddress) {
-        throw new PlcNotImplementedException("Not implemented for " + getProtocolName());
-    }
-
-    /**
-     * @return discovery request builder.
-     * @throws PlcUnsupportedOperationException if the connection does not support subscription
-     */
-    default PlcDiscoveryRequest.Builder discoveryRequestBuilder() {
-        throw new PlcNotImplementedException("Not implemented for " + getProtocolName());
-    }
-
 }
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java
index 8ffeb83028..7ace7ad223 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriver.java
@@ -28,7 +28,7 @@ import org.apache.plc4x.java.api.model.PlcTag;
 
 /**
  * General interface defining the minimal methods required for adding a new type of driver to the PLC4J system.
- *
+ * <br>
  * <b>Note that each driver has to add a service file called org.apache.plc4x.java.spi.PlcDriver to
  * src/main/resources/META-INF which contains the fully qualified classname in order to get loaded
  * by the PlcDriverManager instances.</b>
@@ -49,12 +49,7 @@ public interface PlcDriver {
      * Provides driver metadata.
      */
     default PlcDriverMetadata getMetadata() {
-        return new PlcDriverMetadata() {
-            @Override
-            public boolean canDiscover() {
-                return false;
-            }
-        };
+        return () -> false;
     }
 
     /**
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PlcConnectionFactory.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriverManager.java
similarity index 64%
rename from plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PlcConnectionFactory.java
rename to plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriverManager.java
index c152fb8449..388abc7578 100644
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PlcConnectionFactory.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/PlcDriverManager.java
@@ -16,17 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.utils.connectionpool2;
+package org.apache.plc4x.java.api;
 
-import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 
-/**
- * Simple Factory Method which creates a new PlcConnection
- */
-@FunctionalInterface
-public interface PlcConnectionFactory {
+import java.util.Set;
+
+public interface PlcDriverManager {
+
+    static PlcDriverManager getDefault() {
+        return new DefaultPlcDriverManager();
+    }
+
+    Set<String> listDrivers();
+
+    PlcDriver getDriver(String protocolCode) throws PlcConnectionException;
+
+    PlcDriver getDriverForUrl(String url) throws PlcConnectionException;
 
-    PlcConnection create() throws PlcConnectionException;
+    PlcConnectionManager getConnectionManager();
 
 }
diff --git a/plc4j/api/src/test/java/org/apache/plc4x/java/PlcDriverManagerTest.java b/plc4j/api/src/test/java/org/apache/plc4x/java/PlcDriverManagerTest.java
index 0e3551de1d..9dddd1e729 100644
--- a/plc4j/api/src/test/java/org/apache/plc4x/java/PlcDriverManagerTest.java
+++ b/plc4j/api/src/test/java/org/apache/plc4x/java/PlcDriverManagerTest.java
@@ -45,7 +45,7 @@ public class PlcDriverManagerTest {
      */
     @Test
     public void getExistingDriverTest() throws PlcException {
-        MockPlcConnection mockConnection = (MockPlcConnection) new PlcDriverManager().getConnection("api-mock://some-cool-url");
+        MockPlcConnection mockConnection = (MockPlcConnection) new DefaultPlcDriverManager().getConnection("api-mock://some-cool-url");
 
         assertThat(mockConnection.getAuthentication(), nullValue());
         assertThat(mockConnection.isConnected(), is(true));
@@ -60,7 +60,7 @@ public class PlcDriverManagerTest {
     public void getExistingDriverWithAuthenticationTest() throws PlcException {
         PlcUsernamePasswordAuthentication authentication =
             new PlcUsernamePasswordAuthentication("user", "pass");
-        MockPlcConnection mockConnection = (MockPlcConnection) new PlcDriverManager().getConnection("api-mock://some-cool-url", authentication);
+        MockPlcConnection mockConnection = (MockPlcConnection) new DefaultPlcDriverManager().getConnection("api-mock://some-cool-url", authentication);
 
         assertThat(mockConnection.getAuthentication(), notNullValue());
         assertThat(mockConnection.getAuthentication(), instanceOf(PlcUsernamePasswordAuthentication.class));
@@ -75,7 +75,7 @@ public class PlcDriverManagerTest {
     @Test
     public void getNotExistingDriverTest() {
         assertThrows(PlcConnectionException.class,
-            () -> new PlcDriverManager().getConnection("non-existing-protocol://some-cool-url"));
+            () -> new DefaultPlcDriverManager().getConnection("non-existing-protocol://some-cool-url"));
     }
 
     /**
@@ -86,7 +86,7 @@ public class PlcDriverManagerTest {
     @Test
     public void getInvalidUriTest() throws PlcConnectionException {
         assertThrows(PlcConnectionException.class,
-            () -> new PlcDriverManager().getConnection("The quick brown fox jumps over the lazy dog"));
+            () -> new DefaultPlcDriverManager().getConnection("The quick brown fox jumps over the lazy dog"));
     }
 
     /**
@@ -108,7 +108,7 @@ public class PlcDriverManagerTest {
 
         // expect exception
         assertThrows(IllegalStateException.class,
-            () -> new PlcDriverManager(fakeClassLoader).getConnection("api-mock://some-cool-url"));
+            () -> new DefaultPlcDriverManager(fakeClassLoader).getConnection("api-mock://some-cool-url"));
     }
 
 }
diff --git a/plc4j/drivers/ads/src/main/generated/org/apache/plc4x/java/ads/readwrite/AmsPacket.java b/plc4j/drivers/ads/src/main/generated/org/apache/plc4x/java/ads/readwrite/AmsPacket.java
index 6547947b91..520d01ff4d 100644
--- a/plc4j/drivers/ads/src/main/generated/org/apache/plc4x/java/ads/readwrite/AmsPacket.java
+++ b/plc4j/drivers/ads/src/main/generated/org/apache/plc4x/java/ads/readwrite/AmsPacket.java
@@ -346,71 +346,96 @@ public abstract class AmsPacket implements Message {
 
     // Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
     AmsPacketBuilder builder = null;
-    if (EvaluationHelper.equals(commandId, CommandId.INVALID)
+    if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.INVALID)
         && EvaluationHelper.equals(response, (boolean) false)) {
       builder = AdsInvalidRequest.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.INVALID)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.INVALID)
         && EvaluationHelper.equals(response, (boolean) true)) {
       builder = AdsInvalidResponse.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_READ_DEVICE_INFO)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_READ_DEVICE_INFO)
         && EvaluationHelper.equals(response, (boolean) false)) {
       builder = AdsReadDeviceInfoRequest.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_READ_DEVICE_INFO)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_READ_DEVICE_INFO)
         && EvaluationHelper.equals(response, (boolean) true)) {
       builder = AdsReadDeviceInfoResponse.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_READ)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_READ)
         && EvaluationHelper.equals(response, (boolean) false)) {
       builder = AdsReadRequest.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_READ)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_READ)
         && EvaluationHelper.equals(response, (boolean) true)) {
       builder = AdsReadResponse.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_WRITE)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_WRITE)
         && EvaluationHelper.equals(response, (boolean) false)) {
       builder = AdsWriteRequest.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_WRITE)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_WRITE)
         && EvaluationHelper.equals(response, (boolean) true)) {
       builder = AdsWriteResponse.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_READ_STATE)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_READ_STATE)
         && EvaluationHelper.equals(response, (boolean) false)) {
       builder = AdsReadStateRequest.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_READ_STATE)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_READ_STATE)
         && EvaluationHelper.equals(response, (boolean) true)) {
       builder = AdsReadStateResponse.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_WRITE_CONTROL)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_WRITE_CONTROL)
         && EvaluationHelper.equals(response, (boolean) false)) {
       builder = AdsWriteControlRequest.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_WRITE_CONTROL)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_WRITE_CONTROL)
         && EvaluationHelper.equals(response, (boolean) true)) {
       builder = AdsWriteControlResponse.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_ADD_DEVICE_NOTIFICATION)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_ADD_DEVICE_NOTIFICATION)
         && EvaluationHelper.equals(response, (boolean) false)) {
       builder = AdsAddDeviceNotificationRequest.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_ADD_DEVICE_NOTIFICATION)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_ADD_DEVICE_NOTIFICATION)
         && EvaluationHelper.equals(response, (boolean) true)) {
       builder = AdsAddDeviceNotificationResponse.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_DELETE_DEVICE_NOTIFICATION)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_DELETE_DEVICE_NOTIFICATION)
         && EvaluationHelper.equals(response, (boolean) false)) {
       builder = AdsDeleteDeviceNotificationRequest.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_DELETE_DEVICE_NOTIFICATION)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_DELETE_DEVICE_NOTIFICATION)
         && EvaluationHelper.equals(response, (boolean) true)) {
       builder = AdsDeleteDeviceNotificationResponse.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_DEVICE_NOTIFICATION)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_DEVICE_NOTIFICATION)
         && EvaluationHelper.equals(response, (boolean) false)) {
       builder = AdsDeviceNotificationRequest.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_DEVICE_NOTIFICATION)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_DEVICE_NOTIFICATION)
         && EvaluationHelper.equals(response, (boolean) true)) {
       builder = AdsDeviceNotificationResponse.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_READ_WRITE)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_READ_WRITE)
         && EvaluationHelper.equals(response, (boolean) false)) {
       builder = AdsReadWriteRequest.staticParseBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(commandId, CommandId.ADS_READ_WRITE)
+    } else if (EvaluationHelper.equals(errorCode, (long) 0x00000000L)
+        && EvaluationHelper.equals(commandId, CommandId.ADS_READ_WRITE)
         && EvaluationHelper.equals(response, (boolean) true)) {
       builder = AdsReadWriteResponse.staticParseBuilder(readBuffer);
+    } else {
+      builder = ErrorResponse.staticParseBuilder(readBuffer);
     }
     if (builder == null) {
       throw new ParseException(
           "Unsupported case for discriminated type"
               + " parameters ["
+              + "errorCode="
+              + errorCode
+              + " "
               + "commandId="
               + commandId
               + " "
diff --git a/plc4j/drivers/ads/src/main/generated/org/apache/plc4x/java/ads/readwrite/ReservedIndexGroups.java b/plc4j/drivers/ads/src/main/generated/org/apache/plc4x/java/ads/readwrite/ReservedIndexGroups.java
index 010c716605..e8e46b7f73 100644
--- a/plc4j/drivers/ads/src/main/generated/org/apache/plc4x/java/ads/readwrite/ReservedIndexGroups.java
+++ b/plc4j/drivers/ads/src/main/generated/org/apache/plc4x/java/ads/readwrite/ReservedIndexGroups.java
@@ -58,6 +58,7 @@ public enum ReservedIndexGroups {
   ADSIGRP_MULTIPLE_ADD_DEVICE_NOTIFICATIONS((long) 0x0000F085L),
   ADSIGRP_MULTIPLE_DELETE_DEVICE_NOTIFICATIONS((long) 0x0000F086L),
   ADSIGRP_DEVICE_DATA((long) 0x0000F100L),
+  ADS_OVER_ETHERCAT((long) 0x0000F302L),
   ADSIOFFS_DEVDATA_ADSSTATE((long) 0x00000000L),
   ADSIOFFS_DEVDATA_DEVSTATE((long) 0x00000002L);
   private static final Map<Long, ReservedIndexGroups> map;
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
index c317ec61d6..bfd1dad176 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
@@ -136,11 +136,14 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
         // otherwise just mark the connection as completed instantly.
         setupAmsRouteFuture.whenComplete((unused, throwable) -> {
             if (!configuration.isLoadSymbolAndDataTypeTables()) {
-                future.completeExceptionally(new PlcConnectionException(
-                    "Lazy loading is generally planned, but not implemented yet. " +
-                        "If you are in need for this feature, please reach out to the community."));
-            }
-            //if (configuration.isLoadSymbolAndDataTypeTables()) {
+                context.fireConnected();
+                // Instead of aborting here, we allow connecting, as the user might be using raw-addresses
+                // This is particularly important for using the driver together with ADS over EtherCAT for accessing
+                // direct EtherCAT devices.
+//                future.completeExceptionally(new PlcConnectionException(
+//                    "Lazy loading is generally planned, but not implemented yet. " +
+//                        "If you are in need for this feature, please reach out to the community."));
+            } else {
                 // Execute a ReadDeviceInfo command
                 AmsPacket readDeviceInfoRequest = new AdsReadDeviceInfoRequest(
                     configuration.getTargetAmsNetId(), DefaultAmsPorts.RUNTIME_SYSTEM_01.getValue(),
@@ -230,9 +233,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                                 }
                             }));
                     }));
-            /*} else {
-                context.fireConnected();
-            }*/
+            }
         });
     }
 
@@ -646,7 +647,12 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
 
         String dataTypeName = directAdsTag.getPlcDataType();
         AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(dataTypeName);
-        long size = adsDataTypeTableEntry.getSize();
+        long size;
+        if(adsDataTypeTableEntry == null) {
+            size = AdsDataType.valueOf(dataTypeName).getNumBytes();
+        } else {
+            size = adsDataTypeTableEntry.getSize();
+        }
 
         AmsPacket amsPacket = new AdsReadRequest(configuration.getTargetAmsNetId(), configuration.getTargetAmsPort(),
             configuration.getSourceAmsNetId(), configuration.getSourceAmsPort(), 0, getInvokeId(),
@@ -685,7 +691,12 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
             tag -> {
                 String dataTypeName = tag.getPlcDataType();
                 AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(dataTypeName);
-                long size = adsDataTypeTableEntry.getSize();
+                long size;
+                if(adsDataTypeTableEntry == null) {
+                    size = AdsDataType.valueOf(dataTypeName).getNumBytes();
+                } else {
+                    size = adsDataTypeTableEntry.getSize();
+                }
                 // Status code + payload size
                 return 4 + (size * tag.getNumberOfElements());
             }).sum();
@@ -699,7 +710,12 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                 DirectAdsTag directAdsTag = resolvedTags.get(tag);
                 String dataTypeName = directAdsTag.getPlcDataType();
                 AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(dataTypeName);
-                long size = adsDataTypeTableEntry.getSize();
+                long size;
+                if(adsDataTypeTableEntry == null) {
+                    size = AdsDataType.valueOf(dataTypeName).getNumBytes();
+                } else {
+                    size = adsDataTypeTableEntry.getSize();
+                }
                 return new AdsMultiRequestItemRead(
                     directAdsTag.getIndexGroup(), directAdsTag.getIndexOffset(),
                     (size * directAdsTag.getNumberOfElements()));
@@ -791,7 +807,14 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
     private ResponseItem<PlcValue> parseResponseItem(DirectAdsTag tag, ReadBuffer readBuffer) {
         try {
             String dataTypeName = tag.getPlcDataType();
-            AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(dataTypeName);
+            AdsDataTypeTableEntry adsDataTypeTableEntry;
+            if (dataTypeTable.containsKey(dataTypeName)) {
+                adsDataTypeTableEntry = dataTypeTable.get(dataTypeName);
+            } else {
+                // If we're missing a datatype, try just using the datatype name.
+                AdsDataType adsDataType = AdsDataType.valueOf(dataTypeName);
+                adsDataTypeTableEntry = new AdsDataTypeTableEntry(0L, 0L, 0L, 0L, adsDataType.getNumBytes(), 0L, 0L, 0L, 0, 0, dataTypeName, dataTypeName, "", Collections.emptyList(), Collections.emptyList(), new byte[]{});
+            }
             PlcValueType plcValueType = getPlcValueTypeForAdsDataType(adsDataTypeTableEntry);
 
             int strLen = 0;
diff --git a/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/Scanner.java b/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/Scanner.java
index 197126d8f3..84efe71d36 100644
--- a/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/Scanner.java
+++ b/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/Scanner.java
@@ -24,7 +24,8 @@ import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
-import org.apache.plc4x.java.PlcDriverManager;
+
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.ads.readwrite.AdsDataType;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
@@ -58,7 +59,7 @@ public class Scanner {
         System.out.println("Launching connection " + connectionString);
 
         // Establish a connection to the plc using the url provided as first argument
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection(connectionString)) {
+        try (PlcConnection plcConnection = new DefaultPlcDriverManager().getConnection(connectionString)) {
             PlcConnectionMetadata metadata = plcConnection.getMetadata();
             System.out.println("read: " + metadata.canRead());
             System.out.println("write: " + metadata.canWrite());
diff --git a/plc4j/drivers/can/src/test/java/org/apache/plc4x/java/can/generic/GenericCANDriverTest.java b/plc4j/drivers/can/src/test/java/org/apache/plc4x/java/can/generic/GenericCANDriverTest.java
index e42bd3ebbb..cbd1e09d30 100644
--- a/plc4j/drivers/can/src/test/java/org/apache/plc4x/java/can/generic/GenericCANDriverTest.java
+++ b/plc4j/drivers/can/src/test/java/org/apache/plc4x/java/can/generic/GenericCANDriverTest.java
@@ -21,7 +21,8 @@ package org.apache.plc4x.java.can.generic;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
-import org.apache.plc4x.java.PlcDriverManager;
+
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionEvent;
@@ -34,7 +35,7 @@ public class GenericCANDriverTest {
 
     @Test
     void testConnection() throws PlcConnectionException {
-        PlcConnection connection = new PlcDriverManager().getConnection("genericcan:virtualcan://");
+        PlcConnection connection = new DefaultPlcDriverManager().getConnection("genericcan:virtualcan://");
 
         assertNotNull(connection);
         assertTrue(connection.isConnected());
@@ -48,7 +49,7 @@ public class GenericCANDriverTest {
     void testSubscribeAndWrite() throws Exception {
 //        PlcConnection connection1 = new PlcDriverManager().getConnection("genericcan:socketcan://vcan0");
 //        PlcConnection connection2 = new PlcDriverManager().getConnection("genericcan:socketcan://vcan0");
-        PlcConnection connection1 = new PlcDriverManager().getConnection("genericcan:virtualcan://");
+        PlcConnection connection1 = new DefaultPlcDriverManager().getConnection("genericcan:virtualcan://");
         PlcConnection connection2 = connection1;
 
         CountDownLatch latch = new CountDownLatch(1);
diff --git a/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/Main.java b/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/Main.java
index e3fcdadf4f..6b29b396cc 100644
--- a/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/Main.java
+++ b/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/Main.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.canopen;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
@@ -35,7 +35,7 @@ import java.util.concurrent.CompletableFuture;
 public class Main {
 
     public static void main(String[] args) throws Exception {
-        PlcDriverManager driverManager = new PlcDriverManager();
+        DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
 
         CANOpenDriverContext.CALLBACK.addCallback(new Callback() {
             @Override
diff --git a/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java b/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java
index 3d20215b1a..2d6dc800e8 100644
--- a/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java
+++ b/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.knxnetip;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
@@ -39,7 +39,7 @@ public class ManualKnxNetIp {
 
     public static void main(String[] args) throws Exception {
         //final PlcConnection connection = new PlcDriverManager().getConnection("knxnet-ip://192.168.42.11?knxproj-file-path=/Users/christofer.dutz/Projects/Apache/PLC4X-Documents/KNX/Stettiner%20Str.%2013/StettinerStr-Soll-Ist-Temperatur.knxproj");
-        final PlcConnection connection = new PlcDriverManager().getConnection("knxnet-ip:pcap:///Users/christofer.dutz/Projects/Apache/PLC4X-Documents/KNX/Recording-01.03.2020-2.pcapng?knxproj-file-path=/Users/christofer.dutz/Projects/Apache/PLC4X-Documents/KNX/Stettiner%20Str.%2013/StettinerStr-Soll-Ist-Temperatur.knxproj");
+        final PlcConnection connection = new DefaultPlcDriverManager().getConnection("knxnet-ip:pcap:///Users/christofer.dutz/Projects/Apache/PLC4X-Documents/KNX/Recording-01.03.2020-2.pcapng?knxproj-file-path=/Users/christofer.dutz/Projects/Apache/PLC4X-Documents/KNX/Stettiner%20Str.%2013/StettinerStr-Soll-Ist-Temperatur.knxproj");
         // Make sure we hang up correctly when terminating.
         Runtime.getRuntime().addShutdownHook(new Thread(() -> {
             try {
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDiscoveryTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDiscoveryTest.java
index 89007ee331..0e3342c141 100644
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDiscoveryTest.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDiscoveryTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.modbus;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcDriver;
 import org.apache.plc4x.java.api.messages.PlcDiscoveryResponse;
 import org.junit.jupiter.api.Disabled;
@@ -27,7 +27,7 @@ import org.junit.jupiter.api.Disabled;
 public class ManualModbusDiscoveryTest {
 
     public static void main(String[] args) throws Exception {
-        final PlcDriver modbusDriver = new PlcDriverManager().getDriver("modbus-tcp");
+        final PlcDriver modbusDriver = new DefaultPlcDriverManager().getDriver("modbus-tcp");
         final PlcDiscoveryResponse plcDiscoveryResponse = modbusDriver.discoveryRequestBuilder().build().execute().get();
         System.out.println(plcDiscoveryResponse);
     }
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java
index f9ab1cb59c..b39eab511f 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.opcua;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
@@ -101,7 +101,7 @@ public class ManualPLC4XOpcua {
         OpcuaPlcTagHandler tagH = new OpcuaPlcTagHandler();
         PlcTag tag = tagH.parseTag(BOOL_IDENTIFIER);
         try {
-            opcuaConnection = new PlcDriverManager().getConnection("opcua:tcp://127.0.0.1:12686/milo?discovery=false");
+            opcuaConnection = new DefaultPlcDriverManager().getConnection("opcua:tcp://127.0.0.1:12686/milo?discovery=false");
 
         } catch (PlcConnectionException e) {
             throw new PlcRuntimeException(e);
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
index 3f92f6dd93..616218c8d1 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
@@ -19,7 +19,7 @@
 package org.apache.plc4x.java.opcua;
 
 import io.vavr.collection.List;
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
@@ -156,7 +156,7 @@ public class OpcuaPlcDriverTest {
     public void connectionNoParams() {
         connectionStringValidSet.forEach(connectionString -> {
             try {
-                PlcConnection opcuaConnection = new PlcDriverManager().getConnection(connectionString);
+                PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(connectionString);
                 Condition<PlcConnection> is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
                 assertThat(opcuaConnection).is(is_connected);
                 opcuaConnection.close();
@@ -175,7 +175,7 @@ public class OpcuaPlcDriverTest {
             discoveryParamValidSet.forEach(discoveryParam -> {
                 String connectionString = connectionAddress + paramSectionDivider + discoveryParam;
                 try {
-                    PlcConnection opcuaConnection = new PlcDriverManager().getConnection(connectionString);
+                    PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(connectionString);
                     Condition<PlcConnection> is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
                     assertThat(opcuaConnection).is(is_connected);
                     opcuaConnection.close();
@@ -192,7 +192,7 @@ public class OpcuaPlcDriverTest {
     @Test
     public void readVariables() {
         try {
-            PlcConnection opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress);
+            PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(tcpConnectionAddress);
             Condition<PlcConnection> is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
             assertThat(opcuaConnection).is(is_connected);
 
@@ -269,7 +269,7 @@ public class OpcuaPlcDriverTest {
 
     @Test
     public void writeVariables() throws Exception {
-        PlcConnection opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress);
+        PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(tcpConnectionAddress);
         Condition<PlcConnection> is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
         assertThat(opcuaConnection).is(is_connected);
 
@@ -433,7 +433,7 @@ public class OpcuaPlcDriverTest {
 
 
         try {
-            PlcConnection opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress);
+            PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(tcpConnectionAddress);
             Condition<PlcConnection> is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
             assertThat(opcuaConnection).is(is_connected);
 
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandleTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandleTest.java
index ca8d011787..868576385f 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandleTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandleTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.opcua.protocol;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse;
@@ -97,7 +97,7 @@ public class OpcuaSubscriptionHandleTest {
             exampleServer = new ExampleServer();
             exampleServer.startup().get();
             //Connect
-            opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress);
+            opcuaConnection = new DefaultPlcDriverManager().getConnection(tcpConnectionAddress);
             assert opcuaConnection.isConnected();
         } catch (Exception e) {
             e.printStackTrace();
diff --git a/plc4j/drivers/plc4x/src/test/java/org/apache/plc4x/java/plc4x/Plc4xReadClient.java b/plc4j/drivers/plc4x/src/test/java/org/apache/plc4x/java/plc4x/Plc4xReadClient.java
index 98bd3db7c4..09a2f4d4ed 100644
--- a/plc4j/drivers/plc4x/src/test/java/org/apache/plc4x/java/plc4x/Plc4xReadClient.java
+++ b/plc4j/drivers/plc4x/src/test/java/org/apache/plc4x/java/plc4x/Plc4xReadClient.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.plc4x;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
@@ -26,7 +26,7 @@ import org.apache.plc4x.java.api.messages.PlcReadResponse;
 public class Plc4xReadClient {
 
     public static void main(String[] args) throws Exception {
-        try (final PlcConnection connection = new PlcDriverManager().getConnection("plc4x://localhost?remote-connection-string=simulated%3A%2F%2Flocalhost")) {
+        try (final PlcConnection connection = new DefaultPlcDriverManager().getConnection("plc4x://localhost?remote-connection-string=simulated%3A%2F%2Flocalhost")) {
             final PlcReadRequest.Builder requestBuilder = connection.readRequestBuilder();
             requestBuilder.addTagAddress("test-BOOL", "RANDOM/foo:BOOL");
             requestBuilder.addTagAddress("test-BYTE", "RANDOM/foo:BYTE");
diff --git a/plc4j/drivers/plc4x/src/test/java/org/apache/plc4x/java/plc4x/Plc4xWriteClient.java b/plc4j/drivers/plc4x/src/test/java/org/apache/plc4x/java/plc4x/Plc4xWriteClient.java
index 061cc98eb7..84f473c5cb 100644
--- a/plc4j/drivers/plc4x/src/test/java/org/apache/plc4x/java/plc4x/Plc4xWriteClient.java
+++ b/plc4j/drivers/plc4x/src/test/java/org/apache/plc4x/java/plc4x/Plc4xWriteClient.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.plc4x;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcWriteRequest;
 import org.apache.plc4x.java.api.messages.PlcWriteResponse;
@@ -28,7 +28,7 @@ import java.math.BigInteger;
 public class Plc4xWriteClient {
 
     public static void main(String[] args) throws Exception {
-        try (final PlcConnection connection = new PlcDriverManager().getConnection("plc4x://localhost?remote-connection-string=simulated%3A%2F%2Flocalhost")) {
+        try (final PlcConnection connection = new DefaultPlcDriverManager().getConnection("plc4x://localhost?remote-connection-string=simulated%3A%2F%2Flocalhost")) {
             final PlcWriteRequest.Builder requestBuilder = connection.writeRequestBuilder();
             requestBuilder.addTagAddress("test-BOOL", "STDOUT/foo:BOOL", true);
             requestBuilder.addTagAddress("test-BYTE", "STDOUT/foo:BYTE", new boolean[] {true, true, false, true, false, true, false, true});
diff --git a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoDiscoveryTest.java b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoDiscoveryTest.java
index b5b2967d4a..c0f25a6e0c 100644
--- a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoDiscoveryTest.java
+++ b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoDiscoveryTest.java
@@ -18,14 +18,14 @@
  */
 package org.apache.plc4x.java.profinet;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcDriver;
 import org.apache.plc4x.java.api.messages.PlcDiscoveryResponse;
 
 public class ManualProfinetIoDiscoveryTest {
 
     public static void main(String[] args) throws Exception {
-        final PlcDriver profinetDriver = new PlcDriverManager().getDriver("profinet");
+        final PlcDriver profinetDriver = new DefaultPlcDriverManager().getDriver("profinet");
         final PlcDiscoveryResponse plcDiscoveryResponse = profinetDriver.discoveryRequestBuilder().build().execute().get();
         System.out.println(plcDiscoveryResponse);
     }
diff --git a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
index c68927164f..8d3fe5b07b 100644
--- a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
+++ b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.profinet;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
@@ -26,7 +26,7 @@ import org.apache.plc4x.java.api.messages.PlcReadResponse;
 public class ManualProfinetIoTest {
 
     public static void main(String[] args) throws Exception {
-        final PlcConnection connection = new PlcDriverManager().getConnection("profinet://192.168.24.31");
+        final PlcConnection connection = new DefaultPlcDriverManager().getConnection("profinet://192.168.24.31");
         final PlcReadRequest readRequest = connection.readRequestBuilder().addTagAddress("test", "").build();
         final PlcReadResponse plcReadResponse = readRequest.execute().get();
         System.out.println(plcReadResponse);
diff --git a/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/DatatypesTest.java b/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/DatatypesTest.java
index 08f210f615..2eff79c283 100644
--- a/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/DatatypesTest.java
+++ b/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/DatatypesTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.s7.readwrite;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
@@ -26,7 +26,7 @@ import org.apache.plc4x.java.api.messages.PlcReadResponse;
 public class DatatypesTest {
 
     public static void main(String[] args) throws Exception {
-        try (PlcConnection connection = new PlcDriverManager().getConnection("s7://192.168.23.30")) {
+        try (PlcConnection connection = new DefaultPlcDriverManager().getConnection("s7://192.168.23.30")) {
             final PlcReadRequest.Builder builder = connection.readRequestBuilder();
             builder.addTagAddress("bool-value-1", "%DB2:0.0:BOOL"); // true
             builder.addTagAddress("bool-value-2", "%DB2:2.1:BOOL"); // false
diff --git a/plc4j/tools/connection-pool/pom.xml b/plc4j/examples/hello-ads-telemetry/pom.xml
similarity index 55%
rename from plc4j/tools/connection-pool/pom.xml
rename to plc4j/examples/hello-ads-telemetry/pom.xml
index 41e7df2e2e..dd2c6ff967 100644
--- a/plc4j/tools/connection-pool/pom.xml
+++ b/plc4j/examples/hello-ads-telemetry/pom.xml
@@ -22,15 +22,18 @@
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
-    <groupId>org.apache.plc4x</groupId>
-    <artifactId>plc4j-tools</artifactId>
+    <groupId>org.apache.plc4x.examples</groupId>
+    <artifactId>plc4j-examples</artifactId>
     <version>0.11.0-SNAPSHOT</version>
   </parent>
 
-  <artifactId>plc4j-connection-pool</artifactId>
+  <artifactId>plc4j-examples-hello-ads-telemetry</artifactId>
+  <name>PLC4J: Examples: Hello-ADS telemetry</name>
+  <description>Hello world application using PLC4X to read ADS device telemetry.</description>
 
-  <name>PLC4J: Tools: Connection Pool</name>
-  <description>An implementation of a connection pool based on Apache Commons Pool.</description>
+  <properties>
+    <app.main.class>org.apache.plc4x.java.examples.helloads.telemetry.HelloAdsTelemetry</app.main.class>
+  </properties>
 
   <dependencies>
     <dependency>
@@ -40,13 +43,31 @@
     </dependency>
 
     <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-pool2</artifactId>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-lang3</artifactId>
+      <groupId>org.slf4j</groupId>
+      <artifactId>log4j-over-slf4j</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
     </dependency>
   </dependencies>
 
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <configuration>
+          <usedDependencies combine.children="append">
+            <usedDependency>org.slf4j:log4j-over-slf4j</usedDependency>
+          </usedDependencies>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
 </project>
\ No newline at end of file
diff --git a/plc4j/examples/hello-ads-telemetry/src/main/java/org/apache/plc4x/java/examples/helloads/telemetry/HelloAdsEtherCatTelemetry.java b/plc4j/examples/hello-ads-telemetry/src/main/java/org/apache/plc4x/java/examples/helloads/telemetry/HelloAdsEtherCatTelemetry.java
new file mode 100644
index 0000000000..f828486d3f
--- /dev/null
+++ b/plc4j/examples/hello-ads-telemetry/src/main/java/org/apache/plc4x/java/examples/helloads/telemetry/HelloAdsEtherCatTelemetry.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.examples.helloads.telemetry;
+
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.api.types.PlcValueType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+// Extracted from https://infosys.beckhoff.com/index.php?content=../content/1031/devicemanager/262982923.html
+
+enum EtherCatConstants {
+    DeviceType(0x10000000, PlcValueType.UDINT),
+    ManufacturerDeviceName(0x10080000, PlcValueType.STRING),
+    //HardwareVersion(0x10090000, PlcValueType.),
+    //SoftwareVersion(0x100A0000, PlcValueType.),
+    //IdentityObjectNum(0x10180000, PlcValueType.),
+    IdentityObjectVendorId(0x10180000, PlcValueType.UDINT),
+    IdentityObjectProductCode(0x10180000, PlcValueType.UDINT),
+    IdentityObjectRevisionNumber(0x10180000, PlcValueType.UDINT),
+    IdentityObjectSoftwareVersion(0x10180000, PlcValueType.UDINT),
+    //ConfigurationDataNum(0x80000000, PlcValueType.), // 0x8xxx0000 xxx = device index (starting with 0)
+    ConfigurationDataAddress(0x80000001, PlcValueType.UINT),
+    ConfigurationDataType(0x8000000, PlcValueType.STRING), // Not sure ...
+    ConfigurationDataName(0x8000000, PlcValueType.STRING),
+    ConfigurationDataDeviceType(0x8000000, PlcValueType.UDINT),
+    ConfigurationDataVendorId(0x8000000, PlcValueType.UDINT),
+    ConfigurationDataProductCode(0x8000000, PlcValueType.UDINT),
+    ConfigurationDataRevisionNumber(0x8000000, PlcValueType.UDINT),
+    ConfigurationDataSerialNumber(0x8000000, PlcValueType.UDINT),
+    ConfigurationDataMailboxOutSize(0x8000000, PlcValueType.UINT),
+    ConfigurationDataMailboxInSize(0x8000000, PlcValueType.UINT),
+    ConfigurationDataLinkStatus(0x8000000, PlcValueType.USINT),
+    ConfigurationDataLinkPreset(0x8000000, PlcValueType.USINT),
+    ConfigurationDataFlags(0x8000000, PlcValueType.UINT),
+//    StateMachine(0xA0000000, PlcValueType.),      // 0xAxxx0000 xxx = device index (starting with 0)
+//    ScanSlaves(0xF002000, PlcValueType.),
+    ConfiguredSlavesNum(0xF0200000, PlcValueType.USINT);
+//    FrameStatistics(0xF1200000, PlcValueType.);
+
+    final int typeNumber;
+    final PlcValueType plcValueType;
+    EtherCatConstants(int typeNumber, PlcValueType plcValueType) {
+        this.typeNumber = typeNumber;
+        this.plcValueType = plcValueType;
+    }
+}
+public class HelloAdsEtherCatTelemetry {
+
+    private static final Logger logger = LoggerFactory.getLogger(HelloAdsTelemetry.class);
+    public static void main(String[] args) {
+        if(args.length != 2) {
+            logger.error("Usage: HelloAdsTelemetry {ip-address of PLC} {local ip-address}");
+            System.exit(1);
+        }
+
+        String remoteIp = args[0];
+        String localIp = args[1];
+        // The AmsNetId of the PLC usually is {ip}.1.1 and that of the EtherCAT master is {ip}.3.1
+        // The port number equals the EtherCAT address. For the EtherCAT master, this port is 0xFFFF = 65535
+        try (PlcConnection connection = PlcDriverManager.getDefault().getConnectionManager().getConnection(String.format("ads:tcp://%s?targetAmsNetId=%s.3.1&targetAmsPort=65535&sourceAmsNetId=%s.1.1&sourceAmsPort=65534&load-symbol-and-data-type-tables=false", remoteIp, remoteIp, localIp))) {
+            int vendorId = connection.readRequestBuilder().addTagAddress("vendorId", "0x0000F302/0x10180001:UDINT").build().execute().get().getInteger("vendorId");
+            int productCode = connection.readRequestBuilder().addTagAddress("productCode", "0x0000F302/0x10180002:UDINT").build().execute().get().getInteger("productCode");
+            int revisionNumber = connection.readRequestBuilder().addTagAddress("revisionNumber", "0x0000F302/0x10180003:UDINT").build().execute().get().getInteger("revisionNumber");
+            int serialNumber = connection.readRequestBuilder().addTagAddress("serialNumber", "0x0000F302/0x10180004:UDINT").build().execute().get().getInteger("serialNumber");
+            logger.info("EtherCAT Master: Vendor Id: {}, Product Code: {}, Revision Number: {}, Serial Number {}", vendorId, productCode, revisionNumber, serialNumber);
+
+            // Load the number of EtherCAT slaves:
+            int numSlaves = connection.readRequestBuilder().addTagAddress("numberOfSlaves", "0x0000F302/0xF0200000:USINT").build().execute().get().getInteger("numberOfSlaves");
+
+            // Load the number of slaves and their etherCatAddresses
+            // NOTE: We need to do this without using multi-item-requests as it seems that this part of the system doesn't support this.
+            Map<Integer, Integer> etherCatAddresses = new HashMap<>();
+            for(int i = 1; i < numSlaves; i++) {
+                String name = "slave-" + i;
+                String address = String.format("0x0000F302/0xF020%04X:UINT", i);
+                PlcReadResponse plcReadResponse = connection.readRequestBuilder().addTagAddress(name, address).build().execute().get();
+                if (plcReadResponse.getResponseCode(name) == PlcResponseCode.OK) {
+                    int etherCatAddress = plcReadResponse.getInteger(name);
+                    logger.info("Slave {} has EtherCAT address {}", i, etherCatAddress);
+                    etherCatAddresses.put(i, etherCatAddress);
+
+                }
+            }
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/plc4j/examples/hello-ads-telemetry/src/main/java/org/apache/plc4x/java/examples/helloads/telemetry/HelloAdsTelemetry.java b/plc4j/examples/hello-ads-telemetry/src/main/java/org/apache/plc4x/java/examples/helloads/telemetry/HelloAdsTelemetry.java
new file mode 100644
index 0000000000..ef4eb86b7f
--- /dev/null
+++ b/plc4j/examples/hello-ads-telemetry/src/main/java/org/apache/plc4x/java/examples/helloads/telemetry/HelloAdsTelemetry.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.examples.helloads.telemetry;
+
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+// Extracted from https://infosys.beckhoff.com/index.php?content=../content/1031/devicemanager/262982923.html
+
+enum Module {
+    NIC(0x00000002),
+    Time(0x00000003),
+    UserManagement(0x00000004),
+    RAS(0x00000005),
+    FTP(0x00000006),
+    SMB(0x00000007),
+    TwinCat(0x00000008),
+    Software(0x0000000A),
+    COU(0x0000000B),
+    Memory(0x0000000C),
+    FirewallWinCE(0x0000000E),
+    FileSystemObject(0x00000010),
+    DisplayDevice(0x00000013),
+    EWF(0x00000014),
+    FBWF(0x00000015),
+    OS(0x00000018),
+    RAID(0x00000019),
+    Fan(0x0000001B),
+    Mainboard(0x0000001C),
+    DiskManagement(0x0000001D),
+    UPS(0x0000001E),
+    PhysicalDrive(0x0000001F),
+    MassStorageDrive(0x00000020),
+    UnifiedWriteFilter(0x00000021),
+    IO(0x00000022),
+    Misc(0x00000100);
+
+    final int typeNumber;
+    Module(int typeNumber) {
+        this.typeNumber = typeNumber;
+    }
+
+}
+public class HelloAdsTelemetry {
+
+    private static final Logger logger = LoggerFactory.getLogger(HelloAdsTelemetry.class);
+    public static void main(String[] args) {
+        if(args.length != 2) {
+            logger.error("Usage: HelloAdsTelemetry {ip-address of PLC} {local ip-address}");
+            System.exit(1);
+        }
+
+        String remoteIp = args[0];
+        String localIp = args[1];
+        try (PlcConnection connection = PlcDriverManager.getDefault().getConnectionManager().getConnection(String.format("ads:tcp://%s?targetAmsNetId=%s.1.1&targetAmsPort=10000&sourceAmsNetId=%s.1.1&sourceAmsPort=65534&load-symbol-and-data-type-tables=false", remoteIp, remoteIp, localIp))) {
+            // Load the number of modules:
+            int numModules = connection.readRequestBuilder().addTagAddress("numberOfModules", "0x0000F302/0xF0200000:UINT").build().execute().get().getInteger("numberOfModules");
+
+            // Load the mdp type and index for each module
+            // NOTE: We need to do this without using multi-item-requests as it seems that this part of the system doesn't support this.
+            Map<Integer, Integer> moduleTypeIdMap = new HashMap<>();
+            for(int i = 1; i < numModules; i++) {
+                String name = "module-" + i;
+                String address = String.format("0x0000F302/0xF020%04X:UDINT", i);
+                PlcReadResponse plcReadResponse = connection.readRequestBuilder().addTagAddress(name, address).build().execute().get();
+                if (plcReadResponse.getResponseCode(name) == PlcResponseCode.OK) {
+                    int value = plcReadResponse.getInteger(name);
+                    int mdpType = ((value & 0xFFFF0000) >> 16);
+                    int mdpId = value & 0x0000FFFF;
+                    logger.info("Module {} has mdp type {} and mdp id {}", i, mdpType, mdpId);
+                    moduleTypeIdMap.put(mdpType, mdpId);
+                }
+            }
+
+            // Read the ADS Version information.
+            if(moduleTypeIdMap.containsKey(Module.TwinCat.typeNumber)) {
+                Integer mdpId = moduleTypeIdMap.get(Module.TwinCat.typeNumber);
+                int addrAdsTypeMain = (mdpId << 20) | 0x80010001;
+                int addrAdsTypeMinor = (mdpId << 20) | 0x80010002;
+                int addrAdsTypeBuild = (mdpId << 20) | 0x80010003;
+                int twinCatMainVersion = connection.readRequestBuilder().addTagAddress("value", String.format("0x0000F302/0x%8X:UINT", addrAdsTypeMain)).build().execute().get().getInteger("value");
+                int twinCatMinorVersion = connection.readRequestBuilder().addTagAddress("value", String.format("0x0000F302/0x%8X:UINT", addrAdsTypeMinor)).build().execute().get().getInteger("value");
+                int twinCatBuildVersion = connection.readRequestBuilder().addTagAddress("value", String.format("0x0000F302/0x%8X:UINT", addrAdsTypeBuild)).build().execute().get().getInteger("value");
+                logger.info("TwinCat Version: {}.{}.{}", twinCatMainVersion, twinCatMinorVersion, twinCatBuildVersion);
+            }
+            // Read the CPU Frequency and Utilization.
+            if(moduleTypeIdMap.containsKey(Module.COU.typeNumber)) {
+                Integer mdpId = moduleTypeIdMap.get(Module.COU.typeNumber);
+                int addrCpuFrequency = (mdpId << 20) | 0x80010001;
+                int addrCpuUsage = (mdpId << 20) | 0x80010002;
+                int cpuFrequency = connection.readRequestBuilder().addTagAddress("value", String.format("0x0000F302/0x%8X:UDINT", addrCpuFrequency)).build().execute().get().getInteger("value");
+                int cpuUsage = connection.readRequestBuilder().addTagAddress("value", String.format("0x0000F302/0x%8X:UINT", addrCpuUsage)).build().execute().get().getInteger("value");
+                logger.info("CPU: Frequency: {}MHz Usage: {}%", cpuFrequency, cpuUsage);
+            }
+            // Read the Memory usage.
+            if(moduleTypeIdMap.containsKey(Module.Memory.typeNumber)) {
+                Integer mdpId = moduleTypeIdMap.get(Module.Memory.typeNumber);
+                int addrMemoryAllocated = (mdpId << 20) | 0x80010001;
+                int addrMemoryAvailable = (mdpId << 20) | 0x80010002;
+                int memoryAllocated = connection.readRequestBuilder().addTagAddress("value", String.format("0x0000F302/0x%8X:UDINT", addrMemoryAllocated)).build().execute().get().getInteger("value");
+                int memoryAvailable = connection.readRequestBuilder().addTagAddress("value", String.format("0x0000F302/0x%8X:UDINT", addrMemoryAvailable)).build().execute().get().getInteger("value");
+                logger.info("Memory: Allocated: {}MB, Available: {}MB, Usage {}%", memoryAllocated / (1024 * 1024), memoryAvailable / (1024 * 1024), ((float) 100 / memoryAllocated) * memoryAvailable);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/plc4j/tools/connection-pool/src/test/resources/logback-test.xml b/plc4j/examples/hello-ads-telemetry/src/main/resources/logback.xml
similarity index 97%
rename from plc4j/tools/connection-pool/src/test/resources/logback-test.xml
rename to plc4j/examples/hello-ads-telemetry/src/main/resources/logback.xml
index 33ae65561c..eee180ec73 100644
--- a/plc4j/tools/connection-pool/src/test/resources/logback-test.xml
+++ b/plc4j/examples/hello-ads-telemetry/src/main/resources/logback.xml
@@ -27,7 +27,7 @@
     </encoder>
   </appender>
 
-  <root level="error">
+  <root level="info">
     <appender-ref ref="STDOUT" />
   </root>
 
diff --git a/plc4j/examples/hello-cloud-azure/src/main/java/org/apache/plc4x/java/examples/cloud/azure/S7PlcToAzureIoTHubSample.java b/plc4j/examples/hello-cloud-azure/src/main/java/org/apache/plc4x/java/examples/cloud/azure/S7PlcToAzureIoTHubSample.java
index ed118a5933..1c97a84685 100644
--- a/plc4j/examples/hello-cloud-azure/src/main/java/org/apache/plc4x/java/examples/cloud/azure/S7PlcToAzureIoTHubSample.java
+++ b/plc4j/examples/hello-cloud-azure/src/main/java/org/apache/plc4x/java/examples/cloud/azure/S7PlcToAzureIoTHubSample.java
@@ -21,8 +21,8 @@ package org.apache.plc4x.java.examples.cloud.azure;
 import com.microsoft.azure.sdk.iot.device.DeviceClient;
 import com.microsoft.azure.sdk.iot.device.IotHubClientProtocol;
 import com.microsoft.azure.sdk.iot.device.Message;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
 import org.slf4j.Logger;
@@ -54,7 +54,7 @@ public class S7PlcToAzureIoTHubSample {
 
         // Open both a connection to the remote PLC and the cloud service.
         DeviceClient client = new DeviceClient(options.getIotHubConnectionString(), IotHubClientProtocol.MQTT);
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection(options.getPlc4xConnectionString())) {
+        try (PlcConnection plcConnection = PlcDriverManager.getDefault().getConnectionManager().getConnection(options.getPlc4xConnectionString())) {
 
             LOGGER.info("Connected");
 
diff --git a/plc4j/examples/hello-cloud-google/src/main/java/org/apache/plc4x/java/examples/cloud/google/S7PlcToGoogleIoTCoreSample.java b/plc4j/examples/hello-cloud-google/src/main/java/org/apache/plc4x/java/examples/cloud/google/S7PlcToGoogleIoTCoreSample.java
index 7bbf5c760e..2f7943ef17 100644
--- a/plc4j/examples/hello-cloud-google/src/main/java/org/apache/plc4x/java/examples/cloud/google/S7PlcToGoogleIoTCoreSample.java
+++ b/plc4j/examples/hello-cloud-google/src/main/java/org/apache/plc4x/java/examples/cloud/google/S7PlcToGoogleIoTCoreSample.java
@@ -21,8 +21,8 @@ package org.apache.plc4x.java.examples.cloud.google;
 import io.jsonwebtoken.JwtBuilder;
 import io.jsonwebtoken.Jwts;
 import io.jsonwebtoken.SignatureAlgorithm;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
 import org.eclipse.paho.client.mqttv3.*;
@@ -236,7 +236,7 @@ public class S7PlcToGoogleIoTCoreSample {
 
         // Connect to Plc
         logger.info("Connecting to Plc");
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection("s7://10.10.64.20/1/1")) {
+        try (PlcConnection plcConnection = PlcDriverManager.getDefault().getConnectionManager().getConnection("s7://10.10.64.20/1/1")) {
             logger.info("Connected");
 
             PlcReadRequest readRequest = plcConnection.readRequestBuilder().addTagAddress("outputs", "OUTPUTS/0").build();
diff --git a/plc4j/examples/hello-connectivity-mqtt/src/main/java/org/apache/plc4x/java/examples/connectivity/mqtt/MqttConnector.java b/plc4j/examples/hello-connectivity-mqtt/src/main/java/org/apache/plc4x/java/examples/connectivity/mqtt/MqttConnector.java
index 5a92e47e7c..54c2b203c4 100644
--- a/plc4j/examples/hello-connectivity-mqtt/src/main/java/org/apache/plc4x/java/examples/connectivity/mqtt/MqttConnector.java
+++ b/plc4j/examples/hello-connectivity-mqtt/src/main/java/org/apache/plc4x/java/examples/connectivity/mqtt/MqttConnector.java
@@ -31,8 +31,8 @@ import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
 import io.reactivex.Flowable;
 import io.reactivex.Single;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.exceptions.PlcException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
@@ -83,7 +83,7 @@ public class MqttConnector {
         final Single<Mqtt3ConnAck> connAckSingle = client.connect().timeout(10, TimeUnit.SECONDS);
 
         // Connect to the PLC.
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection(config.getPlcConfig().getConnection())) {
+        try (PlcConnection plcConnection = PlcDriverManager.getDefault().getConnectionManager().getConnection(config.getPlcConfig().getConnection())) {
 
             // Check if this connection support reading of data.
             if (!plcConnection.getMetadata().canRead()) {
diff --git a/plc4j/examples/hello-discovery/src/main/java/org/apache/plc4x/java/examples/hellodiscovery/HelloDiscovery.java b/plc4j/examples/hello-discovery/src/main/java/org/apache/plc4x/java/examples/hellodiscovery/HelloDiscovery.java
index 33fdcf947e..0c89513883 100644
--- a/plc4j/examples/hello-discovery/src/main/java/org/apache/plc4x/java/examples/hellodiscovery/HelloDiscovery.java
+++ b/plc4j/examples/hello-discovery/src/main/java/org/apache/plc4x/java/examples/hellodiscovery/HelloDiscovery.java
@@ -18,8 +18,8 @@
  */
 package org.apache.plc4x.java.examples.hellodiscovery;
 
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcDriver;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.messages.*;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.slf4j.Logger;
@@ -44,7 +44,7 @@ public class HelloDiscovery {
             System.exit(1);
         }
 
-        PlcDriverManager plcDriverManager = new PlcDriverManager();
+        PlcDriverManager plcDriverManager = PlcDriverManager.getDefault();
         Set<String> driverCodes = plcDriverManager.listDrivers();
         for (String driverCode : driverCodes) {
             logger.info("Executing Discovery for Driver: {}", driverCode);
diff --git a/plc4j/examples/hello-influx-data-collection/src/main/java/org/apache/plc4x/java/examples/helloinflux/HelloInflux.java b/plc4j/examples/hello-influx-data-collection/src/main/java/org/apache/plc4x/java/examples/helloinflux/HelloInflux.java
index 989e7180f2..d89e4d35ea 100644
--- a/plc4j/examples/hello-influx-data-collection/src/main/java/org/apache/plc4x/java/examples/helloinflux/HelloInflux.java
+++ b/plc4j/examples/hello-influx-data-collection/src/main/java/org/apache/plc4x/java/examples/helloinflux/HelloInflux.java
@@ -26,7 +26,7 @@ import com.influxdb.client.write.Point;
 import org.apache.commons.configuration2.Configuration;
 import org.apache.commons.configuration2.builder.fluent.Configurations;
 import org.apache.commons.configuration2.ex.ConfigurationException;
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
@@ -141,7 +141,7 @@ public class HelloInflux {
 
     private PlcConnection connectToPlc() throws PlcException {
         final PlcConnection connection =
-            new PlcDriverManager().getConnection(configuration.getString("plc.connectionString"));
+            new DefaultPlcDriverManager().getConnection(configuration.getString("plc.connectionString"));
         connection.connect();
         return connection;
     }
diff --git a/plc4j/examples/hello-nats/src/main/java/org/apache/plc4x/java/examples/hellonats/HelloNats.java b/plc4j/examples/hello-nats/src/main/java/org/apache/plc4x/java/examples/hellonats/HelloNats.java
index 303dbee3c6..07af104397 100644
--- a/plc4j/examples/hello-nats/src/main/java/org/apache/plc4x/java/examples/hellonats/HelloNats.java
+++ b/plc4j/examples/hello-nats/src/main/java/org/apache/plc4x/java/examples/hellonats/HelloNats.java
@@ -23,7 +23,6 @@ import io.nats.client.api.StorageType;
 import io.nats.client.api.StreamConfiguration;
 import io.nats.client.api.StreamInfo;
 import io.nats.client.support.JsonUtils;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
diff --git a/plc4j/examples/hello-opm/pom.xml b/plc4j/examples/hello-opm/pom.xml
index e1f6c8f19f..0b68575f5e 100644
--- a/plc4j/examples/hello-opm/pom.xml
+++ b/plc4j/examples/hello-opm/pom.xml
@@ -43,7 +43,7 @@
     </dependency>
     <dependency>
       <groupId>org.apache.plc4x</groupId>
-      <artifactId>plc4j-connection-pool</artifactId>
+      <artifactId>plc4j-connection-cache</artifactId>
       <version>0.11.0-SNAPSHOT</version>
     </dependency>
 
diff --git a/plc4j/examples/hello-opm/src/main/java/org/apache/plc4x/java/examples/helloopm/HelloOpm.java b/plc4j/examples/hello-opm/src/main/java/org/apache/plc4x/java/examples/helloopm/HelloOpm.java
index c3bc093492..43333d010d 100644
--- a/plc4j/examples/hello-opm/src/main/java/org/apache/plc4x/java/examples/helloopm/HelloOpm.java
+++ b/plc4j/examples/hello-opm/src/main/java/org/apache/plc4x/java/examples/helloopm/HelloOpm.java
@@ -22,11 +22,11 @@ import org.apache.plc4x.java.opm.OPMException;
 import org.apache.plc4x.java.opm.PlcEntity;
 import org.apache.plc4x.java.opm.PlcEntityManager;
 import org.apache.plc4x.java.opm.PlcTag;
-import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 
 /**
  * This Example shows how to use OPM from plc4j via the @{@link PlcEntityManager}.
- * A @{@link PooledPlcDriverManager} is used to optimize the acces and to allow for automatic reconnection.
+ * A @{@link CachedPlcConnectionManager} is used to optimize the acces and to allow for automatic reconnection.
  *
  * The {@link PlcEntityManager} is similar to JPAs EntityManager.
  * The "connected" Entity (shootCounter) can be kept and passed around and stays connected in the sense that all calls
@@ -53,7 +53,7 @@ public class HelloOpm {
     }
 
     public HelloOpm() {
-        entityManager = new PlcEntityManager(new PooledPlcDriverManager());
+        entityManager = new PlcEntityManager(CachedPlcConnectionManager.getBuilder().build());
     }
 
     /**
diff --git a/plc4j/examples/hello-webservice/src/main/java/org/apache/plc4x/java/examples/hellowebservice/HelloWebservice.java b/plc4j/examples/hello-webservice/src/main/java/org/apache/plc4x/java/examples/hellowebservice/HelloWebservice.java
index 2d9eeccda9..4ed3f4ba70 100644
--- a/plc4j/examples/hello-webservice/src/main/java/org/apache/plc4x/java/examples/hellowebservice/HelloWebservice.java
+++ b/plc4j/examples/hello-webservice/src/main/java/org/apache/plc4x/java/examples/hellowebservice/HelloWebservice.java
@@ -27,8 +27,8 @@ import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionEvent;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse;
@@ -56,7 +56,7 @@ public class HelloWebservice {
 
     public void run() throws Exception {
         // Establish a connection to the plc.
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection(options.getConnectionString())) {
+        try (PlcConnection plcConnection = PlcDriverManager.getDefault().getConnectionManager().getConnection(options.getConnectionString())) {
 
             // Check if this connection support subscriptions.
             if (!plcConnection.getMetadata().canSubscribe()) {
diff --git a/plc4j/examples/hello-world-kotlin/src/main/kotlin/org/apache/plc4x/java/examples/hellokotlin/ReadModbusPal.kt b/plc4j/examples/hello-world-kotlin/src/main/kotlin/org/apache/plc4x/java/examples/hellokotlin/ReadModbusPal.kt
index 4438308a89..7df03417cb 100644
--- a/plc4j/examples/hello-world-kotlin/src/main/kotlin/org/apache/plc4x/java/examples/hellokotlin/ReadModbusPal.kt
+++ b/plc4j/examples/hello-world-kotlin/src/main/kotlin/org/apache/plc4x/java/examples/hellokotlin/ReadModbusPal.kt
@@ -18,13 +18,13 @@
  */
 package org.apache.plc4x.java.examples.hellokotlin;
 
-import org.apache.plc4x.java.PlcDriverManager
+import org.apache.plc4x.java.DefaultPlcDriverManager
 import org.apache.plc4x.java.api.types.PlcResponseCode
 import java.util.concurrent.TimeUnit
 import kotlin.system.exitProcess
 
 fun main() {
-    PlcDriverManager()
+    DefaultPlcDriverManager()
         .getConnection("modbus-tcp://localhost:502")
         .use { conn ->
             if (!conn.metadata.canRead()) {
diff --git a/plc4j/examples/hello-world-plc4x-discover-and-browse/src/main/java/org/apache/plc4x/java/examples/helloplc4x/discoverandbrowse/HelloPlc4xDiscoverAndBrowse.java b/plc4j/examples/hello-world-plc4x-discover-and-browse/src/main/java/org/apache/plc4x/java/examples/helloplc4x/discoverandbrowse/HelloPlc4xDiscoverAndBrowse.java
index 1bad000c88..11d4b5c68d 100644
--- a/plc4j/examples/hello-world-plc4x-discover-and-browse/src/main/java/org/apache/plc4x/java/examples/helloplc4x/discoverandbrowse/HelloPlc4xDiscoverAndBrowse.java
+++ b/plc4j/examples/hello-world-plc4x-discover-and-browse/src/main/java/org/apache/plc4x/java/examples/helloplc4x/discoverandbrowse/HelloPlc4xDiscoverAndBrowse.java
@@ -19,9 +19,10 @@
 package org.apache.plc4x.java.examples.helloplc4x.discoverandbrowse;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.PlcDriver;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.messages.PlcBrowseItem;
 import org.apache.plc4x.java.api.messages.PlcBrowseRequest;
 import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
@@ -34,7 +35,8 @@ public class HelloPlc4xDiscoverAndBrowse {
 
     public static void main(String[] args) throws Exception {
         // Iterate over all installed drivers and execute their browse functionality (If they support it)
-        PlcDriverManager driverManager = new PlcDriverManager();
+        PlcDriverManager driverManager = PlcDriverManager.getDefault();
+        PlcConnectionManager connectionManager = driverManager.getConnectionManager();
         for (String protocolCode : driverManager.listDrivers()) {
             PlcDriver driver = driverManager.getDriver(protocolCode);
             if (driver.getMetadata().canDiscover()) {
@@ -44,7 +46,7 @@ public class HelloPlc4xDiscoverAndBrowse {
 
                 discoveryRequest.executeWithHandler(discoveryItem -> {
                     logger.info(" - Found device with connection-url {}", discoveryItem.getConnectionUrl());
-                    try (PlcConnection connection = driverManager.getConnection(discoveryItem.getConnectionUrl())) {
+                    try (PlcConnection connection = connectionManager.getConnection(discoveryItem.getConnectionUrl())) {
                         if (connection.getMetadata().canBrowse()) {
                             PlcBrowseRequest browseRequest = connection.browseRequestBuilder().build();
                             browseRequest.execute().whenComplete((browseResponse, throwable) -> {
diff --git a/plc4j/examples/hello-world-plc4x-read/src/main/java/org/apache/plc4x/java/examples/helloplc4x/read/HelloPlc4xRead.java b/plc4j/examples/hello-world-plc4x-read/src/main/java/org/apache/plc4x/java/examples/helloplc4x/read/HelloPlc4xRead.java
index f0a345a570..922cf3acef 100644
--- a/plc4j/examples/hello-world-plc4x-read/src/main/java/org/apache/plc4x/java/examples/helloplc4x/read/HelloPlc4xRead.java
+++ b/plc4j/examples/hello-world-plc4x-read/src/main/java/org/apache/plc4x/java/examples/helloplc4x/read/HelloPlc4xRead.java
@@ -18,8 +18,8 @@
  */
 package org.apache.plc4x.java.examples.helloplc4x.read;
 
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
@@ -46,7 +46,7 @@ public class HelloPlc4xRead {
         }
 
         // Establish a connection to the plc using the url provided as first argument
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection(options.getConnectionString())) {
+        try (PlcConnection plcConnection = PlcDriverManager.getDefault().getConnectionManager().getConnection(options.getConnectionString())) {
 
             // Check if this connection support reading of data.
             if (!plcConnection.getMetadata().canRead()) {
diff --git a/plc4j/examples/hello-world-plc4x-subscribe/src/main/java/org/apache/plc4x/java/examples/helloplc4x/subscribe/HelloPlc4xSubscription.java b/plc4j/examples/hello-world-plc4x-subscribe/src/main/java/org/apache/plc4x/java/examples/helloplc4x/subscribe/HelloPlc4xSubscription.java
index 33eca3cb6c..b6bb81feed 100644
--- a/plc4j/examples/hello-world-plc4x-subscribe/src/main/java/org/apache/plc4x/java/examples/helloplc4x/subscribe/HelloPlc4xSubscription.java
+++ b/plc4j/examples/hello-world-plc4x-subscribe/src/main/java/org/apache/plc4x/java/examples/helloplc4x/subscribe/HelloPlc4xSubscription.java
@@ -18,8 +18,8 @@
  */
 package org.apache.plc4x.java.examples.helloplc4x.subscribe;
 
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionEvent;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse;
@@ -43,7 +43,7 @@ public class HelloPlc4xSubscription {
 
     public void run() throws Exception {
         // Establish a connection to the plc.
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection(options.getConnectionString())) {
+        try (PlcConnection plcConnection = PlcDriverManager.getDefault().getConnectionManager().getConnection(options.getConnectionString())) {
 
             // Check if this connection support subscriptions.
             if (!plcConnection.getMetadata().canSubscribe()) {
diff --git a/plc4j/examples/hello-world-plc4x-write/src/main/java/org/apache/plc4x/java/examples/helloplc4x/write/HelloPlc4xWrite.java b/plc4j/examples/hello-world-plc4x-write/src/main/java/org/apache/plc4x/java/examples/helloplc4x/write/HelloPlc4xWrite.java
index b885039563..8f743f1424 100644
--- a/plc4j/examples/hello-world-plc4x-write/src/main/java/org/apache/plc4x/java/examples/helloplc4x/write/HelloPlc4xWrite.java
+++ b/plc4j/examples/hello-world-plc4x-write/src/main/java/org/apache/plc4x/java/examples/helloplc4x/write/HelloPlc4xWrite.java
@@ -18,8 +18,8 @@
  */
 package org.apache.plc4x.java.examples.helloplc4x.write;
 
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.messages.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,7 +36,7 @@ public class HelloPlc4xWrite {
 
     public void run() throws Exception {
         // Establish a connection to the plc.
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection(options.getConnectionString())) {
+        try (PlcConnection plcConnection = PlcDriverManager.getDefault().getConnectionManager().getConnection(options.getConnectionString())) {
 
             // Check if this connection support subscriptions.
             if (!plcConnection.getMetadata().canWrite()) {
diff --git a/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/EventSubscription.java b/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/EventSubscription.java
index 30b5f47c68..242bf4704f 100644
--- a/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/EventSubscription.java
+++ b/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/EventSubscription.java
@@ -20,7 +20,7 @@ package org.apache.plc4x.examples.plc4j.s7event;
 
 import java.util.Map;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
 import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse;
@@ -42,7 +42,7 @@ public class EventSubscription {
      * @param args the command line arguments
      */
     public static void main(String[] args) throws Exception {
-        try (PlcConnection connection = new PlcDriverManager().getConnection("s7://192.168.1.51?remote-rack=0&remote-slot=3&controller-type=S7_400")) {
+        try (PlcConnection connection = new DefaultPlcDriverManager().getConnection("s7://192.168.1.51?remote-rack=0&remote-slot=3&controller-type=S7_400")) {
             final PlcSubscriptionRequest.Builder subscription = connection.subscriptionRequestBuilder();
 
             subscription.addEventTagAddress("myMODE", "MODE");
diff --git a/plc4j/examples/poll-loop/src/main/java/org/apache/plc4x/java/examples/pollloop/PollLoop.java b/plc4j/examples/poll-loop/src/main/java/org/apache/plc4x/java/examples/pollloop/PollLoop.java
index a65e379901..1a1bdb02dd 100644
--- a/plc4j/examples/poll-loop/src/main/java/org/apache/plc4x/java/examples/pollloop/PollLoop.java
+++ b/plc4j/examples/poll-loop/src/main/java/org/apache/plc4x/java/examples/pollloop/PollLoop.java
@@ -26,8 +26,9 @@ import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import org.apache.plc4x.java.PlcDriverManager;
+
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
@@ -157,7 +158,7 @@ public class PollLoop {
             }
 
             try {
-                plcConnection = new PlcDriverManager().getConnection(connectionString);
+                plcConnection = PlcDriverManager.getDefault().getConnectionManager().getConnection(connectionString);
                 // in osgi/karaf uses this instead
 //                switch (plcType) {
 //                    case PLC4JTYPE_SIEMENS:
diff --git a/plc4j/examples/pom.xml b/plc4j/examples/pom.xml
index 2447ca392d..61dc602d36 100644
--- a/plc4j/examples/pom.xml
+++ b/plc4j/examples/pom.xml
@@ -39,6 +39,7 @@
   </properties>
 
   <modules>
+    <module>hello-ads-telemetry</module>
     <module>hello-cloud-azure</module>
     <module>hello-cloud-google</module>
     <module>hello-discovery</module>
diff --git a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/Plc4xSinkTask.java b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/Plc4xSinkTask.java
index 984fe213ab..956c59b9d0 100644
--- a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/Plc4xSinkTask.java
+++ b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/Plc4xSinkTask.java
@@ -26,11 +26,11 @@ import org.apache.kafka.connect.transforms.Transformation;
 import org.apache.kafka.connect.sink.SinkRecord;
 import org.apache.kafka.connect.sink.SinkTask;
 import org.apache.kafka.connect.errors.RetriableException;
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcWriteRequest;
-import org.apache.plc4x.java.utils.connectionpool2.PooledDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.apache.plc4x.kafka.config.Constants;
 import org.apache.plc4x.kafka.util.VersionUtil;
 
@@ -109,7 +109,7 @@ public class Plc4xSinkTask extends SinkTask {
         return VersionUtil.getVersion();
     }
 
-    private PlcDriverManager driverManager;
+    private PlcConnectionManager connectionManager;
     private Transformation<SinkRecord> transformation;
     private String plc4xConnectionString;
     private String plc4xTopic;
@@ -148,7 +148,7 @@ public class Plc4xSinkTask extends SinkTask {
         }
 
         log.info("Creating Pooled PLC4x driver manager");
-        driverManager = new PooledDriverManager();
+        connectionManager = CachedPlcConnectionManager.getBuilder().build();
     }
 
     @Override
@@ -166,7 +166,7 @@ public class Plc4xSinkTask extends SinkTask {
 
         PlcConnection connection = null;
         try {
-            connection = driverManager.getConnection(plc4xConnectionString);
+            connection = connectionManager.getConnection(plc4xConnectionString);
         } catch (PlcConnectionException e) {
             log.warn("Failed to Open Connection {}", plc4xConnectionString);
             remainingRetries--;
diff --git a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/Plc4xSourceTask.java b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/Plc4xSourceTask.java
index a37fe92311..d05ce8f4ca 100644
--- a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/Plc4xSourceTask.java
+++ b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/Plc4xSourceTask.java
@@ -25,8 +25,8 @@ import org.apache.kafka.connect.data.Date;
 import org.apache.kafka.connect.errors.ConnectException;
 import org.apache.kafka.connect.source.SourceRecord;
 import org.apache.kafka.connect.source.SourceTask;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.value.PlcValue;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.scraper.config.triggeredscraper.JobConfigurationTriggeredImplBuilder;
 import org.apache.plc4x.java.scraper.config.triggeredscraper.ScraperConfigurationTriggeredImpl;
 import org.apache.plc4x.java.scraper.config.triggeredscraper.ScraperConfigurationTriggeredImplBuilder;
@@ -34,7 +34,7 @@ import org.apache.plc4x.java.scraper.exception.ScraperException;
 import org.apache.plc4x.java.scraper.triggeredscraper.TriggeredScraperImpl;
 import org.apache.plc4x.java.scraper.triggeredscraper.triggerhandler.collector.TriggerCollector;
 import org.apache.plc4x.java.scraper.triggeredscraper.triggerhandler.collector.TriggerCollectorImpl;
-import org.apache.plc4x.java.utils.connectionpool2.PooledDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.apache.plc4x.kafka.config.Constants;
 import org.apache.plc4x.kafka.util.VersionUtil;
 import org.slf4j.Logger;
@@ -152,8 +152,8 @@ public class Plc4xSourceTask extends SourceTask {
         ScraperConfigurationTriggeredImpl scraperConfig = builder.build();
 
         try {
-            PlcDriverManager manager = new PooledDriverManager();
-            TriggerCollector triggerCollector = new TriggerCollectorImpl(manager);
+            PlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder().build();
+            TriggerCollector triggerCollector = new TriggerCollectorImpl(connectionManager);
             scraper = new TriggeredScraperImpl(scraperConfig, (jobName, sourceName, results) -> {
                 try {
                     Long timestamp = System.currentTimeMillis();
diff --git a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Sink.java b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Sink.java
index 6d08488c23..be7bb3f237 100644
--- a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Sink.java
+++ b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Sink.java
@@ -18,11 +18,10 @@
  */
 package org.apache.plc4x.kafka.config;
 
-import org.apache.plc4x.java.PlcDriverManager;
-
 import org.apache.kafka.common.config.AbstractConfig;
 import org.apache.kafka.common.config.ConfigDef;
 import org.apache.kafka.common.config.ConfigException;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 
 import java.util.Map;
 import java.util.ArrayList;
@@ -57,7 +56,7 @@ public class Sink extends AbstractConfig{
                 String.format("Connection string shouldn't be null for source %s ", this.name));
         }
         try {
-            new PlcDriverManager().getDriverForUrl(connectionString);
+            new DefaultPlcDriverManager().getDriverForUrl(connectionString);
         } catch (Exception e) {
             throw new ConfigException(
                 String.format("Connection String format is incorrect %s ", Constants.SINKS_CONFIG + "." + this.name + "." + Constants.CONNECTION_STRING_CONFIG + "=" + connectionString));
diff --git a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Source.java b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Source.java
index 6ffff8934f..cfe0003b97 100644
--- a/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Source.java
+++ b/plc4j/integrations/apache-kafka/src/main/java/org/apache/plc4x/kafka/config/Source.java
@@ -18,16 +18,13 @@
  */
 package org.apache.plc4x.kafka.config;
 
-import org.apache.plc4x.java.PlcDriverManager;
-
 import org.apache.kafka.common.config.AbstractConfig;
 import org.apache.kafka.common.config.ConfigDef;
-import org.apache.kafka.common.config.Config;
 import org.apache.kafka.common.config.ConfigException;
-import org.apache.kafka.common.config.ConfigValue;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+
 import java.util.Map;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 public class Source extends AbstractConfig{
@@ -73,7 +70,7 @@ public class Source extends AbstractConfig{
                 String.format("Connection string shouldn't be null for source %s ", this.name));
         }
         try {
-            new PlcDriverManager().getDriverForUrl(connectionString);
+            new DefaultPlcDriverManager().getDriverForUrl(connectionString);
         } catch (Exception e) {
             throw new ConfigException(
                 String.format("Connection String format is incorrect %s ", SOURCES_CONFIG + "." + this.name + "." + CONNECTION_STRING_CONFIG + "=" + connectionString));
diff --git a/plc4j/integrations/apache-nifi/nifi-plc4x-processors/pom.xml b/plc4j/integrations/apache-nifi/nifi-plc4x-processors/pom.xml
index ba76c962d6..0c6a391517 100644
--- a/plc4j/integrations/apache-nifi/nifi-plc4x-processors/pom.xml
+++ b/plc4j/integrations/apache-nifi/nifi-plc4x-processors/pom.xml
@@ -38,7 +38,7 @@
 		</dependency>
 		<dependency>
 			<groupId>org.apache.plc4x</groupId>
-			<artifactId>plc4j-connection-pool</artifactId>
+			<artifactId>plc4j-connection-cache</artifactId>
 			<version>0.11.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
diff --git a/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/BasePlc4xProcessor.java b/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/BasePlc4xProcessor.java
index 1bd86e1aa5..2a9b05cb8b 100644
--- a/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/BasePlc4xProcessor.java
+++ b/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/BasePlc4xProcessor.java
@@ -39,8 +39,9 @@ import org.apache.nifi.processor.ProcessContext;
 import org.apache.nifi.processor.ProcessorInitializationContext;
 import org.apache.nifi.processor.Relationship;
 import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
-import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 
 public abstract class BasePlc4xProcessor extends AbstractProcessor {
 
@@ -70,7 +71,7 @@ public abstract class BasePlc4xProcessor extends AbstractProcessor {
     protected Map<String, String> addressMap;
 
 
-    private final PooledPlcDriverManager driverManager = new PooledPlcDriverManager();
+    private final PlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder().build();
 
     @Override
     protected void init(final ProcessorInitializationContext context) {
@@ -174,8 +175,8 @@ public abstract class BasePlc4xProcessor extends AbstractProcessor {
         }
     }
 
-    protected PooledPlcDriverManager getDriverManager() {
-        return driverManager;
+    protected PlcConnectionManager getConnectionManager() {
+        return connectionManager;
     }
 
 }
diff --git a/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSinkProcessor.java b/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSinkProcessor.java
index 147ad2641a..970f693cea 100644
--- a/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSinkProcessor.java
+++ b/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSinkProcessor.java
@@ -49,7 +49,7 @@ public class Plc4xSinkProcessor extends BasePlc4xProcessor {
         }
 
         // Get an instance of a component able to write to a PLC.
-        try(PlcConnection connection = getDriverManager().getConnection(getConnectionString())) {
+        try(PlcConnection connection = getConnectionManager().getConnection(getConnectionString())) {
             if (!connection.getMetadata().canWrite()) {
                 throw new ProcessException("Writing not supported by connection");
             }
diff --git a/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSourceProcessor.java b/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSourceProcessor.java
index 6391f114cf..b10cd671b8 100644
--- a/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSourceProcessor.java
+++ b/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSourceProcessor.java
@@ -44,7 +44,7 @@ public class Plc4xSourceProcessor extends BasePlc4xProcessor {
     @Override
     public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
         // Get an instance of a component able to read from a PLC.
-        try(PlcConnection connection = getDriverManager().getConnection(getConnectionString())) {
+        try(PlcConnection connection = getConnectionManager().getConnection(getConnectionString())) {
 
             // Prepare the request.
             if (!connection.getMetadata().canRead()) {
diff --git a/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSourceRecordProcessor.java b/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSourceRecordProcessor.java
index fbfb16dc7e..6ac08491ba 100644
--- a/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSourceRecordProcessor.java
+++ b/plc4j/integrations/apache-nifi/nifi-plc4x-processors/src/main/java/org/apache/plc4x/nifi/Plc4xSourceRecordProcessor.java
@@ -136,7 +136,7 @@ public class Plc4xSourceRecordProcessor extends BasePlc4xProcessor {
 		final AtomicLong nrOfRows = new AtomicLong(0L);
 		final StopWatch executeTime = new StopWatch(true);
 
-		try (PlcConnection connection = getDriverManager().getConnection(getConnectionString())) {
+		try (PlcConnection connection = getConnectionManager().getConnection(getConnectionString())) {
 
 			String inputFileUUID = fileToProcess == null ? null : fileToProcess.getAttribute(CoreAttributes.UUID.key());
 			Map<String, String> inputFileAttrMap = fileToProcess == null ? null : fileToProcess.getAttributes();
diff --git a/plc4j/integrations/opcua-server/pom.xml b/plc4j/integrations/opcua-server/pom.xml
index b8e16e3497..ee1a38db54 100644
--- a/plc4j/integrations/opcua-server/pom.xml
+++ b/plc4j/integrations/opcua-server/pom.xml
@@ -101,7 +101,7 @@
 
     <dependency>
       <groupId>org.apache.plc4x</groupId>
-      <artifactId>plc4j-connection-pool</artifactId>
+      <artifactId>plc4j-connection-cache</artifactId>
       <version>0.11.0-SNAPSHOT</version>
     </dependency>
 
diff --git a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java
index 03fc475e35..e2ff465107 100644
--- a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java
+++ b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java
@@ -18,10 +18,16 @@
  */
 package org.apache.plc4x.java.opcuaserver.backend;
 
-import java.lang.reflect.Array;
-import java.util.Arrays;
-
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.model.PlcTag;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.api.types.PlcValueType;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.eclipse.milo.opcua.sdk.server.AbstractLifecycle;
 import org.eclipse.milo.opcua.sdk.server.api.DataItem;
 import org.eclipse.milo.opcua.sdk.server.nodes.filters.AttributeFilterContext;
@@ -30,31 +36,18 @@ import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
 import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
 import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
 import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
-
 import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.ULong;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.messages.PlcReadRequest;
-import org.apache.plc4x.java.api.messages.PlcReadResponse;
-import org.apache.plc4x.java.api.messages.PlcWriteRequest;
-
-import org.apache.plc4x.java.api.types.PlcResponseCode;
-
-import org.apache.plc4x.java.utils.connectionpool.*;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-
-import org.apache.plc4x.java.api.model.PlcTag;
-
+import java.lang.reflect.Array;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
 import java.util.concurrent.TimeUnit;
-import java.util.Map;
-import java.util.HashMap;
-
-import java.math.BigInteger;
+import java.util.concurrent.TimeoutException;
 
 import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.ulong;
 
@@ -62,6 +55,7 @@ import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.
 public class Plc4xCommunication extends AbstractLifecycle {
 
     private PlcDriverManager driverManager;
+    private CachedPlcConnectionManager cachedPlcConnectionManager;
     private final Logger logger = LoggerFactory.getLogger(getClass());
     private final Integer DEFAULT_TIMEOUT = 1000000;
     private final Integer DEFAULT_RETRY_BACKOFF = 5000;
@@ -71,13 +65,13 @@ public class Plc4xCommunication extends AbstractLifecycle {
 
     Map<NodeId, DataItem> monitoredList = new HashMap<>();
 
-    public Plc4xCommunication () {
+    public Plc4xCommunication() {
 
     }
 
     @Override
     protected void onStartup() {
-        driverManager = new PooledPlcDriverManager();
+        setDriverManager(PlcDriverManager.getDefault());
     }
 
     @Override
@@ -90,7 +84,8 @@ public class Plc4xCommunication extends AbstractLifecycle {
     }
 
     public void setDriverManager(PlcDriverManager driverManager) {
-        this.driverManager =  driverManager;
+        this.driverManager = driverManager;
+        this.cachedPlcConnectionManager = CachedPlcConnectionManager.getBuilder(driverManager.getConnectionManager()).build();
     }
 
     public PlcTag getTag(String tag, String connectionString) throws PlcConnectionException {
@@ -149,7 +144,7 @@ public class Plc4xCommunication extends AbstractLifecycle {
         PlcConnection connection = null;
         try {
 
-            //Check if we just polled the connection and it failed. Wait for the backoff counter to expire before we try again.
+            //Check if we just polled the connection, and it failed. Wait for the backoff counter to expire before we try again.
             if (failedConnectionList.containsKey(connectionString)) {
                 if (System.currentTimeMillis() > failedConnectionList.get(connectionString) + DEFAULT_RETRY_BACKOFF) {
                     failedConnectionList.remove(connectionString);
@@ -161,7 +156,7 @@ public class Plc4xCommunication extends AbstractLifecycle {
 
             //Try to connect to PLC
             try {
-                connection = driverManager.getConnection(connectionString);
+                connection = cachedPlcConnectionManager.getConnection(connectionString);
                 logger.debug(connectionString + " Connected");
             } catch (PlcConnectionException e) {
                 logger.error("Failed to connect to device, error raised - " + e);
@@ -253,53 +248,34 @@ public class Plc4xCommunication extends AbstractLifecycle {
     }
 
     public void setValue(String tag, String value, String connectionString) {
-        PlcConnection connection = null;
-        try {
-          connection = driverManager.getConnection(connectionString);
-          if (connection.isConnected() == false) {
-              logger.debug("getConnection() returned a connection that isn't connected");
-              connection.connect();
-          }
-        } catch (PlcConnectionException e) {
-          logger.warn("Failed" + e);
-        }
-
-        if (!connection.getMetadata().canWrite()) {
-            logger.error("This connection doesn't support writing.");
-            try {
-              connection.close();
-            } catch (Exception e) {
-              logger.warn("Closing connection failed with error " + e);
+        try (PlcConnection connection = cachedPlcConnectionManager.getConnection(connectionString)) {
+            if (!connection.getMetadata().canWrite()) {
+                logger.error("This connection doesn't support writing.");
+                return;
             }
-            return;
-        }
-
-        // Create a new read request:
-        // - Give the single item requested an alias name
-        final PlcWriteRequest.Builder builder = connection.writeRequestBuilder();
-
-        //If an array value is passed instead of a single value then convert to a String array
-        if ((value.charAt(0) == '[') && (value.charAt(value.length() - 1) == ']')) {
-            String[] values = value.substring(1,value.length() - 1).split(",");
-            logger.info("Adding Tag " + Arrays.toString(values));
-            builder.addTagAddress(tag, tag, values);
-        } else {
-            builder.addTagAddress(tag, tag, value);
-        }
 
-        PlcWriteRequest writeRequest = builder.build();
+            // Create a new read request:
+            // - Give the single item requested an alias name
+            final PlcWriteRequest.Builder builder = connection.writeRequestBuilder();
+
+            //If an array value is passed instead of a single value then convert to a String array
+            if ((value.charAt(0) == '[') && (value.charAt(value.length() - 1) == ']')) {
+                String[] values = value.substring(1, value.length() - 1).split(",");
+                logger.info("Adding Tag " + Arrays.toString(values));
+                builder.addTagAddress(tag, tag, values);
+            } else {
+                builder.addTagAddress(tag, tag, value);
+            }
 
-        try {
-          writeRequest.execute().get();
-        } catch (InterruptedException | ExecutionException e) {
-          logger.warn("Failed" + e);
-        }
+            PlcWriteRequest writeRequest = builder.build();
 
-        try {
-          connection.close();
+            try {
+                writeRequest.execute().get();
+            } catch (InterruptedException | ExecutionException e) {
+                logger.warn("Failed" + e);
+            }
         } catch (Exception e) {
-          logger.warn("Closing Connection Failed with error " + e);
+            logger.warn("Failed" + e);
         }
-        return;
     }
 }
diff --git a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java
index 73b70b7811..fd4d6e9188 100644
--- a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java
+++ b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java
@@ -18,14 +18,11 @@
  */
 package org.apache.plc4x.java.opcuaserver.backend;
 
-import java.lang.reflect.Array;
-import java.util.Arrays;
-import java.util.List;
-
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.opcuaserver.configuration.Configuration;
 import org.apache.plc4x.java.opcuaserver.configuration.DeviceConfiguration;
 import org.apache.plc4x.java.opcuaserver.configuration.Tag;
-import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager;
 import org.eclipse.milo.opcua.sdk.core.AccessLevel;
 import org.eclipse.milo.opcua.sdk.core.Reference;
 import org.eclipse.milo.opcua.sdk.core.ValueRank;
@@ -47,7 +44,10 @@ import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.List;
+
 import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
 
 
@@ -74,7 +74,7 @@ public class Plc4xNamespace extends ManagedNamespaceWithLifecycle {
     }
 
     private void addNodes() {
-        for (DeviceConfiguration c: config.getDevices()) {
+        for (DeviceConfiguration c : config.getDevices()) {
             NodeId folderNodeId = newNodeId(c.getName());
 
             UaFolderNode folderNode = new UaFolderNode(
@@ -186,7 +186,7 @@ public class Plc4xNamespace extends ManagedNamespaceWithLifecycle {
 
             if (plc4xServer.getDriverManager() == null) {
                 plc4xServer.removeTag(item);
-                plc4xServer.setDriverManager(new PooledPlcDriverManager());
+                plc4xServer.setDriverManager(new DefaultPlcDriverManager());
             }
         }
 
diff --git a/plc4j/integrations/opcua-server/src/test/java/org/apache/plc4x/java/opcuaserver/OpcuaPlcDriverTest.java b/plc4j/integrations/opcua-server/src/test/java/org/apache/plc4x/java/opcuaserver/OpcuaPlcDriverTest.java
index c5a6626cc7..8fb2a52f48 100644
--- a/plc4j/integrations/opcua-server/src/test/java/org/apache/plc4x/java/opcuaserver/OpcuaPlcDriverTest.java
+++ b/plc4j/integrations/opcua-server/src/test/java/org/apache/plc4x/java/opcuaserver/OpcuaPlcDriverTest.java
@@ -19,7 +19,7 @@
 package org.apache.plc4x.java.opcuaserver;
 
 import io.vavr.collection.List;
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
@@ -112,7 +112,7 @@ public class OpcuaPlcDriverTest {
         connectionStringValidSet.forEach(connectionAddress -> {
                 String connectionString = connectionAddress;
                 try {
-                    PlcConnection opcuaConnection = new PlcDriverManager().getConnection(connectionString);
+                    PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(connectionString);
                     assert opcuaConnection.isConnected();
                     opcuaConnection.close();
                     assert !opcuaConnection.isConnected();
@@ -132,7 +132,7 @@ public class OpcuaPlcDriverTest {
             discoveryParamValidSet.forEach(discoveryParam -> {
                 String connectionString = connectionAddress + paramSectionDivider + discoveryParam;
                 try {
-                    PlcConnection opcuaConnection = new PlcDriverManager().getConnection(connectionString);
+                    PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(connectionString);
                     assert opcuaConnection.isConnected();
                     opcuaConnection.close();
                     assert !opcuaConnection.isConnected();
@@ -150,7 +150,7 @@ public class OpcuaPlcDriverTest {
     @Test
     public void readVariables() throws Exception{
 
-            PlcConnection opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress);
+            PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(tcpConnectionAddress);
             assert opcuaConnection.isConnected();
 
             PlcReadRequest.Builder builder = opcuaConnection.readRequestBuilder();
@@ -199,7 +199,7 @@ public class OpcuaPlcDriverTest {
     @Test
     public void writeVariables() throws Exception {
 
-            PlcConnection opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress);
+            PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(tcpConnectionAddress);
             assert opcuaConnection.isConnected();
 
             PlcWriteRequest.Builder builder = opcuaConnection.writeRequestBuilder();
diff --git a/plc4j/tools/connection-cache/README.md b/plc4j/tools/connection-cache/README.md
new file mode 100644
index 0000000000..1a7fe7600e
--- /dev/null
+++ b/plc4j/tools/connection-cache/README.md
@@ -0,0 +1,51 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+
+# Connection Cache
+
+In contrast to typical database-connections, plc-connections have numerous disadvantages:
+
+1. The number of connections a PLC is able to accept might be very limited.
+2. Connecting can require a number of round-trips and a lot of data being transmitted.
+
+If multiple places in the application want to access a PLC, the option of `every part opens its own connection` will quickly drain the resources of the PLC. Opening and closing the connections in order to reduce this, will waste a lot of resources.
+
+Therefore, it's the goal of the connection-cache to allow gaining access to a PLC the usual way, however as soon as a client is finished with its work, it doesn't close the connection, but gives it back to the cache for the next client to be able to use the same connection without having to re-connect.
+
+The `ConnectionCache` implements the `PlcConnectionManager` interface, just the same way the `PlcDriverManager` does, so it can generally be used instead of the un-cached version.
+
+## Architecture
+
+The `CachedPlcConnectionManager` contains a map of `ConnectionContainer` objects.
+Each of these generally have a reference to a real `PlcConnection` as well as all properties for managing it's state.
+
+In general there are just three properties:
+
+- A reference to the connection this container handles
+- A reference to the current connection-lease (`null`, if the `ConnectionContainer` is idle)
+- A queue where all further lease-requests are lined up
+
+Whenever a `PlcConnection` is required, instead of returning a real `PlcConnection`, the `CachedPlcConnectionManager` returns a `LeasedPlcConnection`. 
+
+This object is a volatile container for a `PlcConnection`, allowing the container to invalidate the `PlcConnection`. 
+
+Whenever a `CachedPlcConnectionManager`'s `getConnection` method is used, it returns a new instance of such a container. Whenever the client calls `close` on this connection, it is however not really closed, but the reference to the real connection is cleared, hereby rendering the connection-lease useless and the connection is returned to the `ConnectionContainer`. Also, if the client holds on to the connection-lease for longer than the `maxLeaseTime` the container invalidates the connec [...]
+
+If a `CachedPlcConnectionManager` is used to get a connection that is currently being used, instead of returning a reference to it, a Future is generated and added to a queue. As soon as the connection is released, the container checks if there are any requests waiting.
+If there are it takes the oldest request and completes that future with a new lease.
\ No newline at end of file
diff --git a/plc4j/tools/connection-cache/pom.xml b/plc4j/tools/connection-cache/pom.xml
index ef8859233a..1312675031 100644
--- a/plc4j/tools/connection-cache/pom.xml
+++ b/plc4j/tools/connection-cache/pom.xml
@@ -30,7 +30,7 @@
   <artifactId>plc4j-connection-cache</artifactId>
 
   <name>PLC4J: Tools: Connection Cache</name>
-  <description>An implementation of a connection pool based on Apache Commons Pool.</description>
+  <description>An implementation of a connection cache.</description>
 
   <dependencies>
     <dependency>
@@ -40,10 +40,11 @@
     </dependency>
 
     <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-lang3</artifactId>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-driver-ads</artifactId>
+      <version>0.11.0-SNAPSHOT</version>
+      <scope>test</scope>
     </dependency>
-
     <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-driver-mock</artifactId>
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/cache/CachedPlcConnectionManager.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/cache/CachedPlcConnectionManager.java
new file mode 100644
index 0000000000..650d976c85
--- /dev/null
+++ b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/cache/CachedPlcConnectionManager.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.utils.cache;
+
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.Duration;
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class CachedPlcConnectionManager implements PlcConnectionManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(CachedPlcConnectionManager.class);
+
+    private final PlcConnectionManager connectionManager;
+    private final Duration maxLeaseTime;
+    private final Duration maxWaitTime;
+
+    private final Map<String, ConnectionContainer> connectionContainers;
+
+    public static Builder getBuilder() {
+        return new Builder(new DefaultPlcDriverManager());
+    }
+
+    public static Builder getBuilder(PlcConnectionManager connectionManager) {
+        return new Builder(connectionManager);
+    }
+
+    public CachedPlcConnectionManager(PlcConnectionManager connectionManager, Duration maxLeaseTime, Duration maxWaitTime) {
+        this.connectionManager = connectionManager;
+        this.maxLeaseTime = maxLeaseTime;
+        this.maxWaitTime = maxWaitTime;
+        this.connectionContainers = new HashMap<>();
+    }
+
+    public PlcConnection getConnection(String url) throws PlcConnectionException {
+        ConnectionContainer connectionContainer;
+        synchronized (connectionContainers) {
+            connectionContainer = connectionContainers.get(url);
+            if (connectionContainers.get(url) == null) {
+                LOG.debug("Creating new connection");
+
+                // Establish the real connection to the plc
+                PlcConnection connection = connectionManager.getConnection(url);
+
+                // Crate a connection container to manage handling this connection
+                connectionContainer = new ConnectionContainer(connection, maxLeaseTime);
+                connectionContainers.put(url, connectionContainer);
+            } else {
+                LOG.debug("Reusing exising connection");
+            }
+        }
+
+        // Get a lease (a future for a connection)
+        Future<PlcConnection> leaseFuture = connectionContainer.lease();
+        try {
+            return leaseFuture.get(this.maxWaitTime.toMillis(), TimeUnit.MILLISECONDS);
+        } catch (ExecutionException | InterruptedException | TimeoutException e) {
+            throw new PlcConnectionException("Error acquiring lease for connection", e);
+        }
+    }
+
+    public PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException {
+        throw new PlcConnectionException("the cached driver manager currently doesn't support authentication");
+    }
+
+    public static class Builder {
+
+        private final PlcConnectionManager connectionManager;
+        private Duration maxLeaseTime;
+        private Duration maxWaitTime;
+
+        public Builder(PlcConnectionManager connectionManager) {
+            this.connectionManager = connectionManager;
+            this.maxLeaseTime = Duration.ofSeconds(4);
+            this.maxWaitTime = Duration.ofSeconds(20);
+        }
+
+        public CachedPlcConnectionManager build() {
+            return new CachedPlcConnectionManager(this.connectionManager, this.maxLeaseTime, this.maxWaitTime);
+        }
+
+        public CachedPlcConnectionManager.Builder withMaxLeaseTime(Duration maxLeaseTime) {
+            this.maxLeaseTime = maxLeaseTime;
+            return this;
+        }
+
+        public CachedPlcConnectionManager.Builder withMaxWaitTime(Duration maxWaitTime) {
+            this.maxWaitTime = maxWaitTime;
+            return this;
+        }
+    }
+
+}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/cache/ConnectionContainer.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/cache/ConnectionContainer.java
new file mode 100644
index 0000000000..c55f4a7de9
--- /dev/null
+++ b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/cache/ConnectionContainer.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.utils.cache;
+
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+
+import java.time.Duration;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+
+class ConnectionContainer {
+    private final PlcConnection connection;
+    private final Duration maxLeaseTime;
+    private final Queue<CompletableFuture<PlcConnection>> queue;
+
+    private LeasedPlcConnection leasedConnection;
+
+    public ConnectionContainer(PlcConnection connection, Duration maxLeaseTime) {
+        this.connection = connection;
+        this.maxLeaseTime = maxLeaseTime;
+        this.queue = new LinkedList<>();
+        this.leasedConnection = null;
+    }
+
+    public synchronized Future<PlcConnection> lease() {
+        CompletableFuture<PlcConnection> connectionFuture = new CompletableFuture<>();
+        // If the connection is currently idle, return the connection immediately.
+        if (leasedConnection == null) {
+            leasedConnection = new LeasedPlcConnection(this, connection, maxLeaseTime);
+            connectionFuture.complete(leasedConnection);
+        }
+        // Otherwise queue the future up for completion as soon as the connection is returned.
+        else {
+            queue.add(connectionFuture);
+        }
+        return connectionFuture;
+    }
+
+    public synchronized void returnConnection(LeasedPlcConnection returnedLeasedConnection) {
+        if(returnedLeasedConnection != leasedConnection) {
+            throw new PlcRuntimeException("Error trying to return lease from invalid connection");
+        }
+
+        // If the queue is empty, simply return.
+        if(queue.isEmpty()) {
+            leasedConnection = null;
+            return;
+        }
+
+        // Create a new lease and complete the next future in the queue with this.
+        leasedConnection = new LeasedPlcConnection(this, connection, maxLeaseTime);
+        CompletableFuture<PlcConnection> leaseFuture = queue.poll();
+        leaseFuture.complete(leasedConnection);
+    }
+
+}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/cache/LeasedPlcConnection.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/cache/LeasedPlcConnection.java
new file mode 100644
index 0000000000..662dd294c4
--- /dev/null
+++ b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/cache/LeasedPlcConnection.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.utils.cache;
+
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.api.metadata.PlcConnectionMetadata;
+
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.CompletableFuture;
+
+public class LeasedPlcConnection implements PlcConnection {
+
+    private final ConnectionContainer connectionContainer;
+    private PlcConnection connection;
+
+    public LeasedPlcConnection(ConnectionContainer connectionContainer, PlcConnection connection, Duration maxUseTime) {
+        this.connectionContainer = connectionContainer;
+        this.connection = connection;
+        Timer usageTimer = new Timer();
+        usageTimer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                close();
+            }
+        }, Date.from(LocalDateTime.now().plusNanos(maxUseTime.toNanos()).atZone(ZoneId.systemDefault()).toInstant()));
+    }
+
+    @Override
+    public synchronized void close() {
+        // Make the connection unusable.
+        connection = null;
+
+        // Tell the connection container that the connection is free to be reused.
+        connectionContainer.returnConnection(this);
+    }
+
+    @Override
+    public void connect() throws PlcConnectionException {
+        throw new PlcConnectionException("Error connecting leased connection");
+    }
+
+    @Override
+    public boolean isConnected() {
+        if(connection == null) {
+            throw new PlcRuntimeException("Error using leased connection after returning it to the cache.");
+        }
+        return connection.isConnected();
+    }
+
+    @Override
+    public PlcConnectionMetadata getMetadata() {
+        if(connection == null) {
+            throw new PlcRuntimeException("Error using leased connection after returning it to the cache.");
+        }
+        return connection.getMetadata();
+    }
+
+    @Override
+    public CompletableFuture<Void> ping() {
+        if(connection == null) {
+            throw new PlcRuntimeException("Error using leased connection after returning it to the cache.");
+        }
+        return connection.ping();
+    }
+
+    @Override
+    public PlcReadRequest.Builder readRequestBuilder() {
+        if(connection == null) {
+            throw new PlcRuntimeException("Error using leased connection after returning it to the cache.");
+        }
+        return connection.readRequestBuilder();
+    }
+
+    @Override
+    public PlcWriteRequest.Builder writeRequestBuilder() {
+        if(connection == null) {
+            throw new PlcRuntimeException("Error using leased connection after returning it to the cache.");
+        }
+        return connection.writeRequestBuilder();
+    }
+
+    @Override
+    public PlcSubscriptionRequest.Builder subscriptionRequestBuilder() {
+        if(connection == null) {
+            throw new PlcRuntimeException("Error using leased connection after returning it to the cache.");
+        }
+        return connection.subscriptionRequestBuilder();
+    }
+
+    @Override
+    public PlcUnsubscriptionRequest.Builder unsubscriptionRequestBuilder() {
+        if(connection == null) {
+            throw new PlcRuntimeException("Error using leased connection after returning it to the cache.");
+        }
+        return connection.unsubscriptionRequestBuilder();
+    }
+
+    @Override
+    public PlcBrowseRequest.Builder browseRequestBuilder() {
+        if(connection == null) {
+            throw new PlcRuntimeException("Error using leased connection after returning it to the cache.");
+        }
+        return connection.browseRequestBuilder();
+    }
+
+}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedBrowseRequest.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedBrowseRequest.java
deleted file mode 100644
index f69f05caa0..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedBrowseRequest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.messages.PlcBrowseRequest;
-import org.apache.plc4x.java.api.messages.PlcBrowseRequestInterceptor;
-import org.apache.plc4x.java.api.messages.PlcBrowseResponse;
-import org.apache.plc4x.java.api.model.PlcQuery;
-
-import java.util.LinkedHashSet;
-import java.util.concurrent.CompletableFuture;
-
-public class CachedBrowseRequest implements PlcBrowseRequest {
-
-    private final CachedPlcConnection parent;
-    private final PlcBrowseRequest innerRequest;
-
-    public CachedBrowseRequest(CachedPlcConnection parent, PlcBrowseRequest innerRequest) {
-        this.parent = parent;
-        this.innerRequest = innerRequest;
-    }
-
-    @Override
-    public CompletableFuture<? extends PlcBrowseResponse> execute() {
-        // Only allowed if connection is still active
-        return parent.execute(innerRequest);
-    }
-
-    @Override
-    public CompletableFuture<? extends PlcBrowseResponse> executeWithInterceptor(PlcBrowseRequestInterceptor interceptor) {
-        return parent.executeWithInterceptor(innerRequest, interceptor);
-    }
-
-    @Override
-    public LinkedHashSet<String> getQueryNames() {
-        return innerRequest.getQueryNames();
-    }
-
-    @Override
-    public PlcQuery getQuery(String name) {
-        return innerRequest.getQuery(name);
-    }
-
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedBrowseRequestBuilder.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedBrowseRequestBuilder.java
deleted file mode 100644
index ff0cfc5090..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedBrowseRequestBuilder.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.messages.PlcBrowseRequest;
-
-public class CachedBrowseRequestBuilder implements PlcBrowseRequest.Builder {
-
-    private final CachedPlcConnection parent;
-    private final PlcBrowseRequest.Builder builder;
-
-    public CachedBrowseRequestBuilder(CachedPlcConnection parent, PlcBrowseRequest.Builder builder) {
-        this.parent = parent;
-        this.builder = builder;
-    }
-
-    @Override
-    public PlcBrowseRequest.Builder addQuery(String name, String query) {
-        return builder.addQuery(name, query);
-    }
-
-    @Override
-    public PlcBrowseRequest build() {
-        return new CachedBrowseRequest(parent, builder.build());
-    }
-
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManager.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManager.java
deleted file mode 100644
index 3dac03cd84..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManager.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.commons.lang3.NotImplementedException;
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.authentication.PlcAuthentication;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.management.ObjectName;
-import java.lang.management.ManagementFactory;
-import java.util.LinkedList;
-import java.util.Queue;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Driver Manager who Caches ONE Single Connection.
- * <p>
- * Usage Example:
- * <code>
- * PlcDriverManager manager = new PlcDriverManager();
- * PlcDriverManager cached = new CachedDriverManager(url, () -&gt; manager.getConnection(url));
- * </code>
- * Now you can use "cached" everywhere you need the corresponding connection.
- */
-public class CachedDriverManager extends PlcDriverManager implements CachedDriverManagerMBean {
-
-    private static final Logger logger = LoggerFactory.getLogger(CachedDriverManager.class);
-
-    // Constants
-    public static final int LONG_BORROW_WATCHDOG_TIMEOUT_MS = 5_000;
-
-    // JMX
-
-    private final AtomicInteger numberOfConnects = new AtomicInteger(0);
-    private final AtomicInteger numberOfBorrows = new AtomicInteger(0);
-    private final AtomicInteger numberOfRejections = new AtomicInteger(0);
-    private final AtomicInteger numberOfWatchdogs = new AtomicInteger(0);
-
-    // End of JMX
-
-    private final String url;
-    private final PlcConnectionFactory connectionFactory;
-
-    // Add Queue for Requests
-    private final Queue<CompletableFuture<PlcConnection>> queue = new LinkedList<>();
-    private final int timeoutMillis;
-
-    private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
-
-    private AtomicReference<ConnectionState> state = new AtomicReference<>(ConnectionState.DISCONNECTED);
-    private PlcConnection activeConnection;
-    private CachedPlcConnection borrowedConnection;
-    private ScheduledFuture<?> borrowWatchdog;
-
-    public CachedDriverManager(String url, PlcConnectionFactory connectionFactory) {
-        this(url, connectionFactory, 1000);
-    }
-
-    /**
-     * @param url               Url that this connection is for
-     * @param connectionFactory Factory to create a suitable connection.
-     * @param timeoutMillis     Time out in milliseconds
-     */
-    public CachedDriverManager(String url, PlcConnectionFactory connectionFactory, int timeoutMillis) {
-        logger.info("Creating new cached Connection for url {} with timeout {} ms", url, timeoutMillis);
-        this.url = url;
-        this.connectionFactory = connectionFactory;
-        this.timeoutMillis = timeoutMillis;
-
-        // MBean
-        try {
-            ManagementFactory.getPlatformMBeanServer().registerMBean(this, new ObjectName("org.apache.plc4x.plc:name=cached-driver-manager,url=\"" + url + "\""));
-        } catch (Exception ignore) {
-        }
-    }
-
-    public synchronized void returnConnection(PlcConnection activeConnection) {
-        logger.debug("Borrowed Connection is closed and returned.");
-        // Stop Watchdog
-        cancelWatchdog();
-        if (state.get() == ConnectionState.DISCONNECTED) {
-            // Getting Disconnected Connection, nothing to do.
-            logger.trace("Connection already disconnected");
-            return;
-        }
-        if (state.get() != ConnectionState.BORROWED) {
-            logger.warn("Connection was returned, although it is not borrowed, currently.");
-        }
-        this.borrowedConnection = null;
-        setState(ConnectionState.AVAILABLE);
-        // Check the queue
-        checkQueue();
-        logger.trace("Connection successfully returned");
-    }
-
-    private void setState(ConnectionState available) {
-        logger.trace("Setting State from {} to {}", this.state.get(), available);
-        this.state.set(available);
-    }
-
-    /**
-     * used to signal, that the connection does not work and has to be re-established.
-     */
-    public synchronized void handleBrokenConnection() {
-        logger.debug("Connection was detected as broken and is invalidated in Cached Manager");
-        // Stop Watchdog
-        cancelWatchdog();
-        if (state.get() != ConnectionState.BORROWED) {
-            // Log at least a WARN???
-            logger.warn("Broken Connection was returned, although it is not borrowed, currently.");
-        }
-        this.borrowedConnection = null;
-        try {
-            this.activeConnection.close();
-        } catch (Exception e) {
-            logger.debug("Unable to Close 'broken' Connection", e);
-        }
-        this.activeConnection = null;
-        setState(ConnectionState.DISCONNECTED);
-    }
-
-    public boolean isConnectionAvailable() {
-        return this.getState().equals(ConnectionState.AVAILABLE);
-    }
-
-    /**
-     * This call now waits (with the timeout given in constructor) until it fails
-     * or returns a valid connection in this window.
-     *
-     * @throws PlcConnectionException if connection cannot be established
-     */
-    @Override
-    public PlcConnection getConnection(String url) throws PlcConnectionException {
-        if (!this.url.equals(url)) {
-            throw new IllegalArgumentException("This Cached Driver Manager only supports the Connection " + url);
-        }
-        CompletableFuture<PlcConnection> future;
-        synchronized (this) {
-            logger.trace("current queue size before check {}", queue.size());
-            if (queue.isEmpty() && isConnectionAvailable()) {
-                logger.trace("queue is empty and a connection is available");
-                return getConnection_(url);
-            } else {
-                logger.trace("Getting a connection and instantly close it");
-                // At least trigger a connection
-                try {
-                    getConnection_(url).close();
-                } catch (Exception ignore) {
-                }
-            }
-
-            future = new CompletableFuture<>();
-            logger.trace("current queue size before add {}", queue.size());
-            queue.add(future);
-        }
-        try {
-            return future.get(timeoutMillis, TimeUnit.MILLISECONDS);
-        } catch (ExecutionException | TimeoutException e) {
-            handleBrokenConnection();
-            throw new PlcConnectionException("No Connection Available, timed out while waiting in queue.", e);
-        } catch (InterruptedException e) {
-            handleBrokenConnection();
-            Thread.currentThread().interrupt();
-            throw new PlcConnectionException("No Connection Available, interrupted while waiting in queue.", e);
-        } finally {
-            future.cancel(true);
-        }
-    }
-
-    /**
-     * Private Impl.
-     */
-    private synchronized PlcConnection getConnection_(String url) throws PlcConnectionException {
-        logger.trace("Current State {}", this.state.get());
-        switch (state.get()) {
-            case AVAILABLE:
-                logger.debug("Connection was requested and is available, thus, returning Chached Connection for usage");
-                setState(ConnectionState.BORROWED);
-                this.numberOfBorrows.incrementAndGet();
-
-                this.borrowedConnection = new CachedPlcConnection(this, activeConnection);
-
-                // Set the Borrwed Counter
-                startWatchdog(this.borrowedConnection);
-
-                return this.borrowedConnection;
-            case DISCONNECTED:
-                logger.debug("Connection was requested but no connection is active, trying to establish a Connection");
-                // Initialize Connection
-                setState(ConnectionState.CONNECTING);
-                this.numberOfConnects.incrementAndGet();
-
-                // Start Connection in Background
-                CompletableFuture.runAsync(() -> {
-                    logger.debug("Starting to establish Connection");
-                    try {
-                        PlcConnection connection = this.connectionFactory.create();
-                        logger.debug("Connection successfully established");
-                        synchronized (this) {
-                            this.activeConnection = connection;
-                            setState(ConnectionState.AVAILABLE);
-                            // Now See if there is someone waiting in the line
-                            checkQueue();
-                            logger.trace("Inline queue check succeeded");
-                        }
-                    } catch (Exception e) {
-                        logger.warn("Unable to establish connection to PLC {}", url, e);
-                        setState(ConnectionState.DISCONNECTED);
-                    }
-                });
-
-                this.numberOfRejections.incrementAndGet();
-                throw new PlcConnectionException("No Connection Available, Starting Connection");
-            case CONNECTING:
-                // We cannot give a Connection
-                logger.debug("Connection was requsted, but currently establishing one, so none available");
-                this.numberOfRejections.incrementAndGet();
-                throw new PlcConnectionException("No Connection Available, Currently Connecting");
-            case BORROWED:
-                // We cannot give a Connection
-                logger.debug("Connection was requsted, but Connection currently is borrowed, so none available");
-                this.numberOfRejections.incrementAndGet();
-                throw new PlcConnectionException("No Connection Available, its in Use");
-        }
-        throw new IllegalStateException();
-    }
-
-    /**
-     * Checks if someone is waiting in the line to get the connection.
-     */
-    private synchronized void checkQueue() {
-        logger.debug("Connection is available, checking if someone is waiting in the queue...");
-        CompletableFuture<PlcConnection> next;
-        logger.trace("current queue size before check queue {}", queue.size());
-        while ((next = queue.poll()) != null) {
-            if (next.isCancelled()) {
-                logger.trace("Cleaning up already timed out connection...");
-                continue;
-            }
-            // Not timed out, give this connection
-            try {
-                next.complete(getConnection_(url));
-                return;
-            } catch (PlcConnectionException e) {
-                logger.debug("Got an Exception on fetching a connection", e);
-            }
-        }
-        logger.trace("check queue ended");
-    }
-
-    private void startWatchdog(CachedPlcConnection connection) {
-        borrowWatchdog = executorService.schedule(() -> {
-            // Just close the borrowed connection
-            logger.warn("Watchdog detected a long borrowed connection, will be forcefully closed!");
-            this.numberOfWatchdogs.incrementAndGet();
-            handleBrokenConnection();
-            try {
-                connection.close();
-            } catch (Exception e) {
-                logger.warn("Unable to close the borrowed Connection from Watchdog", e);
-            }
-        }, LONG_BORROW_WATCHDOG_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-    }
-
-    private void cancelWatchdog() {
-        if (borrowWatchdog != null ) {
-            borrowWatchdog.cancel(false);
-        }
-    }
-
-    @Override
-    public PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException {
-        throw new NotImplementedException("");
-    }
-
-    public ConnectionState getState() {
-        return state.get();
-    }
-
-    enum ConnectionState {
-        DISCONNECTED,
-        CONNECTING,
-        AVAILABLE,
-        BORROWED;
-    }
-
-    // JMX
-
-    @Override
-    public String getStateString() {
-        return getState().toString();
-    }
-
-    @Override
-    public int getNumberOfConnects() {
-        return numberOfConnects.get();
-    }
-
-    @Override
-    public int getNumberOfBorrows() {
-        return numberOfBorrows.get();
-    }
-
-    @Override
-    public int getNumberOfRejections() {
-        return this.numberOfRejections.get();
-    }
-
-    @Override
-    public int getNumberOfWachtdogs() {
-        return numberOfWatchdogs.get();
-    }
-
-    @Override
-    public int getQueueSize() {
-        return this.queue.size();
-    }
-
-    @Override
-    public synchronized void triggerReconnect() {
-        logger.info("Disconnecting current connection, was triggered from external via JMX");
-        handleBrokenConnection();
-        if (this.state.get() == ConnectionState.BORROWED) {
-            try {
-                borrowedConnection.close();
-            } catch (Exception e) {
-                logger.warn("Unable to close the borrowed Connection from JMX", e);
-            }
-        }
-    }
-}
-
-
-
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMBean.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMBean.java
deleted file mode 100644
index 0a44f384f3..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMBean.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-public interface CachedDriverManagerMBean {
-
-    String getStateString();
-
-    int getNumberOfConnects();
-
-    int getNumberOfBorrows();
-
-    int getNumberOfWachtdogs();
-
-    int getNumberOfRejections();
-
-    void triggerReconnect();
-
-    int getQueueSize();
-
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnection.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnection.java
deleted file mode 100644
index 4cf912d3a9..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnection.java
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
-import org.apache.plc4x.java.api.exceptions.PlcUnsupportedOperationException;
-import org.apache.plc4x.java.api.messages.*;
-import org.apache.plc4x.java.api.metadata.PlcConnectionMetadata;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.function.BiFunction;
-
-/**
- * Wrapper around a PlcConnection which interacts with the {@link CachedDriverManager}.
- */
-public class CachedPlcConnection implements PlcConnection, PlcConnectionMetadata {
-
-    private static final Logger logger = LoggerFactory.getLogger(CachedPlcConnection.class);
-
-    private static final ScheduledExecutorService schedulerExecutor =
-        Executors.newScheduledThreadPool(10);
-
-    private final CachedDriverManager parent;
-    private volatile PlcConnection activeConnection;
-    private volatile boolean closed = false;
-
-    public CachedPlcConnection(CachedDriverManager parent, PlcConnection activeConnection) {
-        this.parent = parent;
-        this.activeConnection = activeConnection;
-    }
-
-    @Override
-    public void connect() throws PlcConnectionException {
-        // Do nothing
-        logger.warn(".connect() is called on a Cached Connection. This has no effect but should not happen.");
-    }
-
-    @Override
-    public boolean isConnected() {
-        if (closed) {
-            return false;
-        } else {
-            return activeConnection.isConnected();
-        }
-    }
-
-    private CompletableFuture<? extends PlcBrowseResponse> wrapBrowseWithTimeout(CompletableFuture<? extends PlcBrowseResponse> future, long timeoutMillis) {
-        //schedule watcher
-        final CompletableFuture<PlcBrowseResponse> responseFuture = new CompletableFuture<>();
-        schedulerExecutor.schedule(() -> {
-            if (!future.isDone()) {
-                logger.debug("Timing out the PLC request!");
-                future.cancel(true);
-                responseFuture.completeExceptionally(new TimeoutException("Response did not finish in Time!"));
-            } else {
-                logger.trace("Unnecessary to cancel the request!");
-            }
-        }, timeoutMillis, TimeUnit.MILLISECONDS);
-        future.handle(new BiFunction<PlcBrowseResponse, Throwable, Object>() {
-            @Override
-            public Object apply(PlcBrowseResponse plcBrowseResponse, Throwable throwable) {
-                if (plcBrowseResponse != null) {
-                    logger.debug("Request finsihed successfull!");
-                    responseFuture.complete(plcBrowseResponse);
-                } else {
-                    logger.debug("Request failed", throwable);
-                    responseFuture.completeExceptionally(throwable);
-                }
-                return null;
-            }
-        });
-        return responseFuture;
-    }
-
-    private CompletableFuture<? extends PlcReadResponse> wrapReadWithTimeout(CompletableFuture<? extends PlcReadResponse> future, long timeoutMillis) {
-        //schedule watcher
-        final CompletableFuture<PlcReadResponse> responseFuture = new CompletableFuture<>();
-        schedulerExecutor.schedule(() -> {
-            if (!future.isDone()) {
-                logger.debug("Timing out the PLC request!");
-                future.cancel(true);
-                responseFuture.completeExceptionally(new TimeoutException("Response did not finish in Time!"));
-            } else {
-                logger.trace("Unnecessary to cancel the request!");
-            }
-        }, timeoutMillis, TimeUnit.MILLISECONDS);
-        future.handle(new BiFunction<PlcReadResponse, Throwable, Object>() {
-            @Override
-            public Object apply(PlcReadResponse plcReadResponse, Throwable throwable) {
-                if (plcReadResponse != null) {
-                    logger.debug("Request finsihed successfull!");
-                    responseFuture.complete(plcReadResponse);
-                } else {
-                    logger.debug("Request failed", throwable);
-                    responseFuture.completeExceptionally(throwable);
-                }
-                return null;
-            }
-        });
-        return responseFuture;
-    }
-
-    private CompletableFuture<? extends PlcWriteResponse> wrapWriteWithTimeout(CompletableFuture<? extends PlcWriteResponse> future, long timeoutMillis) {
-        //schedule watcher
-        final CompletableFuture<PlcWriteResponse> responseFuture = new CompletableFuture<>();
-        schedulerExecutor.schedule(() -> {
-            if (!future.isDone()) {
-                logger.debug("Timing out the PLC request!");
-                future.cancel(true);
-                responseFuture.completeExceptionally(new TimeoutException("Response did not finish in Time!"));
-            } else {
-                logger.trace("Unnecessary to cancel the request!");
-            }
-        }, timeoutMillis, TimeUnit.MILLISECONDS);
-        future.handle(new BiFunction<PlcWriteResponse, Throwable, Object>() {
-            @Override
-            public Object apply(PlcWriteResponse plcWriteResponse, Throwable throwable) {
-                if (plcWriteResponse != null) {
-                    logger.debug("Request finsihed successfull!");
-                    responseFuture.complete(plcWriteResponse);
-                } else {
-                    logger.debug("Request failed", throwable);
-                    responseFuture.completeExceptionally(throwable);
-                }
-                return null;
-            }
-        });
-        return responseFuture;
-    }
-
-    public CompletableFuture<? extends PlcBrowseResponse> execute(PlcBrowseRequest request) {
-        logger.trace("Trying to executing Request {}", request);
-        if (closed) {
-            throw new IllegalStateException("Trying to execute a Request on a closed Connection!");
-        }
-        try {
-            logger.trace("Executing Request {}", request);
-            final CompletableFuture<? extends PlcBrowseResponse> responseFuture = wrapBrowseWithTimeout(request.execute(), 5_000);
-            // The following code handles the case, that a read fails (which is handled async and thus not really connected
-            // to the connection, yet
-            // Thus, we register our own listener who gets the notification and reports the connection as broken
-            final CompletableFuture<PlcBrowseResponse> handledResponseFuture = responseFuture.handleAsync(new BiFunction<PlcBrowseResponse, Throwable, PlcBrowseResponse>() {
-                @Override
-                public PlcBrowseResponse apply(PlcBrowseResponse plcBrowseResponse, Throwable throwable) {
-                    if (throwable != null) {
-                        // Do something here...
-                        logger.warn("Request finished with exception. Reporting Connection as Broken", throwable);
-                        closeConnectionExceptionally(null);
-                    }
-                    return plcBrowseResponse;
-                }
-            });
-            return handledResponseFuture;
-        } catch (Exception e) {
-            return (CompletableFuture<? extends PlcBrowseResponse>) closeConnectionExceptionally(e);
-        }
-    }
-
-    public CompletableFuture<? extends PlcBrowseResponse> executeWithInterceptor(PlcBrowseRequest request, PlcBrowseRequestInterceptor interceptor) {
-        logger.trace("Trying to executing Request with interceptor {}", request);
-        if (closed) {
-            throw new IllegalStateException("Trying to execute a Request on a closed Connection!");
-        }
-        try {
-            logger.trace("Executing Request {}", request);
-            final CompletableFuture<? extends PlcBrowseResponse> responseFuture = wrapBrowseWithTimeout(request.executeWithInterceptor(interceptor), 5_000);
-            // The following code handles the case, that a read fails (which is handled async and thus not really connected
-            // to the connection, yet
-            // Thus, we register our own listener who gets the notification and reports the connection as broken
-            final CompletableFuture<PlcBrowseResponse> handledResponseFuture = responseFuture.handleAsync(new BiFunction<PlcBrowseResponse, Throwable, PlcBrowseResponse>() {
-                @Override
-                public PlcBrowseResponse apply(PlcBrowseResponse plcBrowseResponse, Throwable throwable) {
-                    if (throwable != null) {
-                        // Do something here...
-                        logger.warn("Request finished with exception. Reporting Connection as Broken", throwable);
-                        closeConnectionExceptionally(null);
-                    }
-                    return plcBrowseResponse;
-                }
-            });
-            return handledResponseFuture;
-        } catch (Exception e) {
-            return (CompletableFuture<? extends PlcBrowseResponse>) closeConnectionExceptionally(e);
-        }
-    }
-
-    /**
-     * Executes the Request.
-     */
-    public CompletableFuture<? extends PlcReadResponse> execute(PlcReadRequest request) {
-        logger.trace("Trying to executing Request {}", request);
-        if (closed) {
-            throw new IllegalStateException("Trying to execute a Request on a closed Connection!");
-        }
-        try {
-            logger.trace("Executing Request {}", request);
-             final CompletableFuture<? extends PlcReadResponse> responseFuture = wrapReadWithTimeout(request.execute(), 5_000);
-//            final CompletableFuture<? extends PlcReadResponse> responseFuture = request.execute();
-            // The following code handles the case, that a read fails (which is handled async and thus not really connected
-            // to the connection, yet
-            // Thus, we register our own listener who gets the notification and reports the connection as broken
-            final CompletableFuture<PlcReadResponse> handledResponseFuture = responseFuture.handleAsync(new BiFunction<PlcReadResponse, Throwable, PlcReadResponse>() {
-                @Override
-                public PlcReadResponse apply(PlcReadResponse plcReadResponse, Throwable throwable) {
-                    if (throwable != null) {
-                        // Do something here...
-                        logger.warn("Request finished with exception. Reporting Connection as Broken", throwable);
-                        closeConnectionExceptionally(null);
-                    }
-                    return plcReadResponse;
-                }
-            });
-            return handledResponseFuture;
-        } catch (Exception e) {
-            return (CompletableFuture<? extends PlcReadResponse>) closeConnectionExceptionally(e);
-        }
-    }
-
-    public CompletableFuture<? extends PlcWriteResponse> execute(PlcWriteRequest request) {
-        logger.trace("Trying to executing Request {}", request);
-        if (closed) {
-            throw new IllegalStateException("Trying to execute a Request on a closed Connection!");
-        }
-        try {
-            logger.trace("Executing Request {}", request);
-            final CompletableFuture<? extends PlcWriteResponse> responseFuture = wrapWriteWithTimeout(request.execute(), 5_000);
-//            final CompletableFuture<? extends PlcReadResponse> responseFuture = request.execute();
-            // The following code handles the case, that a read fails (which is handled async and thus not really connected
-            // to the connection, yet
-            // Thus, we register our own listener who gets the notification and reports the connection as broken
-            final CompletableFuture<PlcWriteResponse> handledResponseFuture = responseFuture.handleAsync(new BiFunction<PlcWriteResponse, Throwable, PlcWriteResponse>() {
-                @Override
-                public PlcWriteResponse apply(PlcWriteResponse plcWriteResponse, Throwable throwable) {
-                    if (throwable != null) {
-                        // Do something here...
-                        logger.warn("Request finished with exception. Reporting Connection as Broken", throwable);
-                        closeConnectionExceptionally(null);
-                    }
-                    return plcWriteResponse;
-                }
-            });
-            return handledResponseFuture;
-        } catch (Exception e) {
-            return (CompletableFuture<? extends PlcWriteResponse>) closeConnectionExceptionally(e);
-        }
-    }
-
-    private CompletableFuture<? extends PlcResponse> closeConnectionExceptionally(Exception e) {
-        // First, close this connection and allow no further operations on it!
-        this.closed = true;
-        // Return the Connection as invalid
-        parent.handleBrokenConnection();
-        // Invalidate Connection
-        this.activeConnection = null;
-        // Throw Exception
-        throw new PlcRuntimeException("Unable to finish Request!", e);
-    }
-
-    PlcConnection getActiveConnection() {
-        return this.activeConnection;
-    }
-
-    @Override
-    public synchronized void close() throws Exception {
-        logger.debug("Closing cached connection and returning borrowed connection to pool.");
-        // First, close this connection and allow no further operations on it!
-        this.closed = true;
-        // Return the Connection
-        parent.returnConnection(activeConnection);
-        // Invalidate Connection
-        this.activeConnection = null;
-    }
-
-    @Override
-    public PlcConnectionMetadata getMetadata() {
-        if (closed) {
-            throw new IllegalStateException("Trying to get Metadata on a closed Connection!");
-        } else {
-            return this;
-        }
-    }
-
-    @Override
-    public CompletableFuture<Void> ping() {
-        CompletableFuture<Void> future = new CompletableFuture<>();
-        future.completeExceptionally(new PlcUnsupportedOperationException("The connection does not support pinging"));
-        return future;
-    }
-
-    @Override
-    public PlcBrowseRequest.Builder browseRequestBuilder() {
-        if (closed) {
-            throw new IllegalStateException("Trying to build a Request on a closed Connection!");
-        }
-        return new CachedBrowseRequestBuilder(this, this.getActiveConnection().browseRequestBuilder());
-    }
-
-    @Override
-    public PlcReadRequest.Builder readRequestBuilder() {
-        if (closed) {
-            throw new IllegalStateException("Trying to build a Request on a closed Connection!");
-        }
-        return new CachedReadRequestBuilder(this, this.getActiveConnection().readRequestBuilder());
-    }
-
-    @Override
-    public PlcWriteRequest.Builder writeRequestBuilder() {
-        if (closed) {
-            throw new IllegalStateException("Trying to build a Request on a closed Connection!");
-        }
-        return new CachedWriteRequestBuilder(this, this.getActiveConnection().writeRequestBuilder());
-    }
-
-    @Override
-    public PlcSubscriptionRequest.Builder subscriptionRequestBuilder() {
-        if (closed) {
-            throw new IllegalStateException("Trying to build a Request on a closed Connection!");
-        }
-        return new CachedSubscriptionRequestBuilder(this, this.getActiveConnection().subscriptionRequestBuilder());
-    }
-
-    @Override
-    public PlcUnsubscriptionRequest.Builder unsubscriptionRequestBuilder() {
-        if (closed) {
-            throw new IllegalStateException("Trying to build a Request on a closed Connection!");
-        }
-        return new CachedUnsubscriptionRequestBuilder(this, this.getActiveConnection().unsubscriptionRequestBuilder());
-    }
-
-    @Override
-    public boolean canBrowse() {
-        if (closed) {
-            return false;
-        } else {
-            return this.activeConnection.getMetadata().canBrowse();
-        }
-    }
-
-    @Override
-    public boolean canRead() {
-        if (closed) {
-            return false;
-        } else {
-            return this.activeConnection.getMetadata().canRead();
-        }
-    }
-
-    @Override
-    public boolean canWrite() {
-        if (closed) {
-            return false;
-        } else {
-            return this.activeConnection.getMetadata().canWrite();
-        }
-    }
-
-    @Override
-    public boolean canSubscribe() {
-        if (closed) {
-            return false;
-        } else {
-            return this.activeConnection.getMetadata().canSubscribe();
-        }
-    }
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequest.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequest.java
deleted file mode 100644
index 0788748042..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.messages.PlcReadRequest;
-import org.apache.plc4x.java.api.messages.PlcReadResponse;
-import org.apache.plc4x.java.api.model.PlcTag;
-
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-
-public class CachedReadRequest implements PlcReadRequest {
-
-    private final CachedPlcConnection parent;
-    private final PlcReadRequest innerRequest;
-
-    public CachedReadRequest(CachedPlcConnection parent, PlcReadRequest innerRequest) {
-        this.parent = parent;
-        this.innerRequest = innerRequest;
-    }
-
-    @Override
-    public CompletableFuture<? extends PlcReadResponse> execute() {
-        // Only allowed if connection is still active
-        return parent.execute(innerRequest);
-    }
-
-    @Override
-    public int getNumberOfTags() {
-        return innerRequest.getNumberOfTags();
-    }
-
-    @Override
-    public LinkedHashSet<String> getTagNames() {
-        return innerRequest.getTagNames();
-    }
-
-    @Override
-    public PlcTag getTag(String s) {
-        return innerRequest.getTag(s);
-    }
-
-    @Override
-    public List<PlcTag> getTags() {
-        return innerRequest.getTags();
-    }
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequestBuilder.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequestBuilder.java
deleted file mode 100644
index 05804b6237..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedReadRequestBuilder.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.messages.PlcReadRequest;
-import org.apache.plc4x.java.api.model.PlcTag;
-
-public class CachedReadRequestBuilder implements PlcReadRequest.Builder {
-
-    private final CachedPlcConnection parent;
-    private final PlcReadRequest.Builder builder;
-
-    public CachedReadRequestBuilder(CachedPlcConnection parent, PlcReadRequest.Builder builder) {
-        this.parent = parent;
-        this.builder = builder;
-    }
-
-    @Override
-    public PlcReadRequest.Builder addTagAddress(String s, String s1) {
-        builder.addTagAddress(s, s1);
-        return this;
-    }
-
-    @Override
-    public PlcReadRequest.Builder addTag(String name, PlcTag tagQuery) {
-        builder.addTag(name, tagQuery);
-        return this;
-    }
-
-    @Override
-    public PlcReadRequest build() {
-        return new CachedReadRequest(parent, builder.build());
-    }
-
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedSubscriptionRequest.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedSubscriptionRequest.java
deleted file mode 100644
index 1c8ba5e797..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedSubscriptionRequest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.messages.*;
-import org.apache.plc4x.java.api.model.PlcSubscriptionTag;
-
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.function.Consumer;
-
-public class CachedSubscriptionRequest implements PlcSubscriptionRequest {
-
-    private final CachedPlcConnection parent;
-    private final PlcSubscriptionRequest innerRequest;
-
-    public CachedSubscriptionRequest(CachedPlcConnection parent, PlcSubscriptionRequest innerRequest) {
-        this.parent = parent;
-        this.innerRequest = innerRequest;
-    }
-
-    @Override
-    public CompletableFuture<? extends PlcSubscriptionResponse> execute() {
-        // Only allowed if connection is still active
-        return innerRequest.execute();
-    }
-
-    @Override
-    public int getNumberOfTags() {
-        return innerRequest.getNumberOfTags();
-    }
-
-    @Override
-    public LinkedHashSet<String> getTagNames() {
-        return innerRequest.getTagNames();
-    }
-
-    @Override
-    public PlcSubscriptionTag getTag(String name) {
-        return innerRequest.getTag(name);
-    }
-
-    @Override
-    public List<PlcSubscriptionTag> getTags() {
-        return innerRequest.getTags();
-    }
-
-    @Override
-    public Map<String, List<Consumer<PlcSubscriptionEvent>>> getPreRegisteredConsumers() {
-        return innerRequest.getPreRegisteredConsumers();
-    }
-
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedSubscriptionRequestBuilder.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedSubscriptionRequestBuilder.java
deleted file mode 100644
index 759b882d69..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedSubscriptionRequestBuilder.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.messages.PlcSubscriptionEvent;
-import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
-import org.apache.plc4x.java.api.model.PlcTag;
-
-import java.time.Duration;
-import java.util.function.Consumer;
-
-public class CachedSubscriptionRequestBuilder implements PlcSubscriptionRequest.Builder {
-
-    private final CachedPlcConnection parent;
-    private final PlcSubscriptionRequest.Builder builder;
-
-    public CachedSubscriptionRequestBuilder(CachedPlcConnection parent, PlcSubscriptionRequest.Builder builder) {
-        this.parent = parent;
-        this.builder = builder;
-    }
-
-    @Override
-    public PlcSubscriptionRequest build() {
-        return builder.build();
-    }
-
-    @Override
-    public PlcSubscriptionRequest.Builder addCyclicTagAddress(String name, String tagAddress, Duration pollingInterval) {
-        return builder.addCyclicTagAddress(name, tagAddress, pollingInterval);
-    }
-
-    @Override
-    public PlcSubscriptionRequest.Builder addCyclicTag(String name, PlcTag tag, Duration pollingInterval) {
-        return builder.addCyclicTag(name, tag, pollingInterval);
-    }
-
-    @Override
-    public PlcSubscriptionRequest.Builder addChangeOfStateTagAddress(String name, String tagAddress) {
-        return builder.addChangeOfStateTagAddress(name, tagAddress);
-    }
-
-    @Override
-    public PlcSubscriptionRequest.Builder addChangeOfStateTag(String name, PlcTag tag) {
-        return builder.addChangeOfStateTag(name, tag);
-    }
-
-    @Override
-    public PlcSubscriptionRequest.Builder addEventTagAddress(String name, String tagAddress) {
-        return builder.addEventTagAddress(name, tagAddress);
-    }
-
-    @Override
-    public PlcSubscriptionRequest.Builder addEventTag(String name, PlcTag tag) {
-        return builder.addEventTag(name, tag);
-    }
-
-    @Override
-    public PlcSubscriptionRequest.Builder addPreRegisteredConsumer(String name, Consumer<PlcSubscriptionEvent> preRegisteredConsumer) {
-        return builder.addPreRegisteredConsumer(name, preRegisteredConsumer);
-    }
-
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedUnsubscriptionRequest.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedUnsubscriptionRequest.java
deleted file mode 100644
index 2345b5f713..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedUnsubscriptionRequest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.messages.*;
-import org.apache.plc4x.java.api.model.PlcSubscriptionHandle;
-
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-
-public class CachedUnsubscriptionRequest implements PlcUnsubscriptionRequest {
-
-    private final CachedPlcConnection parent;
-    private final PlcUnsubscriptionRequest innerRequest;
-
-    public CachedUnsubscriptionRequest(CachedPlcConnection parent, PlcUnsubscriptionRequest innerRequest) {
-        this.parent = parent;
-        this.innerRequest = innerRequest;
-    }
-
-    @Override
-    public CompletableFuture<PlcUnsubscriptionResponse> execute() {
-        return innerRequest.execute();
-    }
-    @Override
-    public List<PlcSubscriptionHandle> getSubscriptionHandles() {
-        return innerRequest.getSubscriptionHandles();
-    }
-
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedUnsubscriptionRequestBuilder.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedUnsubscriptionRequestBuilder.java
deleted file mode 100644
index 313514add9..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedUnsubscriptionRequestBuilder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.messages.PlcUnsubscriptionRequest;
-import org.apache.plc4x.java.api.model.PlcSubscriptionHandle;
-import org.apache.plc4x.java.api.model.PlcTag;
-
-import java.time.Duration;
-import java.util.Collection;
-import java.util.function.Consumer;
-
-public class CachedUnsubscriptionRequestBuilder implements PlcUnsubscriptionRequest.Builder {
-
-    private final CachedPlcConnection parent;
-    private final PlcUnsubscriptionRequest.Builder builder;
-
-    public CachedUnsubscriptionRequestBuilder(CachedPlcConnection parent, PlcUnsubscriptionRequest.Builder builder) {
-        this.parent = parent;
-        this.builder = builder;
-    }
-
-    @Override
-    public PlcUnsubscriptionRequest build() {
-        return builder.build();
-    }
-
-    @Override
-    public PlcUnsubscriptionRequest.Builder addHandles(PlcSubscriptionHandle plcSubscriptionHandle) {
-        return builder.addHandles(plcSubscriptionHandle);
-    }
-
-    @Override
-    public PlcUnsubscriptionRequest.Builder addHandles(PlcSubscriptionHandle plcSubscriptionHandle, PlcSubscriptionHandle... plcSubscriptionHandles) {
-        return builder.addHandles(plcSubscriptionHandle, plcSubscriptionHandles);
-    }
-
-    @Override
-    public PlcUnsubscriptionRequest.Builder addHandles(Collection<PlcSubscriptionHandle> plcSubscriptionHandles) {
-        return builder.addHandles(plcSubscriptionHandles);
-    }
-
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedWriteRequest.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedWriteRequest.java
deleted file mode 100644
index ec57d11346..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedWriteRequest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.messages.PlcWriteRequest;
-import org.apache.plc4x.java.api.messages.PlcWriteResponse;
-import org.apache.plc4x.java.api.model.PlcTag;
-import org.apache.plc4x.java.api.value.PlcValue;
-
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-
-public class CachedWriteRequest implements PlcWriteRequest {
-
-    private final CachedPlcConnection parent;
-    private final PlcWriteRequest innerRequest;
-
-    public CachedWriteRequest(CachedPlcConnection parent, PlcWriteRequest innerRequest) {
-        this.parent = parent;
-        this.innerRequest = innerRequest;
-    }
-
-    @Override
-    public CompletableFuture<? extends PlcWriteResponse> execute() {
-        // Only allowed if connection is still active
-        return parent.execute(innerRequest);
-    }
-
-    @Override
-    public int getNumberOfTags() {
-        return innerRequest.getNumberOfTags();
-    }
-
-    @Override
-    public LinkedHashSet<String> getTagNames() {
-        return innerRequest.getTagNames();
-    }
-
-    @Override
-    public PlcTag getTag(String s) {
-        return innerRequest.getTag(s);
-    }
-
-    @Override
-    public List<PlcTag> getTags() {
-        return innerRequest.getTags();
-    }
-
-    @Override
-    public int getNumberOfValues(String name) {
-        return innerRequest.getNumberOfValues(name);
-    }
-
-    @Override
-    public PlcValue getPlcValue(String name) {
-        return innerRequest.getPlcValue(name);
-    }
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedWriteRequestBuilder.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedWriteRequestBuilder.java
deleted file mode 100644
index 49d2da1fbd..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedWriteRequestBuilder.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.messages.PlcWriteRequest;
-import org.apache.plc4x.java.api.model.PlcTag;
-
-public class CachedWriteRequestBuilder implements PlcWriteRequest.Builder {
-
-    private final CachedPlcConnection parent;
-    private final PlcWriteRequest.Builder builder;
-
-    public CachedWriteRequestBuilder(CachedPlcConnection parent, PlcWriteRequest.Builder builder) {
-        this.parent = parent;
-        this.builder = builder;
-    }
-
-    @Override
-    public PlcWriteRequest.Builder addTagAddress(String name, String tagAddress, Object... values) {
-        builder.addTagAddress(name, tagAddress, values);
-        return this;
-    }
-
-    @Override
-    public PlcWriteRequest.Builder addTag(String name, PlcTag tag, Object... values) {
-        builder.addTag(name, tag, values);
-        return this;
-    }
-
-    @Override
-    public PlcWriteRequest build() {
-        return new CachedWriteRequest(parent, builder.build());
-    }
-
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManager.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManager.java
deleted file mode 100644
index 12523b320f..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManager.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.authentication.PlcAuthentication;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-
-import javax.management.ObjectName;
-import java.lang.management.ManagementFactory;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Function;
-
-/**
- * Pool that sits on top of the {@link CachedDriverManager}.
- * <p>
- * This class is thread safe!
- */
-public class PooledDriverManager extends PlcDriverManager implements PooledDriverManagerMBean {
-
-    private final Function<String, CachedDriverManager> factory;
-    private final Map<String, CachedDriverManager> cachedManagers = new ConcurrentHashMap<>();
-
-    public PooledDriverManager() {
-        this(new PlcDriverManager());
-    }
-
-    public PooledDriverManager(PlcDriverManager driverManager) {
-        this.factory = key -> {
-            return new CachedDriverManager(key, () -> {
-                try {
-                    return driverManager.getConnection(key);
-                } catch (PlcConnectionException e) {
-                    throw new RuntimeException(e);
-                }
-            });
-        };
-
-        // Register as MBean
-        try {
-            ManagementFactory.getPlatformMBeanServer().registerMBean(this, new ObjectName("org.pragmaticindustries.cockpit.plc:name=connection-pool"));
-        } catch (Exception e) {
-            // Do nothing.
-        }
-    }
-
-    PooledDriverManager(Function<String, CachedDriverManager> factory) {
-        this.factory = factory;
-    }
-
-    @Override
-    public PlcConnection getConnection(String url) throws PlcConnectionException {
-        return cachedManagers.computeIfAbsent(url, this.factory).getConnection(url);
-    }
-
-    @Override
-    public PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException {
-        throw new UnsupportedOperationException();
-    }
-
-    Map<String, CachedDriverManager> getCachedManagers() {
-        return this.cachedManagers;
-    }
-
-    @Override
-    public String[] getConnectedUrls() {
-        return this.cachedManagers.keySet().toArray(new String[0]);
-    }
-}
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerMBean.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerMBean.java
deleted file mode 100644
index 6a2bdc1cce..0000000000
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerMBean.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-public interface PooledDriverManagerMBean {
-
-    String[] getConnectedUrls();
-}
diff --git a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/cache/CachedPlcConnectionManagerTest.java b/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/cache/CachedPlcConnectionManagerTest.java
new file mode 100644
index 0000000000..9d71bc4701
--- /dev/null
+++ b/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/cache/CachedPlcConnectionManagerTest.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.utils.cache;
+
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import java.time.Duration;
+
+public class CachedPlcConnectionManagerTest {
+
+    /**
+     * This is the simplest possible test. Here the ConnectionManager is used exactly once.
+     * So not really much of the caching we can test, but it tests if we're creating connections the right way.
+     *
+     * @throws PlcConnectionException something went wrong
+     */
+    @Test
+    public void testSingleConnectionRequestTest() throws PlcConnectionException {
+        PlcConnectionManager mockConnectionManager = Mockito.mock(PlcConnectionManager.class);
+        CachedPlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder(mockConnectionManager).build();
+
+        // Get the connection for the first time.
+        try (PlcConnection connection = connectionManager.getConnection("test")) {
+            Assertions.assertInstanceOf(LeasedPlcConnection.class, connection);
+        } catch (Exception e) {
+            Assertions.fail("Not expecting an exception here", e);
+        }
+
+        // Check getConnection was called on the mockConnectionManager instance exactly once.
+        Mockito.verify(mockConnectionManager, Mockito.times(1)).getConnection("test");
+    }
+
+    /**
+     * This test tries to get one connection two times after each other, in this case for the second time the
+     * connection should not be created, but the initial one be reused.
+     *
+     * @throws PlcConnectionException something went wrong
+     */
+    @Test
+    public void testDoubleConnectionRequestTest() throws PlcConnectionException {
+        PlcConnectionManager mockConnectionManager = Mockito.mock(PlcConnectionManager.class);
+        CachedPlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder(mockConnectionManager).build();
+
+        // Get the connection for the first time.
+        try (PlcConnection connection = connectionManager.getConnection("test")) {
+            Assertions.assertInstanceOf(LeasedPlcConnection.class, connection);
+        } catch (Exception e) {
+            Assertions.fail("Not expecting an exception here", e);
+        }
+
+        // Get the same connection a second time.
+        try (PlcConnection connection = connectionManager.getConnection("test")) {
+            Assertions.assertInstanceOf(LeasedPlcConnection.class, connection);
+        } catch (Exception e) {
+            Assertions.fail("Not expecting an exception here", e);
+        }
+
+        // Check getConnection was called on the mockConnectionManager instance exactly once.
+        Mockito.verify(mockConnectionManager, Mockito.times(1)).getConnection("test");
+    }
+
+    /**
+     * In contrast to the previous test, in this case different connection strings are used and the
+     * cache should create two different connections.
+     *
+     * @throws PlcConnectionException something went wrong
+     */
+    @Test
+    public void testDoubleConnectionRequestWithDifferentConnectionsTest() throws PlcConnectionException {
+        PlcConnectionManager mockConnectionManager = Mockito.mock(PlcConnectionManager.class);
+        CachedPlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder(mockConnectionManager).build();
+
+        // Get the connection for the first time.
+        try (PlcConnection connection = connectionManager.getConnection("test")) {
+            Assertions.assertInstanceOf(LeasedPlcConnection.class, connection);
+        } catch (Exception e) {
+            Assertions.fail("Not expecting an exception here", e);
+        }
+
+        // Get the same connection a second time.
+        try (PlcConnection connection = connectionManager.getConnection("test-other")) {
+            Assertions.assertInstanceOf(LeasedPlcConnection.class, connection);
+        } catch (Exception e) {
+            Assertions.fail("Not expecting an exception here", e);
+        }
+
+        // Check getConnection was called on the mockConnectionManager instance twice, as they are different connections.
+        Mockito.verify(mockConnectionManager, Mockito.times(2)).getConnection(Mockito.any());
+    }
+
+    /**
+     * This test is almost the same setup as the double connection test, but in this case the one usage exceeds
+     * the maximum wait time, so the connection-cache gives up waiting and returns an exception.
+     *
+     * @throws PlcConnectionException something went wrong
+     */
+    @Test
+    public void testDoubleConnectionRequestTimeoutTest() throws Exception {
+        PlcConnectionManager mockConnectionManager = Mockito.mock(PlcConnectionManager.class);
+        CachedPlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder(mockConnectionManager).withMaxWaitTime(Duration.ofMillis(50)).build();
+
+        // Get the connection for the first time.
+        (new Thread(() -> {
+            try (PlcConnection connection = connectionManager.getConnection("test")) {
+                Assertions.assertInstanceOf(LeasedPlcConnection.class, connection);
+                // Sleep for a second.
+                Thread.sleep(100L);
+            } catch (Exception e) {
+                Assertions.fail("Not expecting an exception here", e);
+            }
+        })).start();
+
+        // This is needed as starting the previous thread seems to take a little-bit of time.
+        Thread.sleep(1L);
+
+        // Get the same connection a second time.
+        try (PlcConnection ignored = connectionManager.getConnection("test")) {
+            Assertions.fail("Was expecting an exception here");
+        } catch (Exception e) {
+            Assertions.assertInstanceOf(PlcConnectionException.class, e);
+            Assertions.assertEquals("Error acquiring lease for connection", e.getMessage());
+        }
+
+        // Check getConnection was called on the mockConnectionManager instance exactly once.
+        Mockito.verify(mockConnectionManager, Mockito.times(1)).getConnection("test");
+    }
+
+    /**
+     * This is the simplest possible test. Here the ConnectionManager is used exactly once.
+     * So not really much of the caching we can test, but it tests if we're creating connections the right way.
+     *
+     * @throws PlcConnectionException something went wrong
+     */
+    @Test
+    public void testSingleConnectionRequestWithTimeoutTest() throws PlcConnectionException {
+        PlcConnectionManager mockConnectionManager = Mockito.mock(PlcConnectionManager.class);
+        CachedPlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder(mockConnectionManager).withMaxLeaseTime(Duration.ofMillis(10)).build();
+
+        // Get the connection for the first time.
+        try (PlcConnection connection = connectionManager.getConnection("test")) {
+            Assertions.assertInstanceOf(LeasedPlcConnection.class, connection);
+            Thread.sleep(100L);
+        } catch (Exception e) {
+            Assertions.assertInstanceOf(PlcRuntimeException.class, e);
+            Assertions.assertEquals("Error trying to return lease from invalid connection", e.getMessage());
+        }
+
+        // Check getConnection was called on the mockConnectionManager instance exactly once.
+        Mockito.verify(mockConnectionManager, Mockito.times(1)).getConnection("test");
+    }
+
+}
diff --git a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java b/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/cache/ManualTest.java
similarity index 50%
copy from plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
copy to plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/cache/ManualTest.java
index c68927164f..60bc40dedd 100644
--- a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
+++ b/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/cache/ManualTest.java
@@ -16,20 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.profinet;
+package org.apache.plc4x.java.utils.cache;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
 
-public class ManualProfinetIoTest {
+public class ManualTest {
 
-    public static void main(String[] args) throws Exception {
-        final PlcConnection connection = new PlcDriverManager().getConnection("profinet://192.168.24.31");
-        final PlcReadRequest readRequest = connection.readRequestBuilder().addTagAddress("test", "").build();
-        final PlcReadResponse plcReadResponse = readRequest.execute().get();
-        System.out.println(plcReadResponse);
+    public static void main(String[] args) {
+        CachedPlcConnectionManager cachedPlcConnectionManager = CachedPlcConnectionManager.getBuilder(new DefaultPlcDriverManager()).build();
+        for (int i = 0; i < 100; i++){
+            try (PlcConnection connection = cachedPlcConnectionManager.getConnection("ads:tcp://192.168.23.20?sourceAmsNetId=192.168.23.200.1.1&sourceAmsPort=65534&targetAmsNetId=192.168.23.20.1.1&targetAmsPort=851")) {
+                PlcReadResponse plcReadResponse = connection.readRequestBuilder().addTagAddress("var", "MAIN.hurz_REAL").build().execute().get();
+                System.out.printf("Run %d: Value: %f%n", i, plcReadResponse.getFloat("var"));
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
     }
 
 }
diff --git a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerIT.java b/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerIT.java
deleted file mode 100644
index 8a25d6e18b..0000000000
--- a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerIT.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.exceptions.PlcException;
-import org.apache.plc4x.java.mock.connection.MockConnection;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-/**
- * Multi Threading Test
- */
-class CachedDriverManagerIT {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(CachedDriverManagerIT.class);
-
-    @Test
-    void connectWithMultipleThreads() throws InterruptedException, PlcException {
-        ExecutorService executorService = Executors.newFixedThreadPool(4);
-
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        MockConnection plcMockConnection = mock(MockConnection.class);
-        when(mock.create()).thenReturn(plcMockConnection);
-
-        CachedDriverManager driverManager = new CachedDriverManager("", mock, 10_000);
-
-        AtomicInteger errorCounter = new AtomicInteger(0);
-        AtomicInteger successCounter = new AtomicInteger(0);
-
-        for (int i = 1; i <= 100; i++) {
-            executorService.submit(() -> {
-                try {
-                    driverManager.getConnection("").close();
-                    successCounter.incrementAndGet();
-                } catch (Exception e) {
-                    LOGGER.warn("error", e);
-                    errorCounter.incrementAndGet();
-                }
-            });
-        }
-
-        executorService.shutdown();
-
-        boolean forced = executorService.awaitTermination(50, TimeUnit.SECONDS);
-
-        // If this is false, a thread was still hanging => something failed
-        assertTrue(forced);
-
-        assertEquals(100, successCounter.get());
-        assertEquals(0, errorCounter.get());
-    }
-}
\ No newline at end of file
diff --git a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMT.java b/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMT.java
deleted file mode 100644
index 6a4cdafdf4..0000000000
--- a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerMT.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.apache.plc4x.java.api.messages.PlcReadResponse;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-@Disabled("These should be run manually")
-class CachedDriverManagerMT {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(CachedDriverManagerMT.class);
-
-    public static final String PLC_IP = "s7://192.168.167.210/1/1";
-//    public static final String PLC_IP = "s7://127.0.0.1/1/1";
-
-    @Test
-    void queryPlc() throws InterruptedException {
-        ScheduledExecutorService pool = Executors.newScheduledThreadPool(4);
-
-        CachedDriverManager driverManager = new CachedDriverManager(PLC_IP, () -> {
-            try {
-                PlcConnection connection = new PlcDriverManager().getConnection(PLC_IP);
-                // Kill it every second
-                pool.schedule(() -> {
-                    try {
-                        System.out.println("Close...");
-                        connection.close();
-                    } catch (Exception e) {
-                        LOGGER.warn("error", e);
-                    }
-                }, 1, TimeUnit.SECONDS);
-                return connection;
-            } catch (PlcConnectionException e) {
-                throw new RuntimeException("", e);
-            }
-        });
-
-        for (int i = 1; i <= 100_000; i++) {
-            pool.submit(() -> {
-                try (PlcConnection conn = driverManager.getConnection(PLC_IP)) {
-                    PlcReadResponse response = conn.readRequestBuilder().addTagAddress("asdf", "%DB444:14.0:BOOL").build().execute().get(500, TimeUnit.MILLISECONDS);
-                } catch (Exception e) {
-                    // Intentionally do nothing...
-                }
-            });
-            Thread.sleep(1);
-        }
-
-        pool.shutdown();
-        pool.awaitTermination(1, TimeUnit.DAYS);
-    }
-
-    @Test
-    void queryPlcWithPool() throws InterruptedException {
-        ScheduledExecutorService pool = Executors.newScheduledThreadPool(4);
-
-        PooledDriverManager driverManager = new PooledDriverManager();
-
-        for (int i = 1; i <= 100_000; i++) {
-            pool.submit(() -> {
-                try (PlcConnection conn = driverManager.getConnection(PLC_IP)) {
-                    PlcReadResponse response = conn.readRequestBuilder().addTagAddress("asdf", "%DB444:14.0:BOOL").build().execute().get(500, TimeUnit.MILLISECONDS);
-                } catch (Exception e) {
-                    // Intentionally do nothing...
-                }
-            });
-            Thread.sleep(1);
-        }
-
-        pool.shutdown();
-        pool.awaitTermination(1, TimeUnit.DAYS);
-    }
-
-    @Test
-    void borrowAndDontReturn() throws InterruptedException {
-        ScheduledExecutorService pool = Executors.newScheduledThreadPool(4);
-
-        PooledDriverManager driverManager = new PooledDriverManager();
-
-        for (int i = 1; i <= 10_000; i++) {
-            pool.submit(() -> {
-                try {
-                    PlcConnection conn = driverManager.getConnection(PLC_IP);
-                    System.out.println("Successfully got a Connection...");
-                    PlcReadResponse response = conn.readRequestBuilder().addTagAddress("asdf", "%DB444:14.0:BOOL").build().execute().get(500, TimeUnit.MILLISECONDS);
-                    System.out.println("Response: " + response.getBoolean("asdf"));
-                } catch (PlcConnectionException | InterruptedException | ExecutionException | TimeoutException e) {
-                    // Intentionally do Nothing...
-                }
-            });
-            Thread.sleep(1);
-        }
-
-        pool.shutdown();
-        pool.awaitTermination(1, TimeUnit.DAYS);
-    }
-}
\ No newline at end of file
diff --git a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerTest.java b/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerTest.java
deleted file mode 100644
index fb5d35a735..0000000000
--- a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedDriverManagerTest.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.apache.plc4x.java.api.exceptions.PlcException;
-import org.apache.plc4x.java.api.messages.PlcReadRequest;
-import org.apache.plc4x.java.mock.connection.MockConnection;
-import org.assertj.core.api.WithAssertions;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@Disabled("disabled due to conccurency issues with occasionally failing tests")
-class CachedDriverManagerTest implements WithAssertions {
-
-    @Test
-    void noConnectionWithoutRequest() throws PlcException {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        CachedDriverManager driverManager = new CachedDriverManager("", mock);
-
-        verify(mock, never()).create();
-    }
-
-    @Test
-    void establishConnectionAtFirstRequest() throws Exception {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        CachedDriverManager driverManager = new CachedDriverManager("", mock);
-
-        driverManager.getConnection("").close();
-
-        verify(mock, timeout(2_000).times(1)).create();
-    }
-
-    @Test
-    void returnConnectionWhenIsActive() throws Exception {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        CachedDriverManager driverManager = new CachedDriverManager("", mock);
-
-        driverManager.getConnection("").close();
-//
-//        verify(mock, timeout(500).times(1)).get();
-
-        // State should now be Connected
-        assertThat(driverManager.getState()).isEqualByComparingTo(CachedDriverManager.ConnectionState.AVAILABLE);
-        Assertions.assertDoesNotThrow(() -> driverManager.getConnection(""));
-        assertThat(driverManager.getState()).isEqualByComparingTo(CachedDriverManager.ConnectionState.BORROWED);
-    }
-
-    @Test
-    void freeConnectionAfterReturn() throws Exception {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        CachedDriverManager driverManager = new CachedDriverManager("", mock);
-
-        // Get Connmection
-        PlcConnection connection = driverManager.getConnection("");
-        // Close the Connection
-        assertThat(driverManager.getState()).isEqualByComparingTo(CachedDriverManager.ConnectionState.BORROWED);
-        connection.close();
-        assertThat(driverManager.getState()).isEqualByComparingTo(CachedDriverManager.ConnectionState.AVAILABLE);
-    }
-
-    @Test
-    void useClosedConnection() throws Exception {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        CachedDriverManager driverManager = new CachedDriverManager("", mock);
-
-        // Get Connmection
-        PlcConnection connection = driverManager.getConnection("");
-        // Close the Connection
-        connection.close();
-        assertThrows(IllegalStateException.class, () -> connection.readRequestBuilder());
-    }
-
-    @Test
-    void useClosedConnection2() throws Exception {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        MockConnection plcMockConnection = mock(MockConnection.class);
-        when(mock.create()).thenReturn(plcMockConnection);
-        when(plcMockConnection.readRequestBuilder()).thenReturn(Mockito.mock(PlcReadRequest.Builder.class));
-
-        CachedDriverManager driverManager = new CachedDriverManager("", mock);
-
-        // Get Connmection
-        PlcConnection connection = driverManager.getConnection("");
-        // Close the Connection
-        PlcReadRequest.Builder builder = connection.readRequestBuilder();
-        PlcReadRequest request = builder.addTagAddress("", "").build();
-        connection.close();
-        assertThrows(IllegalStateException.class, () -> request.execute());
-    }
-
-    @Test
-    void multipleRequests_allbutfirstFail() throws PlcException {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        MockConnection plcMockConnection = mock(MockConnection.class);
-        when(mock.create()).thenReturn(plcMockConnection);
-        when(plcMockConnection.readRequestBuilder()).thenReturn(Mockito.mock(PlcReadRequest.Builder.class));
-
-        CachedDriverManager driverManager = new CachedDriverManager("", mock);
-
-        // Get Connmection
-        PlcConnection connection = driverManager.getConnection("");
-
-        // Try to get another one -> should failt
-        assertThrows(PlcConnectionException.class, () -> driverManager.getConnection(""));
-    }
-
-    @Test
-    void initialRequests_doesNotFail_dueToQueue() throws PlcConnectionException {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        MockConnection plcMockConnection = mock(MockConnection.class);
-        when(mock.create()).thenReturn(plcMockConnection);
-
-        CachedDriverManager driverManager = new CachedDriverManager("", mock, 3_000);
-
-        PlcConnection connection = driverManager.getConnection("");
-
-        assertNotNull(connection);
-    }
-
-    @Test
-    @Disabled
-    void twoRequests_firstTakesLong_secondsTimesOut() throws PlcConnectionException, InterruptedException, ExecutionException, TimeoutException {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        MockConnection plcMockConnection = mock(MockConnection.class);
-        when(mock.create()).thenReturn(plcMockConnection);
-        when(plcMockConnection.readRequestBuilder()).thenReturn(Mockito.mock(PlcReadRequest.Builder.class));
-
-        CachedDriverManager driverManager = new CachedDriverManager("", mock, 5_000);
-
-        CompletableFuture<PlcConnection> future1 = CompletableFuture.supplyAsync(() -> {
-            try {
-                return driverManager.getConnection("");
-            } catch (PlcConnectionException e) {
-                throw new RuntimeException();
-            }
-        });
-
-        CompletableFuture<PlcConnection> future2 = CompletableFuture.supplyAsync(() -> {
-            try {
-                return driverManager.getConnection("");
-            } catch (PlcConnectionException e) {
-                throw new RuntimeException();
-            }
-        });
-
-        PlcConnection conn1 = future1.get(1, TimeUnit.SECONDS);
-        assertThrows(Exception.class, () -> future2.get());
-    }
-
-    @Test
-    @Disabled
-    void twoRequests_firstIsFast_secondWorksAlso() throws Exception {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        MockConnection plcMockConnection = mock(MockConnection.class);
-        when(mock.create()).thenReturn(plcMockConnection);
-        when(plcMockConnection.readRequestBuilder()).thenReturn(Mockito.mock(PlcReadRequest.Builder.class));
-
-        CachedDriverManager driverManager = new CachedDriverManager("", mock, 5_000);
-
-        CompletableFuture<PlcConnection> future1 = CompletableFuture.supplyAsync(() -> {
-            try {
-                return driverManager.getConnection("");
-            } catch (PlcConnectionException e) {
-                throw new RuntimeException(e);
-            }
-        });
-
-        CompletableFuture<PlcConnection> future2 = CompletableFuture.supplyAsync(() -> {
-            try {
-                return driverManager.getConnection("");
-            } catch (PlcConnectionException e) {
-                throw new RuntimeException(e);
-            }
-        });
-
-        // Get and directly close the first one
-        assertDoesNotThrow(() -> {
-            future1.get(1, TimeUnit.SECONDS).close();
-            future2.get(1, TimeUnit.SECONDS).close();
-        });
-    }
-
-    @Test
-    void killBorrowedConnectionWhenRunningLong() throws PlcConnectionException, InterruptedException {
-        PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
-        MockConnection plcMockConnection = mock(MockConnection.class);
-        when(mock.create()).thenReturn(plcMockConnection);
-        when(plcMockConnection.readRequestBuilder()).thenReturn(Mockito.mock(PlcReadRequest.Builder.class));
-
-        CachedDriverManager driverManager = new CachedDriverManager("", mock);
-
-        // Get Connmection
-        PlcConnection connection = driverManager.getConnection("");
-
-        // This should work
-        connection.readRequestBuilder();
-
-        TimeUnit.SECONDS.sleep(6);
-
-        // If we wait to long, the connection should become invalid
-        assertThrows(IllegalStateException.class, () -> connection.readRequestBuilder());
-
-        // And the Pool should once again have a connection
-        assertThat(driverManager.getState())
-            .isEqualTo(CachedDriverManager.ConnectionState.DISCONNECTED);
-    }
-}
\ No newline at end of file
diff --git a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnectionTest.java b/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnectionTest.java
deleted file mode 100644
index 2b349325f5..0000000000
--- a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnectionTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.messages.PlcReadResponse;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-class CachedPlcConnectionTest {
-
-    @Test
-    void whenReadFutureFails_handleGracefully() {
-        final CachedDriverManager driverManager = Mockito.mock(CachedDriverManager.class);
-        final PlcConnection mockConnection = Mockito.mock(PlcConnection.class, Mockito.RETURNS_DEEP_STUBS);
-
-        when(mockConnection.readRequestBuilder().build().execute()).thenAnswer(invocation -> {
-            final CompletableFuture<? extends PlcReadResponse> future = new CompletableFuture<>();
-            new Timer().schedule(new TimerTask() {
-                @Override
-                public void run() {
-                    future.completeExceptionally(new RuntimeException("abc"));
-                }
-            }, TimeUnit.SECONDS.toMillis(2));
-            return future;
-        });
-
-        final CachedPlcConnection connection = new CachedPlcConnection(driverManager, mockConnection);
-
-        try {
-            connection.readRequestBuilder()
-                .addTagAddress("a", "b")
-                .build()
-                .execute()
-                .get(5, TimeUnit.SECONDS);
-        } catch (Exception e) {
-            // Do nothing...
-        }
-
-        verify(driverManager).handleBrokenConnection();
-    }
-
-    @Test
-    void whenReadFutureTimesOut_handleGracefully() {
-        final CachedDriverManager driverManager = Mockito.mock(CachedDriverManager.class);
-        final PlcConnection mockConnection = Mockito.mock(PlcConnection.class, Mockito.RETURNS_DEEP_STUBS);
-
-        when(mockConnection.readRequestBuilder().build().execute()).thenAnswer(invocation -> {
-            // Return a Future that will never end!
-            return new CompletableFuture<PlcReadResponse>();
-        });
-
-        final CachedPlcConnection connection = new CachedPlcConnection(driverManager, mockConnection);
-
-        try {
-            connection.readRequestBuilder()
-                .addTagAddress("a", "b")
-                .build()
-                .execute()
-                .get(10, TimeUnit.SECONDS);
-        } catch (Exception e) {
-            // Do nothing...
-        }
-
-        verify(driverManager).handleBrokenConnection();
-    }
-
-}
\ No newline at end of file
diff --git a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerTest.java b/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerTest.java
deleted file mode 100644
index 479b61df7a..0000000000
--- a/plc4j/tools/connection-cache/src/test/java/org/apache/plc4x/java/utils/connectionpool2/PooledDriverManagerTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool2;
-
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.assertj.core.api.WithAssertions;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-class PooledDriverManagerTest implements WithAssertions {
-
-    @Test
-    void getCachedDriverManager() throws PlcConnectionException {
-        CachedDriverManager mock = Mockito.mock(CachedDriverManager.class, Mockito.RETURNS_DEEP_STUBS);
-        PooledDriverManager driverManager = new PooledDriverManager(key -> mock);
-
-        assertThat(driverManager.getCachedManagers().size()).isEqualTo(0);
-        PlcConnection connection = driverManager.getConnection("abc");
-
-        assertThat(driverManager.getCachedManagers())
-            .containsValue(mock)
-            .containsKey("abc")
-            .hasSize(1);
-
-        verify(mock, times(1)).getConnection("abc");
-    }
-}
\ No newline at end of file
diff --git a/plc4j/tools/connection-cache/src/test/resources/logback-test.xml b/plc4j/tools/connection-cache/src/test/resources/logback-test.xml
index 65c0d3d01f..c404198426 100644
--- a/plc4j/tools/connection-cache/src/test/resources/logback-test.xml
+++ b/plc4j/tools/connection-cache/src/test/resources/logback-test.xml
@@ -27,7 +27,9 @@
     </encoder>
   </appender>
 
-  <root level="error">
+  <logger name="org.apache.plc4x.java.utils.cache" level="debug"/>
+
+  <root level="info">
     <appender-ref ref="STDOUT" />
   </root>
 
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKey.java b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKey.java
deleted file mode 100644
index 520517c777..0000000000
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKey.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool;
-
-import org.apache.plc4x.java.api.authentication.PlcAuthentication;
-
-import java.util.Objects;
-
-public abstract class PoolKey {
-    protected final String url;
-    protected final PlcAuthentication plcAuthentication;
-
-    public PoolKey(String url, PlcAuthentication plcAuthentication) {
-        this.url = url;
-        this.plcAuthentication = plcAuthentication;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public PlcAuthentication getPlcAuthentication() {
-        return plcAuthentication;
-    }
-
-    /**
-     * @return the part of the url that should be pooled.
-     */
-    public abstract String getPoolableKey();
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof PoolKey)) {
-            return false;
-        }
-        PoolKey poolKey = (PoolKey) o;
-        return Objects.equals(getPoolableKey(), poolKey.getPoolableKey()) &&
-            Objects.equals(plcAuthentication, poolKey.plcAuthentication);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(getPoolableKey(), plcAuthentication);
-    }
-
-    @Override
-    public String toString() {
-        return "PoolKey{" +
-            "url='" + url + '\'' +
-            (plcAuthentication != PooledPlcDriverManager.noPlcAuthentication ? ", plcAuthentication=" + plcAuthentication : "") +
-            '}';
-    }
-}
\ No newline at end of file
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactory.java b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactory.java
deleted file mode 100644
index bcd6e2a73a..0000000000
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactory.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool;
-
-import org.apache.plc4x.java.api.authentication.PlcAuthentication;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Objects;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class PoolKeyFactory {
-
-    // TODO 11.12.18 jf: add a property to the drivers to keep this generic
-    public PoolKey getPoolKey(String url, PlcAuthentication plcAuthentication) throws PlcConnectionException {
-        Objects.requireNonNull(url);
-        URI connectionUri;
-        try {
-            connectionUri = new URI(url);
-        } catch (URISyntaxException e) {
-            throw new PlcConnectionException("Invalid plc4j connection string '" + url + "'", e);
-        }
-        String protocol = connectionUri.getScheme().toLowerCase();
-        switch (protocol) {
-            // Currently this is disabled due to 2 reasons
-            // First, see PLC4X-223 it needs to be migrated to new URI Syntax
-            // Second, we have to decide which parameters uniquely identify a connection and which
-            // not. See PLC4X-224
-            /*
-            case "s7":
-                return new PoolKey(url, plcAuthentication) {
-                    private final Pattern s7URIPattern = Pattern.compile("^(?<poolablePart>s7://((?<ip>[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3})|(?<hostname>[a-zA-Z0-9\\.\\-]+))(:(?<port>[0-9]{1,5}))?)(?<params>\\?.*)?");
-
-                    @Override
-                    public String getPoolableKey() {
-                        Matcher matcher = s7URIPattern.matcher(url);
-                        if (!matcher.matches()) {
-                            throw new IllegalArgumentException(url + " doesn't match " + s7URIPattern);
-                        }
-                        return Objects.requireNonNull(matcher.group("poolablePart"));
-                    }
-                };
-            case "ads":
-                return new PoolKey(url, plcAuthentication) {
-                    private final Pattern amsPortPattern = Pattern.compile("\\d+");
-                    private final Pattern amsNetIdPattern = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
-                    private final Pattern adsAddressPattern =
-                        Pattern.compile("(?<targetAmsNetId>" + amsNetIdPattern + "):(?<targetAmsPort>" + amsPortPattern + ")"
-                            + "(/"
-                            + "(?<sourceAmsNetId>" + amsNetIdPattern + "):(?<sourceAmsPort>" + amsPortPattern + ")"
-                            + ")?");
-                    private final Pattern inetAddressPattern = Pattern.compile("tcp://(?<host>[\\w.]+)(:(?<port>\\d*))?");
-                    private final Pattern serialPattern = Pattern.compile("serial://(?<serialDefinition>((?!/\\d).)*)");
-                    private final Pattern adsUriPattern = Pattern.compile("^(?<poolablePart>ads:(" + inetAddressPattern + "|" + serialPattern + "))/" + adsAddressPattern + "(\\?.*)?");
-
-                    @Override
-                    public String getPoolableKey() {
-                        Matcher matcher =
-                            adsUriPattern.matcher(url);
-                        if (!matcher.matches()) {
-                            throw new IllegalArgumentException(url + " doesn't match " + adsUriPattern);
-                        }
-                        return Objects.requireNonNull(matcher.group("poolablePart"));
-                    }
-                };
-            case "modbus":
-                return new PoolKey(url, plcAuthentication) {
-                    private final Pattern inetAddressPattern = Pattern.compile("tcp://(?<host>[\\w.]+)(:(?<port>\\d*))?");
-                    private final Pattern serialPattern = Pattern.compile("serial://(?<serialDefinition>((?!/\\d).)*)");
-                    private final Pattern modbusUriPattern = Pattern.compile("^(?<poolablePart>modbus-tcp:(" + inetAddressPattern + "|" + serialPattern + "))/?" + "(?<params>\\?.*)?");
-
-                    @Override
-                    public String getPoolableKey() {
-                        Matcher matcher = modbusUriPattern.matcher(url);
-                        if (!matcher.matches()) {
-                            throw new IllegalArgumentException(url + " doesn't match " + modbusUriPattern);
-                        }
-                        return Objects.requireNonNull(matcher.group("poolablePart"));
-                    }
-                };
-             */
-            default:
-                return new PoolKey(url, plcAuthentication) {
-                    @Override
-                    public String getPoolableKey() {
-                        return url;
-                    }
-                };
-        }
-    }
-}
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcConnectionFactory.java b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcConnectionFactory.java
deleted file mode 100644
index cada16b393..0000000000
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcConnectionFactory.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool;
-
-import org.apache.commons.pool2.BaseKeyedPooledObjectFactory;
-import org.apache.commons.pool2.PooledObject;
-import org.apache.commons.pool2.impl.DefaultPooledObject;
-import org.apache.plc4x.java.api.PlcConnection;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class PooledPlcConnectionFactory extends BaseKeyedPooledObjectFactory<PoolKey, PlcConnection> {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(PooledPlcConnectionFactory.class);
-
-    @Override
-    public PooledObject<PlcConnection> wrap(PlcConnection plcConnection) {
-        LOGGER.debug("Wrapping connection {}", plcConnection);
-        return new DefaultPooledObject<>(plcConnection);
-    }
-
-    @Override
-    public void destroyObject(PoolKey key, PooledObject<PlcConnection> p) throws Exception {
-        p.getObject().close();
-    }
-
-    @Override
-    public boolean validateObject(PoolKey key, PooledObject<PlcConnection> p) {
-        return p.getObject().isConnected();
-    }
-}
diff --git a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManager.java b/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManager.java
deleted file mode 100644
index ee6a340d29..0000000000
--- a/plc4j/tools/connection-pool/src/main/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManager.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool;
-
-import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.commons.pool2.KeyedObjectPool;
-import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.authentication.PlcAuthentication;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Proxy;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public class PooledPlcDriverManager extends PlcDriverManager {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(PooledPlcDriverManager.class);
-
-    private KeyedObjectPool<PoolKey, PlcConnection> keyedObjectPool;
-
-    // Marker class do detected a non null value
-    static final NoPlcAuthentication noPlcAuthentication = new NoPlcAuthentication();
-
-    private final PoolKeyFactory poolKeyFactory;
-
-    public PooledPlcDriverManager() {
-        this(GenericKeyedObjectPool::new);
-    }
-
-    public PooledPlcDriverManager(PoolKeyFactory poolKeyFactory) {
-        this(GenericKeyedObjectPool::new, poolKeyFactory);
-    }
-
-    public PooledPlcDriverManager(ClassLoader classLoader) {
-        this(classLoader, new PoolKeyFactory());
-    }
-
-    public PooledPlcDriverManager(ClassLoader classLoader, PoolKeyFactory poolKeyFactory) {
-        super(classLoader);
-        setFromPoolCreator(GenericKeyedObjectPool::new);
-        this.poolKeyFactory = poolKeyFactory;
-    }
-
-    public PooledPlcDriverManager(PoolCreator poolCreator) {
-        this(poolCreator, new PoolKeyFactory());
-    }
-
-    public PooledPlcDriverManager(PoolCreator poolCreator, PoolKeyFactory poolKeyFactory) {
-        setFromPoolCreator(poolCreator);
-        this.poolKeyFactory = poolKeyFactory;
-    }
-
-    public PooledPlcDriverManager(ClassLoader classLoader, PoolCreator poolCreator) {
-        super(classLoader);
-        setFromPoolCreator(poolCreator);
-        poolKeyFactory = new PoolKeyFactory();
-    }
-
-    private void setFromPoolCreator(PoolCreator poolCreator) {
-        this.keyedObjectPool = poolCreator.createPool(new PooledPlcConnectionFactory() {
-            @Override
-            public PlcConnection create(PoolKey key) throws Exception {
-                PlcAuthentication plcAuthentication = key.plcAuthentication;
-                String url = key.url;
-                if (plcAuthentication == noPlcAuthentication) {
-                    LOGGER.debug("getting actual connection for {}", url);
-                    return PooledPlcDriverManager.super.getConnection(url);
-                } else {
-                    LOGGER.debug("getting actual connection for {} and plcAuthentication {}", url, plcAuthentication);
-                    return PooledPlcDriverManager.super.getConnection(url, plcAuthentication);
-                }
-            }
-        });
-    }
-
-    @Override
-    public PlcConnection getConnection(String url) throws PlcConnectionException {
-        return getConnection(url, noPlcAuthentication);
-    }
-
-    @Override
-    public PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException {
-        PoolKey poolKey = poolKeyFactory.getPoolKey(url, authentication);
-        if (LOGGER.isDebugEnabled()) {
-            if (authentication != noPlcAuthentication) {
-                LOGGER.debug("Try to borrow an object for url {} and authentication {}", url, authentication);
-            } else {
-                LOGGER.debug("Try to borrow an object for url {}", url);
-            }
-        }
-        PlcConnection plcConnection;
-        try {
-            plcConnection = keyedObjectPool.borrowObject(poolKey);
-            if (plcConnection.isConnected() == false) {
-                LOGGER.debug("Attempting to reconnect to device");
-                plcConnection.connect();
-            }
-        } catch (Exception e) {
-            throw new PlcConnectionException(e);
-        }
-        // Used to invalidate a proxy
-        AtomicBoolean proxyInvalidated = new AtomicBoolean(false);
-        return (PlcConnection) Proxy.newProxyInstance(classLoader, new Class[]{PlcConnection.class}, (proxy, method, args) -> {
-            if (proxyInvalidated.get()) {
-                throw new IllegalStateException("Proxy not valid anymore");
-            }
-            if ("close".equals(method.getName())) {
-                LOGGER.debug("close called on {}", plcConnection);
-                proxyInvalidated.set(true);
-                keyedObjectPool.returnObject(poolKey, plcConnection);
-                return null;
-            } else {
-                try {
-                    return method.invoke(plcConnection, args);
-                } catch (InvocationTargetException e) {
-                    if (e.getCause().getClass() == PlcConnectionException.class) {
-                        keyedObjectPool.invalidateObject(poolKey, plcConnection);
-                        proxyInvalidated.set(true);
-                    }
-                    throw e;
-                }
-            }
-        });
-    }
-
-    @FunctionalInterface
-    public interface PoolCreator {
-        KeyedObjectPool<PoolKey, PlcConnection> createPool(PooledPlcConnectionFactory pooledPlcConnectionFactory);
-    }
-
-    // TODO: maybe export to jmx // generic poolKey has builtin jmx too
-    public Map<String, Number> getStatistics() {
-        HashMap<String, Number> statistics = new HashMap<>();
-        statistics.put("numActive", keyedObjectPool.getNumActive());
-        statistics.put("numIdle", keyedObjectPool.getNumIdle());
-        if (keyedObjectPool instanceof GenericKeyedObjectPool) {
-            GenericKeyedObjectPool<PoolKey, PlcConnection> genericKeyedObjectPool = (GenericKeyedObjectPool<PoolKey, PlcConnection>) this.keyedObjectPool;
-            // Thats pretty ugly and we really should't do that...
-            try {
-                Map poolMap = (Map) FieldUtils.getField(GenericKeyedObjectPool.class, "poolMap", true).get(this.keyedObjectPool);
-                statistics.put("pools.count", poolMap.size());
-            } catch (IllegalAccessException e) {
-                throw new PlcRuntimeException(e);
-            }
-            Map<String, Integer> numActivePerKey = genericKeyedObjectPool.getNumActivePerKey();
-            for (Map.Entry<String, Integer> entry : numActivePerKey.entrySet()) {
-                statistics.put(entry.getKey() + ".numActive", entry.getValue());
-            }
-        }
-
-        return statistics;
-    }
-
-    private static final class NoPlcAuthentication implements PlcAuthentication {
-
-    }
-}
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactoryTest.java b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactoryTest.java
deleted file mode 100644
index 3b447ed689..0000000000
--- a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PoolKeyFactoryTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool;
-
-import org.assertj.core.api.WithAssertions;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-
-/**
- * See Cahnges due to PLC4X-223 and PLC4X-224
- */
-@Disabled
-class PoolKeyFactoryTest implements WithAssertions {
-
-    private PoolKeyFactory SUT = new PoolKeyFactory();
-
-    @Nested
-    class Generic {
-        @Test
-        void getPoolKey() throws Exception {
-            PoolKey poolKey = SUT.getPoolKey("randomProtocol://randomHost/1/1?someOptions", PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getUrl()).isEqualTo("randomProtocol://randomHost/1/1?someOptions");
-            assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getPoolableKey()).isEqualTo("randomProtocol://randomHost/1/1?someOptions");
-        }
-    }
-
-    @Nested
-    class S7 {
-        @Test
-        void getPoolKey() throws Exception {
-            PoolKey poolKey = SUT.getPoolKey("s7://localhost?randomOption=true", PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getUrl()).isEqualTo("s7://localhost?randomOption=true");
-            assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getPoolableKey()).isEqualTo("s7://localhost");
-        }
-    }
-
-    @Nested
-    class ADS {
-        @Test
-        void getPoolKey_TCP() throws Exception {
-            PoolKey poolKey = SUT.getPoolKey("ads:tcp://10.10.64.40/10.10.64.40.1.1:851/10.10.56.23.1.1:30000", PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getUrl()).isEqualTo("ads:tcp://10.10.64.40/10.10.64.40.1.1:851/10.10.56.23.1.1:30000");
-            assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getPoolableKey()).isEqualTo("ads:tcp://10.10.64.40");
-        }
-
-        @Test
-        void getPoolKey_SERIAL() throws Exception {
-            PoolKey poolKey = SUT.getPoolKey("ads:serial:///dev/ttys003/10.10.64.40.1.1:851/10.10.56.23.1.1:30000", PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getUrl()).isEqualTo("ads:serial:///dev/ttys003/10.10.64.40.1.1:851/10.10.56.23.1.1:30000");
-            assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getPoolableKey()).isEqualTo("ads:serial:///dev/ttys003");
-        }
-    }
-
-    @Nested
-    class Modbus {
-        @Test
-        void getPoolKey_TCP() throws Exception {
-            PoolKey poolKey = SUT.getPoolKey("modbus-tcp://10.10.64.40?someRandomOption=true", PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getUrl()).isEqualTo("modbus-tcp://10.10.64.40?someRandomOption=true");
-            assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getPoolableKey()).isEqualTo("modbus-tcp://10.10.64.40");
-        }
-
-        @Disabled("Modbus serial pooling doesn't work right now as intended")
-        @Test
-        void getPoolKey_SERIAL() throws Exception {
-            PoolKey poolKey = SUT.getPoolKey("modbus-adu:///dev/ttys003?someRandomOption=true", PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getUrl()).isEqualTo("modbus-adu:///dev/ttys003?someRandomOption=true");
-            assertThat(poolKey.getPlcAuthentication()).isEqualTo(PooledPlcDriverManager.noPlcAuthentication);
-            assertThat(poolKey.getPoolableKey()).isEqualTo("modbus-adu:///dev/ttys003");
-        }
-    }
-
-
-}
\ No newline at end of file
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledDummyDriver.java b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledDummyDriver.java
deleted file mode 100644
index 723917505b..0000000000
--- a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledDummyDriver.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool;
-
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.authentication.PlcAuthentication;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.apache.plc4x.java.api.PlcDriver;
-
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.mock;
-
-public class PooledDummyDriver implements PlcDriver {
-
-    private PlcDriver mockedPlcDriver = mock(PlcDriver.class, RETURNS_DEEP_STUBS);
-
-    @Override
-    public String getProtocolCode() {
-        return PooledDummyDriver.class.getName();
-    }
-
-    @Override
-    public String getProtocolName() {
-        return mockedPlcDriver.getProtocolCode();
-    }
-
-    @Override
-    public PlcConnection getConnection(String url) throws PlcConnectionException {
-        return mockedPlcDriver.getConnection(url);
-    }
-
-    @Override
-    public PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException {
-        return mockedPlcDriver.getConnection(url, authentication);
-    }
-
-}
diff --git a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManagerTest.java b/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManagerTest.java
deleted file mode 100644
index 499edf1c61..0000000000
--- a/plc4j/tools/connection-pool/src/test/java/org/apache/plc4x/java/utils/connectionpool/PooledPlcDriverManagerTest.java
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.utils.connectionpool;
-
-import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
-import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.authentication.PlcAuthentication;
-import org.apache.plc4x.java.api.authentication.PlcUsernamePasswordAuthentication;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.apache.plc4x.java.api.exceptions.PlcUnsupportedOperationException;
-import org.apache.plc4x.java.api.messages.*;
-import org.apache.plc4x.java.api.metadata.PlcConnectionMetadata;
-import org.apache.plc4x.java.api.PlcDriver;
-import org.assertj.core.api.WithAssertions;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.IntStream;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.*;
-
-@ExtendWith(MockitoExtension.class)
-class PooledPlcDriverManagerTest implements WithAssertions {
-
-    private static Logger LOGGER = LoggerFactory.getLogger(PooledPlcDriverManagerTest.class);
-
-    private PooledPlcDriverManager SUT = new PooledPlcDriverManager(pooledPlcConnectionFactory -> {
-        GenericKeyedObjectPoolConfig<PlcConnection> config = new GenericKeyedObjectPoolConfig<>();
-        config.setMinIdlePerKey(1);
-        config.setTestOnBorrow(true);
-        config.setTestOnReturn(true);
-        return new GenericKeyedObjectPool<>(pooledPlcConnectionFactory, config);
-    });
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    PlcDriver plcDriver;
-
-    private ExecutorService executorService;
-
-    @SuppressWarnings("unchecked")
-    @BeforeEach
-    void setUp() throws Exception {
-        Map<String, PlcDriver> driverMap = (Map) FieldUtils.getField(PooledPlcDriverManager.class, "driverMap", true).get(SUT);
-        driverMap.put("dummydummy", plcDriver);
-        executorService = Executors.newFixedThreadPool(100);
-
-        assertThat(SUT.getStatistics()).containsOnly(
-            entry("pools.count", 0),
-            entry("numActive", 0),
-            entry("numIdle", 0)
-        );
-    }
-
-    @AfterEach
-    void tearDown() {
-        executorService.shutdown();
-    }
-
-    @Test
-    void getConnection() throws Exception {
-        when(plcDriver.getConnection(anyString())).then(invocationOnMock -> new DummyPlcConnection(invocationOnMock.getArgument(0)));
-
-        LinkedList<Callable<PlcConnection>> callables = new LinkedList<>();
-
-        // This: should result in one open connection
-        IntStream.range(0, 8).forEach(i -> callables.add(() -> {
-            try {
-                return SUT.getConnection("dummydummy:single/socket1/socket2?fancyOption=true");
-            } catch (PlcConnectionException e) {
-                throw new RuntimeException(e);
-            }
-        }));
-
-        // This should result in five open connections
-        IntStream.range(0, 5).forEach(i -> callables.add(() -> {
-            try {
-                return SUT.getConnection("dummydummy:multi-" + i + "/socket1/socket2?fancyOption=true");
-            } catch (PlcConnectionException e) {
-                throw new RuntimeException(e);
-            }
-        }));
-
-        List<Future<PlcConnection>> futures = executorService.invokeAll(callables);
-
-        // Wait for existing connections
-        futures.forEach(plcConnectionFuture1 -> {
-            try {
-                plcConnectionFuture1.get();
-            } catch (InterruptedException | ExecutionException e) {
-                throw new RuntimeException(e);
-            }
-        });
-        LOGGER.info("Statistics after execution {}", SUT.getStatistics());
-
-        // As we have a pool size of 8 we should have only 8 + 5 calls for the separate pools
-        verify(plcDriver, times(13)).getConnection(anyString());
-
-        assertThat(SUT.getStatistics()).contains(
-            entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true'}.numActive", 8)
-        );
-
-        futures.forEach(plcConnectionFuture -> {
-            try {
-                plcConnectionFuture.get().close();
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        });
-
-        assertThat(SUT.getStatistics()).contains(
-            entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true'}.numActive", 0)
-        );
-    }
-
-    @Test
-    void getConnectionWithAuth() throws Exception {
-        when(plcDriver.getConnection(anyString(), any())).then(invocationOnMock -> new DummyPlcConnection(invocationOnMock.getArgument(0), invocationOnMock.getArgument(1)));
-
-        LinkedList<Callable<PlcConnection>> callables = new LinkedList<>();
-
-        // This: should result in one open connection
-        IntStream.range(0, 8).forEach(i -> callables.add(() -> {
-            try {
-                return SUT.getConnection("dummydummy:single/socket1/socket2?fancyOption=true", new PlcUsernamePasswordAuthentication("user", "passwordp954368564098Ɵ"));
-            } catch (PlcConnectionException e) {
-                throw new RuntimeException(e);
-            }
-        }));
-
-        // This should result in five open connections
-        IntStream.range(0, 5).forEach(i -> callables.add(() -> {
-            try {
-                return SUT.getConnection("dummydummy:multi-" + i + "/socket1/socket2?fancyOption=true", new PlcUsernamePasswordAuthentication("user", "passwordp954368564098Ɵ"));
-            } catch (PlcConnectionException e) {
-                throw new RuntimeException(e);
-            }
-        }));
-
-        List<Future<PlcConnection>> futures = executorService.invokeAll(callables);
-
-        futures.forEach(plcConnectionFuture1 -> {
-            try {
-                plcConnectionFuture1.get();
-            } catch (InterruptedException | ExecutionException e) {
-                throw new RuntimeException(e);
-            }
-        });
-
-        LOGGER.info("Statistics after execution {}", SUT.getStatistics());
-
-        // As we have a pool size of 8 we should have only 8 + 5 calls for the separate pools
-        verify(plcDriver, times(13)).getConnection(anyString(), any());
-
-        assertThat(SUT.getStatistics()).contains(
-            entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true', plcAuthentication=PlcUsernamePasswordAuthentication{username='user', password='*****************'}}.numActive", 8)
-        );
-
-        futures.forEach(plcConnectionFuture -> {
-            try {
-                plcConnectionFuture.get().close();
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        });
-
-        assertThat(SUT.getStatistics()).contains(
-            entry("PoolKey{url='dummydummy:single/socket1/socket2?fancyOption=true', plcAuthentication=PlcUsernamePasswordAuthentication{username='user', password='*****************'}}.numActive", 0)
-        );
-    }
-
-    @Test
-    void connectionInvalidation() throws Exception {
-        when(plcDriver.getConnection(anyString())).then(invocationOnMock -> new DummyPlcConnection(invocationOnMock.getArgument(0)));
-
-        PlcConnection connection = SUT.getConnection("dummydummy:single/socket1/socket2?fancyOption=true");
-        assertThat(connection.isConnected()).isEqualTo(true);
-        assertThat(connection.getMetadata().canRead()).isEqualTo(false);
-        assertThat(connection.getMetadata().canWrite()).isEqualTo(false);
-        assertThat(connection.getMetadata().canSubscribe()).isEqualTo(false);
-
-        connection.close();
-        assertThatThrownBy(connection::connect).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
-        assertThatThrownBy(connection::isConnected).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
-        assertThatThrownBy(connection::close).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
-        assertThatThrownBy(connection::getMetadata).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
-        assertThatThrownBy(connection::readRequestBuilder).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
-        assertThatThrownBy(connection::writeRequestBuilder).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
-        assertThatThrownBy(connection::subscriptionRequestBuilder).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
-        assertThatThrownBy(connection::unsubscriptionRequestBuilder).isInstanceOf(IllegalStateException.class).hasMessage("Proxy not valid anymore");
-    }
-
-    @Test
-    void cleanupOfBrokenConnections() throws Exception {
-        AtomicBoolean failNow = new AtomicBoolean(false);
-        when(plcDriver.getConnection(anyString())).then(invocationOnMock -> {
-            DummyPlcConnection dummyPlcConnection = spy(new DummyPlcConnection(invocationOnMock.getArgument(0)));
-            // we fake an connection which breaks at this call
-            doAnswer(invocation -> {
-                if (failNow.get()) {
-                    throw new PlcConnectionException("blub");
-                }
-                return invocation.callRealMethod();
-            }).when(dummyPlcConnection).connect();
-            return dummyPlcConnection;
-        });
-
-        assertThat(SUT.getStatistics()).containsOnly(
-            entry("pools.count", 0),
-            entry("numActive", 0),
-            entry("numIdle", 0)
-        );
-        PlcConnection connection = SUT.getConnection("dummydummy:breakIt");
-        assertThat(SUT.getStatistics()).containsOnly(
-            entry("pools.count", 1),
-            entry("numActive", 1),
-            entry("numIdle", 0),
-            entry("PoolKey{url='dummydummy:breakIt'}.numActive", 1)
-        );
-        failNow.set(true);
-        try {
-            connection.connect();
-            fail("This should throw an exception");
-        } catch (Exception e) {
-            // TODO: currently UndeclaredThrowableException is the top one which should be InvocationTargetException
-            //assertThat(e).isInstanceOf(InvocationTargetException.class);
-            assertThat(e).hasRootCauseInstanceOf(PlcConnectionException.class);
-        }
-        // Faulty connection should have been discarded
-        assertThat(SUT.getStatistics()).containsOnly(
-            entry("pools.count", 0),
-            entry("numActive", 0),
-            entry("numIdle", 0)
-        );
-    }
-
-    @Test
-    public void testOtherConstructors() {
-        assertThat(new PooledPlcDriverManager()).isNotNull();
-        assertThat(new PooledPlcDriverManager(new PoolKeyFactory())).isNotNull();
-        assertThat(new PooledPlcDriverManager(PooledPlcDriverManager.class.getClassLoader())).isNotNull();
-        assertThat(new PooledPlcDriverManager(
-            PooledPlcDriverManager.class.getClassLoader(), new PoolKeyFactory())).isNotNull();
-    }
-
-    class DummyPlcConnection implements PlcConnection, PlcConnectionMetadata {
-
-        private final String url;
-
-        private final PlcAuthentication plcAuthentication;
-
-        boolean connected = false;
-
-        public DummyPlcConnection(String url) {
-            this(url, null);
-        }
-
-        public DummyPlcConnection(String url, PlcAuthentication plcAuthentication) {
-            this.url = url;
-            this.plcAuthentication = plcAuthentication;
-        }
-
-        @Override
-        public void connect() {
-            connected = true;
-        }
-
-        @Override
-        public CompletableFuture<Void> ping() {
-            CompletableFuture<Void> future = new CompletableFuture<>();
-            future.completeExceptionally(new UnsupportedOperationException());
-            return future;
-        }
-
-        @Override
-        public boolean isConnected() {
-            return connected;
-        }
-
-        @Override
-        public PlcConnectionMetadata getMetadata() {
-            return this;
-        }
-
-        @Override
-        public boolean canRead() {
-            return false;
-        }
-
-        @Override
-        public boolean canWrite() {
-            return false;
-        }
-
-        @Override
-        public boolean canSubscribe() {
-            return false;
-        }
-
-        @Override
-        public boolean canBrowse() {
-            return false;
-        }
-
-        @Override
-        public void close() {
-            connected = false;
-        }
-
-        @Override
-        public PlcReadRequest.Builder readRequestBuilder() {
-            throw new PlcUnsupportedOperationException("The connection does not support reading");
-        }
-
-        @Override
-        public PlcWriteRequest.Builder writeRequestBuilder() {
-            throw new PlcUnsupportedOperationException("The connection does not support writing");
-        }
-
-        @Override
-        public PlcSubscriptionRequest.Builder subscriptionRequestBuilder() {
-            throw new PlcUnsupportedOperationException("The connection does not support subscription");
-        }
-
-        @Override
-        public PlcUnsubscriptionRequest.Builder unsubscriptionRequestBuilder() {
-            throw new PlcUnsupportedOperationException("The connection does not support subscription");
-        }
-
-        @Override
-        public PlcBrowseRequest.Builder browseRequestBuilder() {
-            throw new PlcUnsupportedOperationException("The connection does not support browsing");
-        }
-
-        @Override
-        public String toString() {
-            return "DummyPlcConnection{" +
-                "url='" + url + '\'' +
-                ", plcAuthentication=" + plcAuthentication +
-                ", connected=" + connected +
-                '}';
-        }
-    }
-}
\ No newline at end of file
diff --git a/plc4j/tools/connection-pool/src/test/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver b/plc4j/tools/connection-pool/src/test/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
deleted file mode 100644
index a53e1aad44..0000000000
--- a/plc4j/tools/connection-pool/src/test/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-org.apache.plc4x.java.utils.connectionpool.PooledDummyDriver
diff --git a/plc4j/tools/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityInterceptor.java b/plc4j/tools/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityInterceptor.java
index 3972b8b986..1a62c6f4c3 100644
--- a/plc4j/tools/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityInterceptor.java
+++ b/plc4j/tools/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityInterceptor.java
@@ -23,8 +23,8 @@ import org.apache.commons.configuration2.Configuration;
 import org.apache.commons.configuration2.SystemConfiguration;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.Validate;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.*;
@@ -50,7 +50,7 @@ import java.util.concurrent.TimeoutException;
 
 /**
  * Interceptor for dynamic functionality of @{@link PlcEntity}.
- * Basically, its {@link #interceptGetter(Object, Method, Callable, String, PlcDriverManager, AliasRegistry, Map, Map)} method is called for each
+ * Basically, its {@link #interceptGetter(Object, Method, Callable, String, PlcConnectionManager, AliasRegistry, Map, Map)} method is called for each
  * invocation of a method on a connected @{@link PlcEntity} and does then the dynamic part.
  * <p>
  * For those not too familiar with the JVM's dispatch on can roughly imagine the intercept method being a "regular"
@@ -71,16 +71,16 @@ public class PlcEntityInterceptor {
     /**
      * Basic Intersector for all methods on the proxy object.
      * It checks if the invoked method is a getter and if so, only retrieves the requested tag, forwarding to
-     * the {@link #fetchAndSetValueForGetter(Object, Method, PlcDriverManager, String, AliasRegistry, Map)} method.
+     * the {@link #fetchAndSetValueForGetter(Object, Method, PlcConnectionManager, String, AliasRegistry, Map)} method.
      * <p>
-     * If the tag is no getter, then all tags are refreshed by calling {@link #refetchAllFields(Object, PlcDriverManager, String, AliasRegistry, Map)}
+     * If the tag is no getter, then all tags are refreshed by calling {@link #refetchAllFields(Object, PlcConnectionManager, String, AliasRegistry, Map)}
      * and then, the method is invoked.
      *
-     * @param proxy         Object to intercept
-     * @param method        Method that was intercepted
-     * @param callable      Callable to call the method after fetching the values
-     * @param address       Address of the plc (injected from private tag)
-     * @param driverManager DriverManager instance to use (injected from private tag)
+     * @param proxy             Object to intercept
+     * @param method            Method that was intercepted
+     * @param callable          Callable to call the method after fetching the values
+     * @param address           Address of the plc (injected from private tag)
+     * @param connectionManager PlcConnectionManager instance to use (injected from private tag)
      * @return possible result of the original methods invocation
      * @throws OPMException Problems with plc / proxying
      */
@@ -88,15 +88,15 @@ public class PlcEntityInterceptor {
     @RuntimeType
     public static Object interceptGetter(@This Object proxy, @Origin Method method, @SuperCall Callable<?> callable,
                                          @FieldValue(PlcEntityManager.PLC_ADDRESS_FIELD_NAME) String address,
-                                         @FieldValue(PlcEntityManager.DRIVER_MANAGER_FIELD_NAME) PlcDriverManager driverManager,
+                                         @FieldValue(PlcEntityManager.CONNECTION_MANAGER_FIELD_NAME) PlcConnectionManager connectionManager,
                                          @FieldValue(PlcEntityManager.ALIAS_REGISTRY) AliasRegistry registry,
                                          @FieldValue(PlcEntityManager.LAST_FETCHED) Map<String, Instant> lastFetched,
                                          @FieldValue(PlcEntityManager.LAST_WRITTEN) Map<String, Instant> lastWritten) throws OPMException {
         LOGGER.trace("Invoked method {} on connected PlcEntity {}", method.getName(), method.getDeclaringClass().getName());
 
         // If "detached" (i.e. _driverManager is null) simply forward the call
-        if (driverManager == null) {
-            LOGGER.trace("Entity not connected, simply fowarding call");
+        if (connectionManager == null) {
+            LOGGER.trace("Entity not connected, simply forwarding call");
             try {
                 return callable.call();
             } catch (Exception e) {
@@ -112,7 +112,7 @@ public class PlcEntityInterceptor {
             LOGGER.trace("Invoked method {} is getter, trying to find annotated tag and return requested value",
                 method.getName());
 
-            fetchAndSetValueForGetter(proxy, method, driverManager, address, registry, lastFetched);
+            fetchAndSetValueForGetter(proxy, method, connectionManager, address, registry, lastFetched);
             try {
                 return callable.call();
             } catch (Exception e) {
@@ -127,7 +127,7 @@ public class PlcEntityInterceptor {
             // Fetch single value
             LOGGER.trace("Invoked method {} is boolean flag method, trying to find annotated tag and return requested value",
                 method.getName());
-            fetchAndSetValueForIsGetter(proxy, method, driverManager, address, registry, lastFetched);
+            fetchAndSetValueForIsGetter(proxy, method, connectionManager, address, registry, lastFetched);
             try {
                 return callable.call();
             } catch (Exception e) {
@@ -135,13 +135,13 @@ public class PlcEntityInterceptor {
             }
         }
 
-        // Fetch all values, than invoke method
+        // Fetch all values then invoke method
         try {
             LOGGER.trace("Invoked method is no getter, refetch all tags and invoke method {} then", method.getName());
-            refetchAllFields(proxy, driverManager, address, registry, lastFetched);
+            refetchAllFields(proxy, connectionManager, address, registry, lastFetched);
             Object call = callable.call();
             // We write back
-            writeAllFields(proxy, driverManager, address, registry, lastWritten);
+            writeAllFields(proxy, connectionManager, address, registry, lastWritten);
             return call;
         } catch (Exception e) {
             throw new OPMException("Unable to forward invocation " + method.getName() + " on connected PlcEntity", e);
@@ -152,14 +152,14 @@ public class PlcEntityInterceptor {
     @RuntimeType
     public static Object interceptSetter(@This Object proxy, @Origin Method method, @SuperCall Callable<?> callable,
                                          @FieldValue(PlcEntityManager.PLC_ADDRESS_FIELD_NAME) String address,
-                                         @FieldValue(PlcEntityManager.DRIVER_MANAGER_FIELD_NAME) PlcDriverManager driverManager,
+                                         @FieldValue(PlcEntityManager.CONNECTION_MANAGER_FIELD_NAME) PlcConnectionManager connectionManager,
                                          @FieldValue(PlcEntityManager.ALIAS_REGISTRY) AliasRegistry registry,
                                          @FieldValue(PlcEntityManager.LAST_FETCHED) Map<String, Instant> lastFetched,
                                          @Argument(0) Object argument) throws OPMException {
         LOGGER.trace("Invoked method {} on connected PlcEntity {}", method.getName(), method.getDeclaringClass().getName());
 
         // If "detached" (i.e. _driverManager is null) simply forward the call
-        if (driverManager == null) {
+        if (connectionManager == null) {
             LOGGER.trace("Entity not connected, simply fowarding call");
             try {
                 return callable.call();
@@ -176,13 +176,13 @@ public class PlcEntityInterceptor {
             LOGGER.trace("Invoked method {} is setter, trying to find annotated tag and return requested value",
                 method.getName());
 
-            return setValueForSetter(proxy, method, callable, driverManager, address, registry, lastFetched, argument);
+            return setValueForSetter(proxy, method, callable, connectionManager, address, registry, lastFetched, argument);
         }
 
-        // Fetch all values, than invoke method
+        // Fetch all values then invoke method
         try {
             LOGGER.trace("Invoked method is no getter, refetch all tags and invoke method {} then", method.getName());
-            refetchAllFields(proxy, driverManager, address, registry, lastFetched);
+            refetchAllFields(proxy, connectionManager, address, registry, lastFetched);
             return callable.call();
         } catch (Exception e) {
             throw new OPMException("Unable to forward invocation " + method.getName() + " on connected PlcEntity", e);
@@ -193,13 +193,13 @@ public class PlcEntityInterceptor {
      * Renews all values of all tags that are annotated with {@link PlcEntity}.
      *
      * @param proxy         Object to refresh the tags on.
-     * @param driverManager Driver Manager to use
+     * @param connectionManager Connection Manager to use
      * @param registry      AliasRegistry to use
      * @param lastFetched
      * @throws OPMException on various errors.
      */
     @SuppressWarnings("squid:S1141") // Nested try blocks readability is okay, move to other method makes it imho worse
-    static void refetchAllFields(Object proxy, PlcDriverManager driverManager, String address, AliasRegistry registry, Map<String, Instant> lastFetched) throws OPMException {
+    static void refetchAllFields(Object proxy, PlcConnectionManager connectionManager, String address, AliasRegistry registry, Map<String, Instant> lastFetched) throws OPMException {
         // Don't log o here as this would cause a second request against a plc so don't touch it, or if you log be aware of that
         Class<?> entityClass = proxy.getClass().getSuperclass();
         LOGGER.trace("Refetching all tags on proxy object of class {}", entityClass);
@@ -214,7 +214,7 @@ public class PlcEntityInterceptor {
                 OpmUtils.getOrResolveAddress(registry, field.getAnnotation(PlcTag.class).value());
             }
         }
-        try (PlcConnection connection = driverManager.getConnection(address)) {
+        try (PlcConnection connection = connectionManager.getConnection(address)) {
             // Catch the exception, if no reader present (see below)
             // Build the query
             PlcReadRequest.Builder requestBuilder = connection.readRequestBuilder();
@@ -255,7 +255,7 @@ public class PlcEntityInterceptor {
         }
     }
 
-    static void writeAllFields(Object proxy, PlcDriverManager driverManager, String address, AliasRegistry registry, Map<String, Instant> lastWritten) throws OPMException {
+    static void writeAllFields(Object proxy, PlcConnectionManager connectionManager, String address, AliasRegistry registry, Map<String, Instant> lastWritten) throws OPMException {
         // Don't log o here as this would cause a second request against a plc so don't touch it, or if you log be aware of that
         Class<?> entityClass = proxy.getClass().getSuperclass();
         LOGGER.trace("Writing all tags on proxy object of class {}", entityClass);
@@ -270,7 +270,7 @@ public class PlcEntityInterceptor {
                 OpmUtils.getOrResolveAddress(registry, field.getAnnotation(PlcTag.class).value());
             }
         }
-        try (PlcConnection connection = driverManager.getConnection(address)) {
+        try (PlcConnection connection = connectionManager.getConnection(address)) {
             // Catch the exception, if no reader present (see below)
             // Build the query
             PlcWriteRequest.Builder requestBuilder = connection.writeRequestBuilder();
@@ -334,15 +334,15 @@ public class PlcEntityInterceptor {
         return true;
     }
 
-    private static void fetchAndSetValueForIsGetter(Object proxy, Method m, PlcDriverManager driverManager, String address, AliasRegistry registry, Map<String, Instant> lastFetched) throws OPMException {
-        fetchAndSetValueForGetter(proxy, m, 2, driverManager, address, registry, lastFetched);
+    private static void fetchAndSetValueForIsGetter(Object proxy, Method m, PlcConnectionManager connectionManager, String address, AliasRegistry registry, Map<String, Instant> lastFetched) throws OPMException {
+        fetchAndSetValueForGetter(proxy, m, 2, connectionManager, address, registry, lastFetched);
     }
 
-    private static void fetchAndSetValueForGetter(Object proxy, Method m, PlcDriverManager driverManager, String address, AliasRegistry registry, Map<String, Instant> lastFetched) throws OPMException {
-        fetchAndSetValueForGetter(proxy, m, 3, driverManager, address, registry, lastFetched);
+    private static void fetchAndSetValueForGetter(Object proxy, Method m, PlcConnectionManager connectionManager, String address, AliasRegistry registry, Map<String, Instant> lastFetched) throws OPMException {
+        fetchAndSetValueForGetter(proxy, m, 3, connectionManager, address, registry, lastFetched);
     }
 
-    private static void fetchAndSetValueForGetter(Object proxy, Method m, int prefixLength, PlcDriverManager driverManager,
+    private static void fetchAndSetValueForGetter(Object proxy, Method m, int prefixLength, PlcConnectionManager connectionManager,
                                                   String address, AliasRegistry registry, Map<String, Instant> lastFetched) throws OPMException {
         String s = m.getName().substring(prefixLength);
         // First char to lower
@@ -364,7 +364,7 @@ public class PlcEntityInterceptor {
         if (!needsToBeSynced(lastFetched, field)) {
             return;
         }
-        try (PlcConnection connection = driverManager.getConnection(address)) {
+        try (PlcConnection connection = connectionManager.getConnection(address)) {
             // Catch the exception, if no reader present (see below)
 
             PlcReadRequest request = connection.readRequestBuilder()
@@ -394,7 +394,7 @@ public class PlcEntityInterceptor {
         }
     }
 
-    private static Object setValueForSetter(Object proxy, Method m, Callable<?> callable, PlcDriverManager driverManager,
+    private static Object setValueForSetter(Object proxy, Method m, Callable<?> callable, PlcConnectionManager connectionManager,
                                             String address, AliasRegistry registry, Map<String, Instant> lastFetched, Object object) throws OPMException {
         String s = m.getName().substring(3);
         // First char to lower
@@ -412,7 +412,7 @@ public class PlcEntityInterceptor {
         // Use Fully qualified Name as tag index
         String fqn = getFqn(field);
 
-        try (PlcConnection connection = driverManager.getConnection(address)) {
+        try (PlcConnection connection = connectionManager.getConnection(address)) {
             // Catch the exception, if no reader present (see below)
 
             PlcWriteRequest request = connection.writeRequestBuilder()
diff --git a/plc4j/tools/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityManager.java b/plc4j/tools/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityManager.java
index a180800a3f..4fe3423840 100644
--- a/plc4j/tools/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityManager.java
+++ b/plc4j/tools/opm/src/main/java/org/apache/plc4x/java/opm/PlcEntityManager.java
@@ -22,7 +22,8 @@ import net.bytebuddy.ByteBuddy;
 import net.bytebuddy.description.modifier.Visibility;
 import net.bytebuddy.implementation.MethodDelegation;
 import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.slf4j.Logger;
@@ -72,7 +73,7 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
  * regular Pojo it was before.
  * <p>
  * All invocations on the getters are forwarded to the
- * {@link PlcEntityInterceptor#interceptGetter(Object, Method, Callable, String, PlcDriverManager, AliasRegistry, Map, Map)}
+ * {@link PlcEntityInterceptor#interceptGetter(Object, Method, Callable, String, PlcConnectionManager, AliasRegistry, Map, Map)}
  * method.
  */
 public class PlcEntityManager {
@@ -80,24 +81,24 @@ public class PlcEntityManager {
     private static final Logger LOGGER = LoggerFactory.getLogger(PlcEntityManager.class);
 
     public static final String PLC_ADDRESS_FIELD_NAME = "_plcAddress";
-    static final String DRIVER_MANAGER_FIELD_NAME = "_driverManager";
+    static final String CONNECTION_MANAGER_FIELD_NAME = "_connectionManager";
     static final String ALIAS_REGISTRY = "_aliasRegistry";
     public static final String LAST_FETCHED = "_lastFetched";
     public static final String LAST_WRITTEN = "_lastWritten";
 
-    private final PlcDriverManager driverManager;
+    private final PlcConnectionManager connectionManager;
     private final SimpleAliasRegistry registry;
 
     public PlcEntityManager() {
-        this(new PlcDriverManager());
+        this(new DefaultPlcDriverManager());
     }
 
-    public PlcEntityManager(PlcDriverManager driverManager) {
-        this(driverManager, new SimpleAliasRegistry());
+    public PlcEntityManager(PlcConnectionManager connectionManager) {
+        this(connectionManager, new SimpleAliasRegistry());
     }
 
-    public PlcEntityManager(PlcDriverManager driverManager, SimpleAliasRegistry registry) {
-        this.driverManager = driverManager;
+    public PlcEntityManager(PlcConnectionManager connectionManager, SimpleAliasRegistry registry) {
+        this.connectionManager = connectionManager;
         this.registry = registry;
     }
 
@@ -146,7 +147,7 @@ public class PlcEntityManager {
             T instance = new ByteBuddy()
                 .subclass(clazz)
                 .defineField(PLC_ADDRESS_FIELD_NAME, String.class, Visibility.PRIVATE)
-                .defineField(DRIVER_MANAGER_FIELD_NAME, PlcDriverManager.class, Visibility.PRIVATE)
+                .defineField(CONNECTION_MANAGER_FIELD_NAME, PlcConnectionManager.class, Visibility.PRIVATE)
                 .defineField(ALIAS_REGISTRY, AliasRegistry.class, Visibility.PRIVATE)
                 .defineField(LAST_FETCHED, Map.class, Visibility.PRIVATE)
                 .defineField(LAST_WRITTEN, Map.class, Visibility.PRIVATE)
@@ -158,7 +159,7 @@ public class PlcEntityManager {
                 .newInstance();
             // Set connection value into the private field
             FieldUtils.writeDeclaredField(instance, PLC_ADDRESS_FIELD_NAME, address, true);
-            FieldUtils.writeDeclaredField(instance, DRIVER_MANAGER_FIELD_NAME, driverManager, true);
+            FieldUtils.writeDeclaredField(instance, CONNECTION_MANAGER_FIELD_NAME, connectionManager, true);
             FieldUtils.writeDeclaredField(instance, ALIAS_REGISTRY, registry, true);
             Map<String, Instant> lastFetched = new HashMap<>();
             FieldUtils.writeDeclaredField(instance, LAST_FETCHED, lastFetched, true);
@@ -167,13 +168,13 @@ public class PlcEntityManager {
 
             // Initially fetch all values
             if (existingInstance == null) {
-                PlcEntityInterceptor.refetchAllFields(instance, driverManager, address, registry, lastFetched);
+                PlcEntityInterceptor.refetchAllFields(instance, connectionManager, address, registry, lastFetched);
             } else {
                 FieldUtils.getAllFieldsList(clazz).stream()
                     .peek(field -> field.setAccessible(true))
                     .forEach(field -> setValueToField(field, instance, getValueFromField(field, existingInstance)));
 
-                PlcEntityInterceptor.writeAllFields(instance, driverManager, address, registry, lastWritten);
+                PlcEntityInterceptor.writeAllFields(instance, connectionManager, address, registry, lastWritten);
             }
 
             return instance;
@@ -211,11 +212,11 @@ public class PlcEntityManager {
             throw new OPMException("Unable to disconnect Object, is no entity!");
         }
         try {
-            Object manager = FieldUtils.readDeclaredField(entity, DRIVER_MANAGER_FIELD_NAME, true);
+            Object manager = FieldUtils.readDeclaredField(entity, CONNECTION_MANAGER_FIELD_NAME, true);
             if (manager == null) {
                 throw new OPMException("Instance is already disconnected!");
             }
-            FieldUtils.writeDeclaredField(entity, DRIVER_MANAGER_FIELD_NAME, null, true);
+            FieldUtils.writeDeclaredField(entity, CONNECTION_MANAGER_FIELD_NAME, null, true);
         } catch (IllegalAccessException e) {
             throw new OPMException("Unable to fetch driverManager instance on entity instance", e);
         }
diff --git a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/ConnectedEntityTest.java b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/ConnectedEntityTest.java
index e4c7de4a58..3724a65bc0 100644
--- a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/ConnectedEntityTest.java
+++ b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/ConnectedEntityTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.opm;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.spi.values.PlcSTRING;
 import org.apache.plc4x.java.mock.connection.MockConnection;
@@ -42,7 +42,7 @@ import static org.mockito.Mockito.*;
 @ExtendWith(MockitoExtension.class)
 public class ConnectedEntityTest {
 
-    PlcDriverManager driverManager;
+    DefaultPlcDriverManager driverManager;
 
     MockConnection connection;
 
@@ -53,7 +53,7 @@ public class ConnectedEntityTest {
 
     @BeforeEach
     void setUp() throws Exception {
-        driverManager = new PlcDriverManager();
+        driverManager = new DefaultPlcDriverManager();
         connection = (MockConnection) driverManager.getConnection("mock:cached");
         when(mockDevice.read(any()))
             .thenReturn(new ResponseItem<>(PlcResponseCode.OK, new PlcSTRING("hallo")));
diff --git a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityInterceptorTest.java b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityInterceptorTest.java
index f35ada67d7..2d77e7a58a 100644
--- a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityInterceptorTest.java
+++ b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityInterceptorTest.java
@@ -18,7 +18,8 @@
  */
 package org.apache.plc4x.java.opm;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
@@ -59,7 +60,7 @@ public class PlcEntityInterceptorTest implements WithAssertions {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(PlcEntityInterceptorTest.class);
 
-    PlcDriverManager driverManager;
+    DefaultPlcDriverManager driverManager;
 
     MockConnection connection;
 
@@ -70,7 +71,7 @@ public class PlcEntityInterceptorTest implements WithAssertions {
 
     @BeforeEach
     void setUp() throws Exception {
-        driverManager = new PlcDriverManager();
+        driverManager = new DefaultPlcDriverManager();
         connection = (MockConnection) driverManager.getConnection("mock:test");
         connection.setDevice(mockDevice);
         entityManager = new PlcEntityManager(driverManager);
@@ -139,7 +140,7 @@ public class PlcEntityInterceptorTest implements WithAssertions {
         Callable callable;
 
         @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-        PlcDriverManager plcDriverManager;
+        PlcConnectionManager connectionManager;
 
         class MiscEntity {
 
@@ -181,27 +182,27 @@ public class PlcEntityInterceptorTest implements WithAssertions {
             assertThatThrownBy(() -> PlcEntityInterceptor.interceptGetter(null, MiscEntity.class.getDeclaredMethod("something"), callable, null, null, null, lastFetched, lastWritten))
                 .isInstanceOf(OPMException.class)
                 .hasMessage("Exception during forwarding call");
-            assertThatThrownBy(() -> PlcEntityInterceptor.interceptGetter(null, MiscEntity.class.getDeclaredMethod("getTest", String.class), callable, null, plcDriverManager, null, lastFetched, lastWritten))
+            assertThatThrownBy(() -> PlcEntityInterceptor.interceptGetter(null, MiscEntity.class.getDeclaredMethod("getTest", String.class), callable, null, connectionManager, null, lastFetched, lastWritten))
                 .isInstanceOf(OPMException.class)
                 .hasMessage("Only getter with no arguments are supported");
-            assertThatThrownBy(() -> PlcEntityInterceptor.interceptGetter(null, MiscEntity.class.getDeclaredMethod("getOk"), callable, null, plcDriverManager, null, lastFetched, lastWritten))
+            assertThatThrownBy(() -> PlcEntityInterceptor.interceptGetter(null, MiscEntity.class.getDeclaredMethod("getOk"), callable, null, connectionManager, null, lastFetched, lastWritten))
                 .isInstanceOf(OPMException.class)
                 .hasMessageMatching("Unable to identify tag with name .*");
-            assertThatThrownBy(() -> PlcEntityInterceptor.interceptGetter(null, MiscEntity.class.getDeclaredMethod("getOk2"), callable, null, plcDriverManager, null, lastFetched, lastWritten))
+            assertThatThrownBy(() -> PlcEntityInterceptor.interceptGetter(null, MiscEntity.class.getDeclaredMethod("getOk2"), callable, null, connectionManager, null, lastFetched, lastWritten))
                 .isInstanceOf(OPMException.class)
                 .hasMessage("Problem during processing");
-            assertThatThrownBy(() -> PlcEntityInterceptor.interceptGetter(null, MiscEntity.class.getDeclaredMethod("getOk2"), callable, null, plcDriverManager, null, lastFetched, lastWritten))
+            assertThatThrownBy(() -> PlcEntityInterceptor.interceptGetter(null, MiscEntity.class.getDeclaredMethod("getOk2"), callable, null, connectionManager, null, lastFetched, lastWritten))
                 .isInstanceOf(OPMException.class)
                 .hasMessage("Problem during processing")
                 .hasStackTraceContaining(" Unable to read specified tag 'org.apache.plc4x.java.opm.PlcEntityInterceptorTest$Misc$MiscEntity.ok2', response code was 'Mock for PlcResponseCode");
-            assertThatThrownBy(() -> PlcEntityInterceptor.interceptSetter(null, MiscEntity.class.getDeclaredMethod("setOk2", String.class), callable, null, plcDriverManager, null, lastFetched, lastWritten))
+            assertThatThrownBy(() -> PlcEntityInterceptor.interceptSetter(null, MiscEntity.class.getDeclaredMethod("setOk2", String.class), callable, null, connectionManager, null, lastFetched, lastWritten))
                 .isInstanceOf(OPMException.class)
                 .hasMessage("Problem during processing")
                 .hasStackTraceContaining(" Unable to read specified tag 'org.apache.plc4x.java.opm.PlcEntityInterceptorTest$Misc$MiscEntity.ok2', response code was 'Mock for PlcResponseCode");
-            assertThatThrownBy(() -> PlcEntityInterceptor.interceptSetter(null, MiscEntity.class.getDeclaredMethod("setOkOk", String.class, String.class), callable, null, plcDriverManager, null, lastFetched, lastWritten))
+            assertThatThrownBy(() -> PlcEntityInterceptor.interceptSetter(null, MiscEntity.class.getDeclaredMethod("setOkOk", String.class, String.class), callable, null, connectionManager, null, lastFetched, lastWritten))
                 .isInstanceOf(OPMException.class)
                 .hasMessage("Only setter with one arguments are supported");
-            assertThatThrownBy(() -> PlcEntityInterceptor.interceptSetter(null, MiscEntity.class.getDeclaredMethod("someNotSetterMethod", String.class), callable, null, plcDriverManager, null, lastFetched, lastWritten))
+            assertThatThrownBy(() -> PlcEntityInterceptor.interceptSetter(null, MiscEntity.class.getDeclaredMethod("someNotSetterMethod", String.class), callable, null, connectionManager, null, lastFetched, lastWritten))
                 .isInstanceOf(OPMException.class)
                 .hasMessage("Unable to forward invocation someNotSetterMethod on connected PlcEntity");
         }
diff --git a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java
index 797f0a3c1d..e10a89dbf7 100644
--- a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java
+++ b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java
@@ -19,7 +19,7 @@
 package org.apache.plc4x.java.opm;
 
 import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
@@ -62,7 +62,7 @@ import static org.mockito.Mockito.when;
 
 public class PlcEntityManagerComplexTest implements WithAssertions {
 
-    private PlcDriverManager driverManager;
+    private DefaultPlcDriverManager driverManager;
 
     @Test
     public void noEntity_throws() {
@@ -175,7 +175,7 @@ public class PlcEntityManagerComplexTest implements WithAssertions {
         manager.disconnect(connected);
 
         // Assert disconnected
-        Object o = FieldUtils.readDeclaredField(connected, PlcEntityManager.DRIVER_MANAGER_FIELD_NAME, true);
+        Object o = FieldUtils.readDeclaredField(connected, PlcEntityManager.CONNECTION_MANAGER_FIELD_NAME, true);
         assertNull(o);
 
         // Call a method and receive the result
@@ -197,8 +197,8 @@ public class PlcEntityManagerComplexTest implements WithAssertions {
     }
 
     private PlcEntityManager getPlcEntityManager(final Map<String, PlcValue> responses) throws PlcConnectionException {
-        driverManager = Mockito.mock(PlcDriverManager.class);
-        PlcDriverManager mock = driverManager;
+        driverManager = Mockito.mock(DefaultPlcDriverManager.class);
+        DefaultPlcDriverManager mock = driverManager;
         PlcConnection connection = Mockito.mock(PlcConnection.class);
         when(mock.getConnection(ArgumentMatchers.anyString())).thenReturn(connection);
         when(connection.getMetadata()).thenReturn(new PlcConnectionMetadata() {
diff --git a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerTest.java b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerTest.java
index 2cea1e6ea1..389f58335f 100644
--- a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerTest.java
+++ b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerTest.java
@@ -19,7 +19,7 @@
 package org.apache.plc4x.java.opm;
 
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
@@ -49,7 +49,7 @@ public class PlcEntityManagerTest implements WithAssertions {
     class Read {
 
         @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-        PlcDriverManager driverManager;
+        DefaultPlcDriverManager driverManager;
 
         @Test
         public void throwsInvalidTagException_rethrows() throws PlcConnectionException {
@@ -85,7 +85,7 @@ public class PlcEntityManagerTest implements WithAssertions {
         public void timeoutOnGet_throwsException() throws PlcConnectionException {
             // Prepare the Mock
             MockDevice mockDevice = Mockito.mock(MockDevice.class);
-            PlcDriverManager driverManager = new PlcDriverManager();
+            DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
             MockConnection connection = (MockConnection) driverManager.getConnection("mock:test");
             when(mockDevice.read(any())).thenAnswer(invocation -> {
                 // Sleep for 3s
@@ -116,7 +116,7 @@ public class PlcEntityManagerTest implements WithAssertions {
             registry.register("alias", "real_tag");
 
             // Mock
-            PlcDriverManager driverManager = new PlcDriverManager();
+            DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
             MockConnection connection = (MockConnection) driverManager.getConnection("mock:test");
             MockDevice mockDevice = Mockito.mock(MockDevice.class);
             when(mockDevice.read(any())).thenReturn(new ResponseItem<>(PlcResponseCode.OK, new PlcSTRING("value")));
@@ -165,7 +165,7 @@ public class PlcEntityManagerTest implements WithAssertions {
             registry.register("alias", "real_tag");
 
             // Mock
-            PlcDriverManager driverManager = new PlcDriverManager();
+            DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
             MockConnection connection = (MockConnection) driverManager.getConnection("mock:test");
             MockDevice mockDevice = Mockito.mock(MockDevice.class);
             when(mockDevice.write(anyString(), any())).thenReturn(PlcResponseCode.OK);
@@ -195,7 +195,7 @@ public class PlcEntityManagerTest implements WithAssertions {
         @Test
         void simpleWrite_uses_getter() throws Exception {
             // Mock
-            PlcDriverManager driverManager = new PlcDriverManager();
+            DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
             MockConnection connection = (MockConnection) driverManager.getConnection("mock:test");
             MockDevice mockDevice = Mockito.mock(MockDevice.class);
             when(mockDevice.read(any())).thenReturn(new ResponseItem<>(PlcResponseCode.OK, new PlcSTRING("value")));
@@ -228,7 +228,7 @@ public class PlcEntityManagerTest implements WithAssertions {
             registry.register("alias", "real_tag");
 
             // Mock
-            PlcDriverManager driverManager = new PlcDriverManager();
+            DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
             MockConnection connection = (MockConnection) driverManager.getConnection("mock:test");
             MockDevice mockDevice = Mockito.mock(MockDevice.class);
             when(mockDevice.read(any())).thenReturn(new ResponseItem<>(PlcResponseCode.OK, new PlcSTRING("value")));
diff --git a/plc4j/tools/plc4x-server/src/main/java/org/apache/plc4x/java/tools/plc4xserver/protocol/Plc4xServerAdapter.java b/plc4j/tools/plc4x-server/src/main/java/org/apache/plc4x/java/tools/plc4xserver/protocol/Plc4xServerAdapter.java
index 391d0af0ef..7194b24ffc 100644
--- a/plc4j/tools/plc4x-server/src/main/java/org/apache/plc4x/java/tools/plc4xserver/protocol/Plc4xServerAdapter.java
+++ b/plc4j/tools/plc4x-server/src/main/java/org/apache/plc4x/java/tools/plc4xserver/protocol/Plc4xServerAdapter.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.java.tools.plc4xserver.protocol;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
 import org.apache.plc4x.java.api.messages.PlcWriteRequest;
@@ -28,7 +29,7 @@ import org.apache.plc4x.java.api.messages.PlcWriteResponse;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.plc4x.readwrite.*;
-import org.apache.plc4x.java.utils.connectionpool2.PooledDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -42,12 +43,12 @@ public class Plc4xServerAdapter extends ChannelInboundHandlerAdapter {
 
     private final Logger logger = LoggerFactory.getLogger(Plc4xServerAdapter.class);
 
-    private final PooledDriverManager driverManager;
+    private final PlcConnectionManager connectionManager;
     private final AtomicInteger connectionIdGenerator;
     private final ConcurrentHashMap<Integer, String> connectionUrls;
 
     public Plc4xServerAdapter() {
-        driverManager = new PooledDriverManager();
+        connectionManager = CachedPlcConnectionManager.getBuilder().build();
         connectionIdGenerator = new AtomicInteger(1);
         connectionUrls = new ConcurrentHashMap<>();
     }
@@ -59,7 +60,7 @@ public class Plc4xServerAdapter extends ChannelInboundHandlerAdapter {
             switch (plc4xMessage.getRequestType()) {
                 case CONNECT_REQUEST: {
                     Plc4xConnectRequest request = (Plc4xConnectRequest) plc4xMessage;
-                    try (final PlcConnection ignored = driverManager.getConnection(request.getConnectionString())) {
+                    try (final PlcConnection ignored = connectionManager.getConnection(request.getConnectionString())) {
                         //connection.ping().get();
                         final int connectionId = connectionIdGenerator.getAndIncrement();
                         connectionUrls.put(connectionId, request.getConnectionString());
@@ -76,7 +77,7 @@ public class Plc4xServerAdapter extends ChannelInboundHandlerAdapter {
                 case READ_REQUEST: {
                     final Plc4xReadRequest request = (Plc4xReadRequest) plc4xMessage;
                     String connectionUrl = connectionUrls.get(request.getConnectionId());
-                    try (final PlcConnection connection = driverManager.getConnection(connectionUrl)) {
+                    try (final PlcConnection connection = connectionManager.getConnection(connectionUrl)) {
                         // Build a read request for all tags in the request.
                         final PlcReadRequest.Builder builder = connection.readRequestBuilder();
                         for (Plc4xTagRequest requestTag : request.getTags()) {
@@ -127,7 +128,7 @@ public class Plc4xServerAdapter extends ChannelInboundHandlerAdapter {
                 case WRITE_REQUEST:
                     final Plc4xWriteRequest plc4xWriteRequest = (Plc4xWriteRequest) plc4xMessage;
                     String connectionUrl = connectionUrls.get(plc4xWriteRequest.getConnectionId());
-                    try (final PlcConnection connection = driverManager.getConnection(connectionUrl)) {
+                    try (final PlcConnection connection = connectionManager.getConnection(connectionUrl)) {
                         // Build a write request for all tags in the request.
                         final PlcWriteRequest.Builder builder = connection.writeRequestBuilder();
                         for (Plc4xTagValueRequest plc4xRequestTag : plc4xWriteRequest.getTags()) {
diff --git a/plc4j/tools/pom.xml b/plc4j/tools/pom.xml
index c3fbe156a4..9fe529019a 100644
--- a/plc4j/tools/pom.xml
+++ b/plc4j/tools/pom.xml
@@ -36,10 +36,10 @@
   <modules>
     <module>capture-replay</module>
     <module>connection-cache</module>
-    <module>connection-pool</module>
     <module>opm</module>
     <module>plc4x-server</module>
     <module>scraper</module>
+    <module>scraper-ng</module>
     <module>ui</module>
   </modules>
 
diff --git a/plc4j/tools/scraper/pom.xml b/plc4j/tools/scraper-ng/pom.xml
similarity index 93%
copy from plc4j/tools/scraper/pom.xml
copy to plc4j/tools/scraper-ng/pom.xml
index 3ad45ff7a2..ef871edaa4 100644
--- a/plc4j/tools/scraper/pom.xml
+++ b/plc4j/tools/scraper-ng/pom.xml
@@ -27,14 +27,14 @@
     <version>0.11.0-SNAPSHOT</version>
   </parent>
 
-  <artifactId>plc4j-scraper</artifactId>
+  <artifactId>plc4j-scraper-ng</artifactId>
 
-  <name>PLC4J: Tools: Scraper</name>
+  <name>PLC4J: Tools: Scraper (NG)</name>
   <description>Utility to efficiently collect a large number of items on multiple devices by different triggers.</description>
 
   <dependencies>
     <!--Jackson-->
-    <dependency>
+    <!--dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-core</artifactId>
     </dependency>
@@ -49,10 +49,10 @@
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-databind</artifactId>
-    </dependency>
+    </dependency-->
 
     <!-- Apache Commons -->
-    <dependency>
+    <!--dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-math3</artifactId>
     </dependency>
@@ -67,10 +67,10 @@
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-collections4</artifactId>
-    </dependency>
+    </dependency-->
 
     <!-- PLC4X dependencies -->
-    <dependency>
+    <!--dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-api</artifactId>
       <version>0.11.0-SNAPSHOT</version>
@@ -80,6 +80,11 @@
       <artifactId>plc4j-connection-pool</artifactId>
       <version>0.11.0-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-connection-cache</artifactId>
+      <version>0.11.0-SNAPSHOT</version>
+    </dependency-->
 
     <dependency>
       <groupId>org.apache.plc4x</groupId>
@@ -100,12 +105,6 @@
       <version>0.11.0-SNAPSHOT</version>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.apache.plc4x</groupId>
-      <artifactId>plc4j-connection-cache</artifactId>
-      <version>0.11.0-SNAPSHOT</version>
-      <scope>compile</scope>
-    </dependency>
   </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/plc4j/tools/scraper/pom.xml b/plc4j/tools/scraper/pom.xml
index 3ad45ff7a2..30536e52ca 100644
--- a/plc4j/tools/scraper/pom.xml
+++ b/plc4j/tools/scraper/pom.xml
@@ -56,10 +56,6 @@
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-math3</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-pool2</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
@@ -77,7 +73,7 @@
     </dependency>
     <dependency>
       <groupId>org.apache.plc4x</groupId>
-      <artifactId>plc4j-connection-pool</artifactId>
+      <artifactId>plc4j-connection-cache</artifactId>
       <version>0.11.0-SNAPSHOT</version>
     </dependency>
 
@@ -100,12 +96,6 @@
       <version>0.11.0-SNAPSHOT</version>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.apache.plc4x</groupId>
-      <artifactId>plc4j-connection-cache</artifactId>
-      <version>0.11.0-SNAPSHOT</version>
-      <scope>compile</scope>
-    </dependency>
   </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/ScraperImpl.java b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/ScraperImpl.java
index a29143d67d..d4428247e1 100644
--- a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/ScraperImpl.java
+++ b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/ScraperImpl.java
@@ -24,14 +24,11 @@ import org.apache.commons.lang3.Validate;
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
 import org.apache.commons.lang3.tuple.Triple;
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
-import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
-import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.scraper.config.ScraperConfiguration;
 import org.apache.plc4x.java.scraper.exception.ScraperException;
 import org.apache.plc4x.java.scraper.util.PercentageAboveThreshold;
-import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -67,31 +64,31 @@ public class ScraperImpl implements Scraper {
 
     private final MultiValuedMap<ScrapeJob, ScraperTask> tasks = new ArrayListValuedHashMap<>();
     private final MultiValuedMap<ScraperTask, ScheduledFuture<?>> futures = new ArrayListValuedHashMap<>();
-    private final PlcDriverManager driverManager;
+    private final PlcConnectionManager connectionManager;
     private final List<ScrapeJob> jobs;
 
     /**
      * default constructor
      * @param resultHandler handler for acquired data
-     * @param driverManager handler for Plc connection
+     * @param connectionManager handler for Plc connection
      * @param jobs list of scrapings jobs to be executed
      */
-    public ScraperImpl(ResultHandler resultHandler, PlcDriverManager driverManager, List<ScrapeJob> jobs) {
+    public ScraperImpl(ResultHandler resultHandler, PlcConnectionManager connectionManager, List<ScrapeJob> jobs) {
         this.resultHandler = resultHandler;
         Validate.notEmpty(jobs);
-        this.driverManager = driverManager;
+        this.connectionManager = connectionManager;
         this.jobs = jobs;
     }
 
     /**
      * Creates a Scraper instance from a configuration.
-     * By default a {@link PooledPlcDriverManager} is used.
+     * By default, a {@link CachedPlcConnectionManager} is used.
      * @param config Configuration to use.
      * @param resultHandler handler for acquired data
      * @throws ScraperException something went wrong ...
      */
     public ScraperImpl(ScraperConfiguration config, ResultHandler resultHandler) throws ScraperException {
-        this(resultHandler, createPooledDriverManager(), config.getJobs());
+        this(resultHandler, createCachedPlcConnectionManager(), config.getJobs());
     }
 
     /**
@@ -99,18 +96,10 @@ public class ScraperImpl implements Scraper {
      * Then, on reconnect we can fail all getConnection calls (in the ScraperTask) fast until
      * (in the background) the idle connection is created and the getConnection call returns fast.
      */
-    private static PooledPlcDriverManager createPooledDriverManager() {
-        return new PooledPlcDriverManager(pooledPlcConnectionFactory -> {
-            GenericKeyedObjectPoolConfig<PlcConnection> poolConfig = new GenericKeyedObjectPoolConfig<>();
-            poolConfig.setMinIdlePerKey(1);  // This should avoid problems with long running connect attempts??
-            poolConfig.setTestOnBorrow(true);
-            poolConfig.setTestOnReturn(true);
-            return new GenericKeyedObjectPool<>(pooledPlcConnectionFactory, poolConfig);
-        });
+    private static CachedPlcConnectionManager createCachedPlcConnectionManager() {
+        return CachedPlcConnectionManager.getBuilder().build();
     }
 
-
-
     @Override
     public void start() {
         // Schedule all jobs
@@ -123,7 +112,7 @@ public class ScraperImpl implements Scraper {
                 tuple -> {
                     LOGGER.debug("Register task for job {} for conn {} ({}) at rate {} ms",
                         tuple.getLeft().getJobName(), tuple.getMiddle(), tuple.getRight(), tuple.getLeft().getScrapeRate());
-                    ScraperTask task = new ScraperTaskImpl(driverManager,
+                    ScraperTask task = new ScraperTaskImpl(connectionManager,
                         tuple.getLeft().getJobName(), tuple.getMiddle(), tuple.getRight(),
                         tuple.getLeft().getTags(),
                         1_000,
diff --git a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/ScraperTaskImpl.java b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/ScraperTaskImpl.java
index 2b414a1e54..96e2c7c669 100644
--- a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/ScraperTaskImpl.java
+++ b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/ScraperTaskImpl.java
@@ -21,8 +21,8 @@ package org.apache.plc4x.java.scraper;
 import org.apache.commons.lang3.Validate;
 import org.apache.commons.lang3.time.StopWatch;
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
@@ -53,7 +53,7 @@ public class ScraperTaskImpl implements ScraperTask {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ScraperTaskImpl.class);
 
-    private final PlcDriverManager driverManager;
+    private final PlcConnectionManager connectionManager;
     private final String jobName;
     private final String connectionAlias;
     private final String connectionString;
@@ -67,7 +67,7 @@ public class ScraperTaskImpl implements ScraperTask {
     private final DescriptiveStatistics latencyStatistics = new DescriptiveStatistics(1000);
     private final DescriptiveStatistics failedStatistics = new DescriptiveStatistics(1000);
 
-    public ScraperTaskImpl(PlcDriverManager driverManager,
+    public ScraperTaskImpl(PlcConnectionManager connectionManager,
                            String jobName,
                            String connectionAlias,
                            String connectionString,
@@ -75,14 +75,14 @@ public class ScraperTaskImpl implements ScraperTask {
                            long requestTimeoutMs,
                            ExecutorService handlerService,
                            ResultHandler resultHandler) {
-        Validate.notNull(driverManager);
+        Validate.notNull(connectionManager);
         Validate.notBlank(jobName);
         Validate.notBlank(connectionAlias);
         Validate.notBlank(connectionString);
         Validate.notEmpty(tags);
         Validate.isTrue(requestTimeoutMs > 0);
         Validate.notNull(resultHandler);
-        this.driverManager = driverManager;
+        this.connectionManager = connectionManager;
         this.jobName = jobName;
         this.connectionAlias = connectionAlias;
         this.connectionString = connectionString;
@@ -106,7 +106,7 @@ public class ScraperTaskImpl implements ScraperTask {
         try {
             CompletableFuture<PlcConnection> future = CompletableFuture.supplyAsync(() -> {
                 try {
-                    return driverManager.getConnection(connectionString);
+                    return connectionManager.getConnection(connectionString);
                 } catch (PlcConnectionException e) {
                     LOGGER.warn("Unable to instantiate connection to " + connectionString, e);
                     throw new PlcRuntimeException(e);
diff --git a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImpl.java b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImpl.java
index 8afb916dd9..7772b6f500 100644
--- a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImpl.java
+++ b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImpl.java
@@ -23,8 +23,8 @@ import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
 import org.apache.commons.lang3.Validate;
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
@@ -35,7 +35,7 @@ import org.apache.plc4x.java.scraper.config.triggeredscraper.ScraperConfiguratio
 import org.apache.plc4x.java.scraper.triggeredscraper.triggerhandler.collector.TriggerCollector;
 import org.apache.plc4x.java.scraper.util.PercentageAboveThreshold;
 import org.apache.plc4x.java.api.PlcDriver;
-import org.apache.plc4x.java.utils.connectionpool2.PooledDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -73,7 +73,7 @@ public class TriggeredScraperImpl implements Scraper, TriggeredScraperMBean {
 
     private final MultiValuedMap<ScrapeJob, ScraperTask> tasks = new ArrayListValuedHashMap<>();
     private final MultiValuedMap<ScraperTask, ScheduledFuture<?>> scraperTaskMap = new ArrayListValuedHashMap<>();
-    private final PlcDriverManager driverManager;
+    private final PlcConnectionManager plcConnectionManager;
     private final List<ScrapeJob> jobs;
     private MBeanServer mBeanServer;
 
@@ -83,61 +83,61 @@ public class TriggeredScraperImpl implements Scraper, TriggeredScraperMBean {
 
     /**
      * Creates a Scraper instance from a configuration.
-     * By default a {@link PooledDriverManager} is used.
+     * By default a {@link CachedPlcConnectionManager} is used.
      * @param config Configuration to use.
      * @param resultHandler handler the defines the processing of acquired data
      * @param triggerCollector the trigger collector
      * @throws ScraperException something went wrong
      */
     public TriggeredScraperImpl(ScraperConfiguration config, ResultHandler resultHandler, TriggerCollector triggerCollector) throws ScraperException {
-        this(resultHandler, createPooledDriverManager(), config.getJobs(),triggerCollector,DEFAULT_FUTURE_TIME_OUT);
+        this(resultHandler, createCachedPlcConnectionManager(), config.getJobs(),triggerCollector,DEFAULT_FUTURE_TIME_OUT);
     }
 
     /**
      * Creates a Scraper instance from a configuration.
      * @param config Configuration to use.
-     * @param plcDriverManager external DriverManager
+     * @param plcConnectionManager external DriverManager
      * @param resultHandler handler the defines the processing of acquired data
      * @param triggerCollector the trigger collector
      * @throws ScraperException something went wrong
      */
-    public TriggeredScraperImpl(ScraperConfiguration config, PlcDriverManager plcDriverManager, ResultHandler resultHandler,TriggerCollector triggerCollector) throws ScraperException {
-        this(resultHandler, plcDriverManager, config.getJobs(),triggerCollector,DEFAULT_FUTURE_TIME_OUT);
+    public TriggeredScraperImpl(ScraperConfiguration config, PlcConnectionManager plcConnectionManager, ResultHandler resultHandler, TriggerCollector triggerCollector) throws ScraperException {
+        this(resultHandler, plcConnectionManager, config.getJobs(),triggerCollector,DEFAULT_FUTURE_TIME_OUT);
     }
 
     /**
      * Creates a Scraper instance from a configuration.
      * @param config Configuration to use.
-     * @param plcDriverManager external DriverManager
+     * @param plcConnectionManager external DriverManager
      * @param resultHandler handler the defines the processing of acquired data
      * @param triggerCollector the trigger collector
      * @param poolSizeExecutor the pool size of the executor
      * @param poolSizeScheduler the pool size of the scheduler
      * @throws ScraperException something went wrong
      */
-    public TriggeredScraperImpl(ScraperConfigurationTriggeredImpl config, PlcDriverManager plcDriverManager, ResultHandler resultHandler, TriggerCollector triggerCollector, int poolSizeScheduler, int poolSizeExecutor) throws ScraperException {
-        this(resultHandler, plcDriverManager, config.getJobs(),triggerCollector,DEFAULT_FUTURE_TIME_OUT,poolSizeScheduler,poolSizeExecutor);
+    public TriggeredScraperImpl(ScraperConfigurationTriggeredImpl config, PlcConnectionManager plcConnectionManager, ResultHandler resultHandler, TriggerCollector triggerCollector, int poolSizeScheduler, int poolSizeExecutor) throws ScraperException {
+        this(resultHandler, plcConnectionManager, config.getJobs(),triggerCollector,DEFAULT_FUTURE_TIME_OUT,poolSizeScheduler,poolSizeExecutor);
     }
 
     /**
      * Creates a Scraper instance from a configuration.
-     * @param plcDriverManager external DriverManager
+     * @param plcConnectionManager external DriverManager
      * @param resultHandler handler the defines the processing of acquired data
      * @param jobs list of jobs that scraper shall handle
      * @param triggerCollector a collection that centralizes the trigger requests and joins them to grouped plc requests
      * @param futureTimeOut max duration of future to return a result
      */
-    public TriggeredScraperImpl(ResultHandler resultHandler, PlcDriverManager plcDriverManager, List<ScrapeJob> jobs,TriggerCollector triggerCollector, long futureTimeOut) {
-        this(resultHandler,plcDriverManager,jobs,triggerCollector,futureTimeOut,20,5);
+    public TriggeredScraperImpl(ResultHandler resultHandler, PlcConnectionManager plcConnectionManager, List<ScrapeJob> jobs,TriggerCollector triggerCollector, long futureTimeOut) {
+        this(resultHandler,plcConnectionManager,jobs,triggerCollector,futureTimeOut,20,5);
     }
 
-    public TriggeredScraperImpl(ResultHandler resultHandler, PlcDriverManager plcDriverManager, List<ScrapeJob> jobs,TriggerCollector triggerCollector, long futureTimeOut, int poolSizeScheduler, int poolSizeExecutor) {
+    public TriggeredScraperImpl(ResultHandler resultHandler, PlcConnectionManager plcConnectionManager, List<ScrapeJob> jobs,TriggerCollector triggerCollector, long futureTimeOut, int poolSizeScheduler, int poolSizeExecutor) {
         this.resultHandler = resultHandler;
         Validate.notEmpty(jobs);
-        if (!(plcDriverManager instanceof PooledDriverManager)) {
-            LOGGER.warn("The Triggered Scraper is intended to be used with a Pooled Connection. In other situations leaks could occur!");
+        if (!(plcConnectionManager instanceof CachedPlcConnectionManager)) {
+            LOGGER.warn("The Triggered Scraper is intended to be used with a cached PlcConnectionManager. In other situations leaks could occur!");
         }
-        this.driverManager = plcDriverManager;
+        this.plcConnectionManager = plcConnectionManager;
         this.jobs = jobs;
         this.triggerCollector = triggerCollector;
         this.futureTimeOut = futureTimeOut;
@@ -172,8 +172,8 @@ public class TriggeredScraperImpl implements Scraper, TriggeredScraperMBean {
      * Then, on reconnect we can fail all getConnection calls (in the ScraperTask) fast until
      * (in the background) the idle connection is created and the getConnection call returns fast.
      */
-    private static PooledDriverManager createPooledDriverManager() {
-        return new PooledDriverManager();
+    private static CachedPlcConnectionManager createCachedPlcConnectionManager() {
+        return CachedPlcConnectionManager.getBuilder().build();
     }
 
     /**
@@ -200,7 +200,7 @@ public class TriggeredScraperImpl implements Scraper, TriggeredScraperMBean {
                 TriggeredScraperTask triggeredScraperTask;
                 try {
                     triggeredScraperTask = new TriggeredScraperTask(
-                        driverManager,
+                        plcConnectionManager,
                         job.getJobName(),
                         sourceEntry.getKey(),
                         sourceEntry.getValue(),
@@ -276,17 +276,17 @@ public class TriggeredScraperImpl implements Scraper, TriggeredScraperMBean {
 
     /**
      * acquires a plc connection from connection pool
-     * @param plcDriverManager  Driver manager handling connection and pools
-     * @param connectionString  Connection string as defined in the regarding implementation of {@link PlcDriver}
-     * @param executorService   ExecuterService holding a pool as threads handling requests and stuff
-     * @param requestTimeoutMs  maximum awaiting for the the future to return a result
-     * @param info              additional info for trace reasons
+     * @param plcConnectionManager  Connection manager handling connection and pools
+     * @param connectionString      Connection string as defined in the regarding implementation of {@link PlcDriver}
+     * @param executorService       ExecutorService holding a pool as threads handling requests and stuff
+     * @param requestTimeoutMs      maximum wait time for the future to return a result
+     * @param info                  additional info for trace reasons
      * @return the {@link PlcConnection} used for acquiring data from PLC endpoint
      * @throws InterruptedException something went wrong
      * @throws ExecutionException something went wrong
      * @throws TimeoutException something went wrong
      */
-    public static PlcConnection getPlcConnection(PlcDriverManager plcDriverManager,
+    public static PlcConnection getPlcConnection(PlcConnectionManager plcConnectionManager,
                                                  String connectionString,
                                                  ExecutorService executorService,
                                                  long requestTimeoutMs,
@@ -296,7 +296,7 @@ public class TriggeredScraperImpl implements Scraper, TriggeredScraperMBean {
         }
         CompletableFuture<PlcConnection> future = CompletableFuture.supplyAsync(() -> {
             try {
-                return plcDriverManager.getConnection(connectionString);
+                return plcConnectionManager.getConnection(connectionString);
             } catch (PlcConnectionException e) {
                 LOGGER.warn("Unable to instantiate connection to " + connectionString, e);
                 throw new PlcRuntimeException(e);
@@ -322,20 +322,20 @@ public class TriggeredScraperImpl implements Scraper, TriggeredScraperMBean {
 
     /**
      * acquires a plc connection from connection pool
-     * @param plcDriverManager  Driver manager handling connection and pools
+     * @param plcConnectionManager  Connection manager handling connection and pools
      * @param connectionString  Connection string as defined in the regarding implementation of {@link PlcDriver}
      * @param executorService   ExecuterService holding a pool as threads handling requests and stuff
-     * @param requestTimeoutMs  maximum awaiting for the the future to return a result
+     * @param requestTimeoutMs  maximum waiting time for the future to return a result
      * @return the {@link PlcConnection} used for acquiring data from PLC endpoint
      * @throws InterruptedException something went wrong
      * @throws ExecutionException something went wrong
      * @throws TimeoutException something went wrong
      */
-    public static PlcConnection getPlcConnection(PlcDriverManager plcDriverManager,
+    public static PlcConnection getPlcConnection(PlcConnectionManager plcConnectionManager,
                                                  String connectionString,
                                                  ExecutorService executorService,
                                                  long requestTimeoutMs) throws InterruptedException, ExecutionException, TimeoutException {
-        return getPlcConnection(plcDriverManager,connectionString,executorService,requestTimeoutMs,"");
+        return getPlcConnection(plcConnectionManager,connectionString,executorService,requestTimeoutMs,"");
     }
 
     /**
diff --git a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java
index 8e2fd70334..cd84143918 100644
--- a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java
+++ b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java
@@ -20,8 +20,8 @@ package org.apache.plc4x.java.scraper.triggeredscraper;
 
 import org.apache.commons.lang3.time.StopWatch;
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
@@ -49,7 +49,7 @@ import java.util.stream.Collectors;
 public class TriggeredScraperTask implements ScraperTask, TriggeredScraperTaskMBean {
     private static final Logger LOGGER = LoggerFactory.getLogger(TriggeredScraperTask.class);
 
-    private final PlcDriverManager driverManager;
+    private final PlcConnectionManager connectionManager;
     private final String jobName;
     private final String connectionAlias;
     private final String connectionString;
@@ -65,7 +65,7 @@ public class TriggeredScraperTask implements ScraperTask, TriggeredScraperTaskMB
     private final DescriptiveStatistics failedStatistics = new DescriptiveStatistics(1000);
 
 
-    public TriggeredScraperTask(PlcDriverManager driverManager,
+    public TriggeredScraperTask(PlcConnectionManager connectionManager,
                                 String jobName,
                                 String connectionAlias,
                                 String connectionString,
@@ -75,7 +75,7 @@ public class TriggeredScraperTask implements ScraperTask, TriggeredScraperTaskMB
                                 ResultHandler resultHandler,
                                 TriggeredScrapeJobImpl triggeredScrapeJob,
                                 TriggerCollector triggerCollector) throws ScraperException {
-        this.driverManager = driverManager;
+        this.connectionManager = connectionManager;
         this.jobName = jobName;
         this.connectionAlias = connectionAlias;
         this.connectionString = connectionString;
@@ -109,7 +109,7 @@ public class TriggeredScraperTask implements ScraperTask, TriggeredScraperTaskMB
                     info = String.format("acquiring data collecting connection to (%s,%s)", connectionAlias,jobName);
                     LOGGER.trace("acquiring data collecting connection to ({},{})", connectionAlias,jobName);
                 }
-                connection = TriggeredScraperImpl.getPlcConnection(driverManager,connectionString,executorService,requestTimeoutMs,info);
+                connection = TriggeredScraperImpl.getPlcConnection(connectionManager,connectionString,executorService,requestTimeoutMs,info);
                 if(LOGGER.isTraceEnabled()) {
                     LOGGER.trace("Connection to {} established: {}", connectionString, connection);
                 }
@@ -213,8 +213,8 @@ public class TriggeredScraperTask implements ScraperTask, TriggeredScraperTaskMB
         LOGGER.warn("Handling error responses: {}", failed);
     }
 
-    public PlcDriverManager getDriverManager() {
-        return driverManager;
+    public PlcConnectionManager getConnectionManager() {
+        return connectionManager;
     }
 
     public String getConnectionString() {
@@ -232,7 +232,7 @@ public class TriggeredScraperTask implements ScraperTask, TriggeredScraperTaskMB
     @Override
     public String toString() {
         return "TriggeredScraperTask{" +
-            "driverManager=" + driverManager +
+            "connectionManager=" + connectionManager +
             ", jobName='" + jobName + '\'' +
             ", connectionAlias='" + connectionAlias + '\'' +
             ", connectionString='" + connectionString + '\'' +
diff --git a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
index 1163cb2137..434c367656 100644
--- a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
+++ b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.scraper.triggeredscraper.triggerhandler;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcDriver;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.model.PlcTag;
@@ -559,7 +559,7 @@ public class TriggerConfiguration{
         //I used this because the prepareField method is deprecated with generated drivers
         //So I need to create the tag using the connection string here
         private PlcTag parseTag(String tagAddress) throws PlcConnectionException {
-            PlcDriverManager driverManager = new PlcDriverManager();
+            DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
             PlcDriver driver = driverManager.getDriverForUrl(plcConnectionString);
             return driver.prepareTag(tagAddress);
         }
diff --git a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/collector/TriggerCollectorImpl.java b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/collector/TriggerCollectorImpl.java
index 8041eecb92..f23ee76ece 100644
--- a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/collector/TriggerCollectorImpl.java
+++ b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/collector/TriggerCollectorImpl.java
@@ -19,13 +19,13 @@
 package org.apache.plc4x.java.scraper.triggeredscraper.triggerhandler.collector;
 
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
 import org.apache.plc4x.java.scraper.exception.ScraperException;
 import org.apache.plc4x.java.scraper.triggeredscraper.TriggeredScraperImpl;
-import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -44,7 +44,7 @@ public class TriggerCollectorImpl implements TriggerCollector {
     private static final int FUTURE_TIMEOUT                     = 2000;
     private static final int READ_REQUEST_TIMEOUT               = 2000;
 
-    private final PlcDriverManager plcDriverManager;
+    private final PlcConnectionManager plcConnectionManager;
     private final Map<String,RequestElement> currentRequestElements;
     private long schedulerInterval;
     private final long futureTimeout;
@@ -52,11 +52,11 @@ public class TriggerCollectorImpl implements TriggerCollector {
     private final ScheduledExecutorService scheduledExecutorService;
     private final ExecutorService executorService;
 
-    public TriggerCollectorImpl(PlcDriverManager plcDriverManager, long schedulerInterval, long futureTimeout, int poolSizeScheduler, int poolSizeExecutor) {
-        if (!(plcDriverManager instanceof PooledPlcDriverManager)) {
-            logger.warn("The Triggered Scraper is intended to be used with a Pooled Connection. In other situations leaks could occur!");
+    public TriggerCollectorImpl(PlcConnectionManager plcConnectionManager, long schedulerInterval, long futureTimeout, int poolSizeScheduler, int poolSizeExecutor) {
+        if (!(plcConnectionManager instanceof CachedPlcConnectionManager)) {
+            logger.warn("The Triggered Scraper is intended to be used with a Cached Connection-Manager. In other situations leaks could occur!");
         }
-        this.plcDriverManager = plcDriverManager;
+        this.plcConnectionManager = plcConnectionManager;
         this.currentRequestElements = new ConcurrentHashMap<>();
         this.schedulerInterval = schedulerInterval;
         this.futureTimeout = futureTimeout;
@@ -76,12 +76,12 @@ public class TriggerCollectorImpl implements TriggerCollector {
 
     }
 
-    public TriggerCollectorImpl(PlcDriverManager plcDriverManager, long schedulerInterval, long futureTimeout) {
-        this(plcDriverManager,schedulerInterval,futureTimeout,10,20);
+    public TriggerCollectorImpl(PlcConnectionManager plcConnectionManager, long schedulerInterval, long futureTimeout) {
+        this(plcConnectionManager,schedulerInterval,futureTimeout,10,20);
     }
 
-    public TriggerCollectorImpl(PlcDriverManager plcDriverManager) {
-        this(plcDriverManager,DEFAULT_SCHEDULED_TRIGGER_INTERVAL, FUTURE_TIMEOUT);
+    public TriggerCollectorImpl(PlcConnectionManager plcConnectionManager) {
+        this(plcConnectionManager,DEFAULT_SCHEDULED_TRIGGER_INTERVAL, FUTURE_TIMEOUT);
     }
 
     /**
@@ -151,7 +151,7 @@ public class TriggerCollectorImpl implements TriggerCollector {
                             info = String.format("acquiring trigger connection to (%s)", plcConnectionString);
                             logger.trace("acquiring trigger connection to ({})", plcConnectionString);
                         }
-                        plcConnection = TriggeredScraperImpl.getPlcConnection(plcDriverManager,plcConnectionString,executorService,futureTimeout,info);
+                        plcConnection = TriggeredScraperImpl.getPlcConnection(plcConnectionManager,plcConnectionString,executorService,futureTimeout,info);
                         plcConnectionList.add(plcConnection);
                         plcReadRequestBuilderMap.put(plcConnectionString,plcConnection.readRequestBuilder());
                         plcReadRequestBuilderMap.get(plcConnectionString).addTagAddress(entry.getKey(),entry.getValue().getPlcTag());
diff --git a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/s7/ManualS7PlcDriverMT.java b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/s7/ManualS7PlcDriverMT.java
index 5b2b440178..e4367e0a4b 100644
--- a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/s7/ManualS7PlcDriverMT.java
+++ b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/s7/ManualS7PlcDriverMT.java
@@ -19,12 +19,12 @@
 package org.apache.plc4x.java.s7;
 
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
-import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -51,11 +51,11 @@ public class ManualS7PlcDriverMT {
 
     @Test
     public void simpleLoop() {
-        PlcDriverManager plcDriverManager = new PooledPlcDriverManager();
+        PlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder().build();
 
         DescriptiveStatistics statistics = new DescriptiveStatistics();
         for (int i = 1; i <= 1000; i++) {
-            double timeNs = runSingleRequest(plcDriverManager);
+            double timeNs = runSingleRequest(connectionManager);
             statistics.addValue(timeNs);
         }
 
@@ -65,7 +65,7 @@ public class ManualS7PlcDriverMT {
     @ParameterizedTest
     @ValueSource(ints = {1, 5, 10, 20})
     public void scheduledLoop(int period) throws InterruptedException {
-        PlcDriverManager plcDriverManager = new PooledPlcDriverManager();
+        PlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder().build();
         ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);
         DescriptiveStatistics statistics = new DescriptiveStatistics();
 
@@ -73,7 +73,7 @@ public class ManualS7PlcDriverMT {
         AtomicInteger counter = new AtomicInteger(0);
         executorService.scheduleAtFixedRate(() -> {
             // System.out.println("Run: " + counter.get());
-            double timeNs = runSingleRequest(plcDriverManager);
+            double timeNs = runSingleRequest(connectionManager);
             statistics.addValue(timeNs);
             if (counter.getAndIncrement() >= numberOfRuns) {
                 executorService.shutdown();
@@ -87,7 +87,7 @@ public class ManualS7PlcDriverMT {
     @Test
     public void parallelScheduledLoop() throws InterruptedException {
         int period = 5;
-        PlcDriverManager plcDriverManager = new PooledPlcDriverManager();
+        PlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder().build();
         ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);
         DescriptiveStatistics statistics1 = new DescriptiveStatistics();
         DescriptiveStatistics statistics2 = new DescriptiveStatistics();
@@ -97,7 +97,7 @@ public class ManualS7PlcDriverMT {
         AtomicInteger counter2 = new AtomicInteger(0);
         executorService.scheduleAtFixedRate(() -> {
             // System.out.println("Run: " + counter.get());
-            double timeNs = runSingleRequest(plcDriverManager);
+            double timeNs = runSingleRequest(connectionManager);
             statistics1.addValue(timeNs);
             if (counter1.getAndIncrement() >= numberOfRuns) {
                 executorService.shutdown();
@@ -105,7 +105,7 @@ public class ManualS7PlcDriverMT {
         }, 0, period, TimeUnit.MILLISECONDS);
         executorService.scheduleAtFixedRate(() -> {
             // System.out.println("Run: " + counter.get());
-            double timeNs = runSingleRequest(plcDriverManager);
+            double timeNs = runSingleRequest(connectionManager);
             statistics2.addValue(timeNs);
             if (counter2.getAndIncrement() >= numberOfRuns) {
                 executorService.shutdown();
@@ -132,21 +132,21 @@ public class ManualS7PlcDriverMT {
     @MethodSource("periodAndRus")
     public void scheduledCancellingLoop(int period, int numberOfRuns) throws InterruptedException, PlcConnectionException {
         System.out.println("Starting iteration with period " + period + " and " + numberOfRuns + " runs.");
-        PlcDriverManager plcDriverManager = new PooledPlcDriverManager();
+        PlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder().build();
         ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);
         DescriptiveStatistics statistics = new DescriptiveStatistics();
 
         AtomicInteger counter = new AtomicInteger(0);
 
         // Warmup
-        plcDriverManager.getConnection(CONN_STRING);
+        connectionManager.getConnection(CONN_STRING);
 
         Runnable iteration = new Runnable() {
             @Override
             public void run() {
 //                System.out.println("Setting a request / guard...");
                 CompletableFuture<Double> requestFuture = CompletableFuture.supplyAsync(
-                    () -> ManualS7PlcDriverMT.this.runSingleRequest(plcDriverManager)
+                    () -> ManualS7PlcDriverMT.this.runSingleRequest(connectionManager)
                 );
                 executorService.schedule(() -> {
                     if (!requestFuture.isDone()) {
@@ -173,9 +173,9 @@ public class ManualS7PlcDriverMT {
         ManualS7PlcDriverMT.this.printStatistics(statistics);
     }
 
-    private double runSingleRequest(PlcDriverManager plcDriverManager) {
+    private double runSingleRequest(PlcConnectionManager connectionManager) {
         long start = System.nanoTime();
-        try (PlcConnection connection = plcDriverManager.getConnection(CONN_STRING)) {
+        try (PlcConnection connection = connectionManager.getConnection(CONN_STRING)) {
             System.out.println("Connection: " + connection);
             CompletableFuture<? extends PlcReadResponse> future = connection.readRequestBuilder()
                 .addTagAddress("distance", TAG_STRING)
diff --git a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/ScraperTaskTest.java b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/ScraperTaskTest.java
index fcc0142f2a..aebf65e16b 100644
--- a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/ScraperTaskTest.java
+++ b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/ScraperTaskTest.java
@@ -18,7 +18,8 @@
  */
 package org.apache.plc4x.java.scraper;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.spi.values.PlcSTRING;
@@ -50,7 +51,7 @@ public class ScraperTaskTest implements WithAssertions {
 
     @Test
     public void scrape() throws PlcConnectionException {
-        PlcDriverManager driverManager = new PlcDriverManager();
+        DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
         MockConnection connection = (MockConnection) driverManager.getConnection("mock:scraper");
         connection.setDevice(mockDevice);
         when(mockDevice.read(any())).thenReturn(new ResponseItem<>(PlcResponseCode.OK, new PlcSTRING("hallo")));
@@ -67,7 +68,7 @@ public class ScraperTaskTest implements WithAssertions {
         @Test
         public void badResponseCode_shouldHandleException() throws PlcConnectionException {
             // Given
-            PlcDriverManager driverManager = new PlcDriverManager();
+            DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
             MockConnection connection = (MockConnection) driverManager.getConnection("mock:scraper");
             connection.setDevice(mockDevice);
             when(mockDevice.read(any())).thenReturn(new ResponseItem<>(PlcResponseCode.NOT_FOUND, new PlcSTRING("hallo")));
@@ -80,14 +81,14 @@ public class ScraperTaskTest implements WithAssertions {
         }
 
         @Mock
-        PlcDriverManager driverManager;
+        PlcConnectionManager connectionManager;
 
         @Test
         public void handleConnectionException() throws PlcConnectionException {
             // Given
-            when(driverManager.getConnection(anyString())).thenThrow(new PlcConnectionException("stfu"));
+            when(connectionManager.getConnection(anyString())).thenThrow(new PlcConnectionException("stfu"));
 
-            ScraperTask scraperTask = new ScraperTaskImpl(driverManager, "job1", "m1", "mock:scraper", Collections.singletonMap("a", "b"),
+            ScraperTask scraperTask = new ScraperTaskImpl(connectionManager, "job1", "m1", "mock:scraper", Collections.singletonMap("a", "b"),
                 1_000, ForkJoinPool.commonPool(), (j,a,m) -> {});
 
             ScraperTask spy = spy(scraperTask);
@@ -98,9 +99,9 @@ public class ScraperTaskTest implements WithAssertions {
 
         @Test
         void runByScheduler_handledGracefully() throws PlcConnectionException {
-            when(driverManager.getConnection(anyString())).thenThrow(new PlcConnectionException("stfu"));
+            when(connectionManager.getConnection(anyString())).thenThrow(new PlcConnectionException("stfu"));
             ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
-            ScraperTask scraperTask = new ScraperTaskImpl(driverManager, "job1", "m1", "mock:scraper", Collections.singletonMap("a", "b"),
+            ScraperTask scraperTask = new ScraperTaskImpl(connectionManager, "job1", "m1", "mock:scraper", Collections.singletonMap("a", "b"),
                 1_000, ForkJoinPool.commonPool(), (j,a,m) -> {});
 
             Future<?> future = pool.scheduleAtFixedRate(scraperTask, 0, 10, TimeUnit.MILLISECONDS);
diff --git a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/ScraperTest.java b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/ScraperTest.java
index 394651a6cd..c329d8a95f 100644
--- a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/ScraperTest.java
+++ b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/ScraperTest.java
@@ -18,17 +18,15 @@
  */
 package org.apache.plc4x.java.scraper;
 
-import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
-import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.spi.values.PlcDINT;
 import org.apache.plc4x.java.mock.connection.MockConnection;
 import org.apache.plc4x.java.mock.connection.MockDevice;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
-import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.assertj.core.api.WithAssertions;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
@@ -61,19 +59,9 @@ class ScraperTest implements WithAssertions {
     @Test
     @Disabled
     void real_stuff() throws InterruptedException {
-        PlcDriverManager driverManager = new PooledPlcDriverManager(pooledPlcConnectionFactory -> {
-            GenericKeyedObjectPoolConfig<PlcConnection> config = new GenericKeyedObjectPoolConfig<>();
-            config.setJmxEnabled(true);
-            config.setMaxWaitMillis(-1);
-            config.setMaxTotal(3);
-            config.setMinIdlePerKey(0);
-            config.setBlockWhenExhausted(true);
-            config.setTestOnBorrow(true);
-            config.setTestOnReturn(true);
-            return new GenericKeyedObjectPool<>(pooledPlcConnectionFactory, config);
-        });
-
-        Scraper scraper = new ScraperImpl((j, a, m) -> {}, driverManager, Arrays.asList(
+        PlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder().build();
+
+        Scraper scraper = new ScraperImpl((j, a, m) -> {}, connectionManager, Arrays.asList(
             new ScrapeJobImpl("job1",
                 10,
                 Collections.singletonMap("tim", CONN_STRING_TIM),
@@ -91,7 +79,7 @@ class ScraperTest implements WithAssertions {
 
     @Test
     void scraper_schedulesJob() throws InterruptedException, PlcConnectionException {
-        PlcDriverManager driverManager = new PlcDriverManager();
+        DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
         MockConnection connection = (MockConnection) driverManager.getConnection("mock:m1");
         connection.setDevice(mockDevice);
 
@@ -119,7 +107,7 @@ class ScraperTest implements WithAssertions {
 
     @Test
     void stop_stopsAllJobs() {
-        PlcDriverManager driverManager = new PlcDriverManager();
+        DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
 
         Scraper scraper = new ScraperImpl((j, a, m) -> {}, driverManager, Collections.singletonList(
             new ScrapeJobImpl("job1",
@@ -142,7 +130,7 @@ class ScraperTest implements WithAssertions {
 
     @Test
     void restart_works() throws PlcConnectionException {
-        PlcDriverManager driverManager = new PlcDriverManager();
+        DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
         MockConnection connection = (MockConnection) driverManager.getConnection("mock:m1");
         connection.setDevice(mockDevice);
 
diff --git a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunner.java b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunner.java
index 6315574d36..fbaf20a060 100644
--- a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunner.java
+++ b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunner.java
@@ -18,16 +18,14 @@
  */
 package org.apache.plc4x.java.scraper;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.scraper.config.ScraperConfiguration;
 import org.apache.plc4x.java.scraper.config.triggeredscraper.ScraperConfigurationTriggeredImpl;
 import org.apache.plc4x.java.scraper.exception.ScraperException;
-
-
 import org.apache.plc4x.java.scraper.triggeredscraper.TriggeredScraperImpl;
 import org.apache.plc4x.java.scraper.triggeredscraper.triggerhandler.collector.TriggerCollector;
 import org.apache.plc4x.java.scraper.triggeredscraper.triggerhandler.collector.TriggerCollectorImpl;
-import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -44,8 +42,8 @@ public class TriggeredScraperRunner {
 
         ScraperConfiguration configuration = ScraperConfiguration.fromFile("plc4j/utils/scraper/src/test/resources/example_triggered_scraper.yml", ScraperConfigurationTriggeredImpl.class);
 
-        PlcDriverManager plcDriverManager = new PooledPlcDriverManager();
-        TriggerCollector triggerCollector = new TriggerCollectorImpl(plcDriverManager);
+        PlcConnectionManager connectionManager = CachedPlcConnectionManager.getBuilder().build();
+        TriggerCollector triggerCollector = new TriggerCollectorImpl(connectionManager);
         TriggeredScraperImpl scraper = new TriggeredScraperImpl(configuration, (j, a, m) -> LOGGER.info("Results from {}/{}: {}", j, a, m),triggerCollector);
 
         scraper.start();
diff --git a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunnerModbus.java b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunnerModbus.java
index 3eb3e9eb46..d6bb0f9854 100644
--- a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunnerModbus.java
+++ b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunnerModbus.java
@@ -18,13 +18,13 @@
  */
 package org.apache.plc4x.java.scraper;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnectionManager;
 import org.apache.plc4x.java.scraper.config.ScraperConfiguration;
 import org.apache.plc4x.java.scraper.config.triggeredscraper.ScraperConfigurationTriggeredImpl;
 import org.apache.plc4x.java.scraper.exception.ScraperException;
 import org.apache.plc4x.java.scraper.triggeredscraper.TriggeredScraperImpl;
 import org.apache.plc4x.java.scraper.triggeredscraper.triggerhandler.collector.TriggerCollectorImpl;
-import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager;
+import org.apache.plc4x.java.utils.cache.CachedPlcConnectionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -41,10 +41,10 @@ public class TriggeredScraperRunnerModbus {
      */
     public static void main(String[] args) throws IOException, ScraperException {
         ScraperConfiguration configuration = ScraperConfiguration.fromFile("plc4j/utils/scraper/src/test/resources/example_triggered_scraper_modbus.yml", ScraperConfigurationTriggeredImpl.class);
-        PlcDriverManager plcDriverManager = new PooledPlcDriverManager();
+        PlcConnectionManager plcConnectionManager = CachedPlcConnectionManager.getBuilder().build();
         TriggeredScraperImpl scraper = new TriggeredScraperImpl(
             configuration,
-            plcDriverManager,
+            plcConnectionManager,
             (j, a, m) -> {
             LOGGER.info("Results from {}/{}: {}", j, a, m);
             for(Map.Entry<String, Object> entry:m.entrySet()){
@@ -53,7 +53,7 @@ public class TriggeredScraperRunnerModbus {
                 }
             }
             },
-            new TriggerCollectorImpl(plcDriverManager));
+            new TriggerCollectorImpl(plcConnectionManager));
 
         scraper.start();
     }
diff --git a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImplTest.java b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImplTest.java
index 4c794123a3..e109009e82 100644
--- a/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImplTest.java
+++ b/plc4j/tools/scraper/src/test/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImplTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.scraper.triggeredscraper;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.mock.connection.MockConnection;
 import org.apache.plc4x.java.mock.connection.MockDevice;
@@ -44,13 +44,13 @@ import static org.mockito.Mockito.when;
 
 class TriggeredScraperImplTest {
 
-    private PlcDriverManager driverManager;
+    private DefaultPlcDriverManager driverManager;
     private MockDevice mockDevice1;
     private MockDevice mockDevice2;
 
     @BeforeEach
     public void setUp() throws Exception {
-        driverManager = new PlcDriverManager();
+        driverManager = new DefaultPlcDriverManager();
         MockConnection mock1Connection = ((MockConnection) driverManager.getConnection("mock:1"));
         MockConnection mock2Connection = ((MockConnection) driverManager.getConnection("mock:2"));
 
diff --git a/plc4j/tools/ui/src/main/java/org/apache/plc4x/java/ui/FxmlController.java b/plc4j/tools/ui/src/main/java/org/apache/plc4x/java/ui/FxmlController.java
index 4da3f36109..4b6c2db5f1 100644
--- a/plc4j/tools/ui/src/main/java/org/apache/plc4x/java/ui/FxmlController.java
+++ b/plc4j/tools/ui/src/main/java/org/apache/plc4x/java/ui/FxmlController.java
@@ -28,9 +28,9 @@ import javafx.scene.input.MouseEvent;
 import javafx.scene.paint.Paint;
 
 import javafx.util.StringConverter;
-import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.PlcDriver;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.messages.PlcDiscoveryItem;
 import org.apache.plc4x.java.api.messages.PlcDiscoveryResponse;
@@ -55,7 +55,7 @@ public class FxmlController {
     public TabPane connectionTabs;
 
     public FxmlController() {
-        driverManager = new PlcDriverManager();
+        driverManager = PlcDriverManager.getDefault();
     }
 
     @FXML
@@ -121,7 +121,7 @@ public class FxmlController {
                     if(mouseEvent.getButton().equals(MouseButton.PRIMARY) && mouseEvent.getClickCount() == 2) {
                         String connectionString = selectedItem.getCode();
                         try {
-                            PlcConnection connection = driverManager.getConnection(connectionString);
+                            PlcConnection connection = driverManager.getConnectionManager().getConnection(connectionString);
                             FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(getClass().getResource("connection-tab.fxml")));
 
                             Tab connectionTab = loader.load();
diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/ConnectionManager.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/ConnectionManager.java
index 1bb5fcd4e2..00481eced3 100644
--- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/ConnectionManager.java
+++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/ConnectionManager.java
@@ -20,8 +20,9 @@ package org.apache.plc4x.test.driver.internal;
 
 import io.netty.channel.Channel;
 import io.netty.channel.embedded.Plc4xEmbeddedChannel;
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.PlcDriverManager;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.spi.connection.ChannelExposingConnection;
@@ -34,7 +35,7 @@ public class ConnectionManager {
     PlcDriverManager plcDriverManager;
 
     public ConnectionManager() {
-        this.plcDriverManager = new PlcDriverManager();
+        this.plcDriverManager = new DefaultPlcDriverManager();
     }
 
     public PlcConnection getConnection(String driverName, Map<String, String> driverParameters) throws DriverTestsuiteException {
@@ -48,7 +49,7 @@ public class ConnectionManager {
             if (sb.length() > 0) {
                 sb.replace(0, 1, "?");
             }
-            return plcDriverManager.getConnection(driverName + ":test://hurz" + sb);
+            return plcDriverManager.getConnectionManager().getConnection(driverName + ":test://hurz" + sb);
         } catch (PlcConnectionException e) {
             throw new DriverTestsuiteException("Error loading driver", e);
         }
diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java
index ea2ccef4e4..85cfd2f849 100644
--- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java
+++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.test.manual;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
@@ -56,7 +56,7 @@ public abstract class ManualTest {
     }
 
     public void run() throws Exception {
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection(connectionString)) {
+        try (PlcConnection plcConnection = new DefaultPlcDriverManager().getConnection(connectionString)) {
             System.out.println("Reading all types in separate requests");
             // Run all entries separately:
             for (TestCase testCase : testCases) {
diff --git a/pom.xml b/pom.xml
index 9fd43158bb..e0011f8bf9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1126,11 +1126,17 @@
             <release>${java.version}</release>
           </configuration>
           <dependencies>
+            <dependency>
+              <groupId>org.codehaus.plexus</groupId>
+              <artifactId>plexus-compiler-api</artifactId>
+              <version>2.13.0</version>
+            </dependency>
             <dependency>
               <groupId>org.codehaus.plexus</groupId>
               <artifactId>plexus-compiler-eclipse</artifactId>
-              <version>2.12.1</version>
+              <version>2.13.0</version>
             </dependency>
+            <!-- Redundant import, however we might need to bump this version more often -->
             <dependency>
               <groupId>org.eclipse.jdt</groupId>
               <artifactId>ecj</artifactId>
diff --git a/protocols/ads/src/main/resources/protocols/ads/ads.mspec b/protocols/ads/src/main/resources/protocols/ads/ads.mspec
index ffead9cd7d..5ee6f8d9ea 100644
--- a/protocols/ads/src/main/resources/protocols/ads/ads.mspec
+++ b/protocols/ads/src/main/resources/protocols/ads/ads.mspec
@@ -146,12 +146,13 @@
     // 4 bytes	Free usable 32 bit array. Usually this array serves to send an Id. This Id makes is possible to assign a received response to a request, which was sent before.
     [simple        uint        32  invokeId                                  ]
     // The payload
-    [typeSwitch commandId, response
-        ['INVALID', 'false' AdsInvalidRequest]
-        ['INVALID', 'true' AdsInvalidResponse]
+    // TODO: In case of an error code that is not 0, we might not have a payload at all
+    [typeSwitch errorCode, commandId, response
+        ['0x00000000', 'INVALID', 'false' AdsInvalidRequest]
+        ['0x00000000', 'INVALID', 'true' AdsInvalidResponse]
 
-        ['ADS_READ_DEVICE_INFO', 'false' AdsReadDeviceInfoRequest]
-        ['ADS_READ_DEVICE_INFO', 'true' AdsReadDeviceInfoResponse
+        ['0x00000000', 'ADS_READ_DEVICE_INFO', 'false' AdsReadDeviceInfoRequest]
+        ['0x00000000', 'ADS_READ_DEVICE_INFO', 'true' AdsReadDeviceInfoResponse
             // 4 bytes	ADS error number.
             [simple ReturnCode result]
             // Version	1 byte	Major version number
@@ -164,7 +165,7 @@
             [array byte  device count '16']
         ]
 
-        ['ADS_READ', 'false' AdsReadRequest
+        ['0x00000000', 'ADS_READ', 'false' AdsReadRequest
             // 4 bytes	Index Group of the data which should be read.
             [simple uint 32 indexGroup]
             // 4 bytes	Index Offset of the data which should be read.
@@ -172,7 +173,7 @@
             // 4 bytes	Length of the data (in bytes) which should be read.
             [simple uint 32 length]
         ]
-        ['ADS_READ', 'true' AdsReadResponse
+        ['0x00000000', 'ADS_READ', 'true' AdsReadResponse
             // 4 bytes	ADS error number
             [simple ReturnCode result]
             // 4 bytes	Length of data which are supplied back.
@@ -181,7 +182,7 @@
             [array byte data count 'length']
         ]
 
-        ['ADS_WRITE', 'false' AdsWriteRequest
+        ['0x00000000', 'ADS_WRITE', 'false' AdsWriteRequest
             // 4 bytes	Index Group of the data which should be written.
             [simple uint 32 indexGroup]
             // 4 bytes	Index Offset of the data which should be written.
@@ -191,13 +192,13 @@
             // n bytes	Data which are written in the ADS device.
             [array byte data count 'length']
         ]
-        ['ADS_WRITE', 'true' AdsWriteResponse
+        ['0x00000000', 'ADS_WRITE', 'true' AdsWriteResponse
             // 4 bytes	ADS error number
             [simple ReturnCode result]
         ]
 
-        ['ADS_READ_STATE', 'false' AdsReadStateRequest]
-        ['ADS_READ_STATE', 'true' AdsReadStateResponse
+        ['0x00000000', 'ADS_READ_STATE', 'false' AdsReadStateRequest]
+        ['0x00000000', 'ADS_READ_STATE', 'true' AdsReadStateResponse
             // 4 bytes	ADS error number
             [simple ReturnCode result]
             // 2 bytes	New ADS status (see data type ADSSTATE of the ADS-DLL).
@@ -206,7 +207,7 @@
             [simple uint 16 deviceState]
         ]
 
-        ['ADS_WRITE_CONTROL', 'false' AdsWriteControlRequest
+        ['0x00000000', 'ADS_WRITE_CONTROL', 'false' AdsWriteControlRequest
             // 2 bytes	New ADS status (see data type ADSSTATE of the ADS-DLL).
             [simple uint 16 adsState]
             // 2 bytes	New device status.
@@ -216,12 +217,12 @@
             // n bytes	Additional data which are sent to the ADS device
             [array byte data count 'length']
         ]
-        ['ADS_WRITE_CONTROL', 'true' AdsWriteControlResponse
+        ['0x00000000', 'ADS_WRITE_CONTROL', 'true' AdsWriteControlResponse
             // 4 bytes	ADS error number
             [simple ReturnCode result]
         ]
 
-        ['ADS_ADD_DEVICE_NOTIFICATION', 'false' AdsAddDeviceNotificationRequest
+        ['0x00000000', 'ADS_ADD_DEVICE_NOTIFICATION', 'false' AdsAddDeviceNotificationRequest
             // 4 bytes	Index Group of the data, which should be sent per notification.
             [simple     uint 32      indexGroup      ]
             // 4 bytes	Index Offset of the data, which should be sent per notification.
@@ -239,23 +240,23 @@
             [reserved   uint 64      '0x0000'        ]
             [reserved   uint 64      '0x0000'        ]
         ]
-        ['ADS_ADD_DEVICE_NOTIFICATION', 'true' AdsAddDeviceNotificationResponse
+        ['0x00000000', 'ADS_ADD_DEVICE_NOTIFICATION', 'true' AdsAddDeviceNotificationResponse
             // 4 bytes	ADS error number
             [simple ReturnCode result]
             // 4 bytes	Handle of notification
             [simple uint 32 notificationHandle]
         ]
 
-        ['ADS_DELETE_DEVICE_NOTIFICATION', 'false' AdsDeleteDeviceNotificationRequest
+        ['0x00000000', 'ADS_DELETE_DEVICE_NOTIFICATION', 'false' AdsDeleteDeviceNotificationRequest
             // 4 bytes	Handle of notification
             [simple uint 32 notificationHandle]
         ]
-        ['ADS_DELETE_DEVICE_NOTIFICATION', 'true' AdsDeleteDeviceNotificationResponse
+        ['0x00000000', 'ADS_DELETE_DEVICE_NOTIFICATION', 'true' AdsDeleteDeviceNotificationResponse
             // 4 bytes	ADS error number
             [simple ReturnCode result]
         ]
 
-        ['ADS_DEVICE_NOTIFICATION', 'false' AdsDeviceNotificationRequest
+        ['0x00000000', 'ADS_DEVICE_NOTIFICATION', 'false' AdsDeviceNotificationRequest
             // 4 bytes	Size of data in byte.
             [simple uint 32 length]
             // 4 bytes	Number of elements of type AdsStampHeader.
@@ -263,9 +264,9 @@
             // n bytes	Array with elements of type AdsStampHeader.
             [array AdsStampHeader adsStampHeaders count 'stamps']
         ]
-        ['ADS_DEVICE_NOTIFICATION', 'true' AdsDeviceNotificationResponse]
+        ['0x00000000', 'ADS_DEVICE_NOTIFICATION', 'true' AdsDeviceNotificationResponse]
 
-        ['ADS_READ_WRITE', 'false' AdsReadWriteRequest
+        ['0x00000000', 'ADS_READ_WRITE', 'false' AdsReadWriteRequest
             // 4 bytes	Index Group of the data which should be written.
             [simple uint 32 indexGroup]
             // 4 bytes	Index Offset of the data which should be written.
@@ -279,7 +280,7 @@
             // n bytes	Data which are written in the ADS device.
             [array byte data count 'writeLength - (COUNT(items) * 12)']
         ]
-        ['ADS_READ_WRITE', 'true' AdsReadWriteResponse
+        ['0x00000000', 'ADS_READ_WRITE', 'true' AdsReadWriteResponse
             // 4 bytes	ADS error number
             [simple ReturnCode result]
             // 4 bytes	Length of data in byte.
@@ -287,6 +288,8 @@
             // n bytes Additional data which are sent to the ADS device
             [array byte data count 'length']
         ]
+        [ErrorResponse
+        ]
     ]
 ]
 
@@ -631,54 +634,59 @@
 // Especially interesting for the sum add/delete notification requests
 // https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_ads_intro/117463563.html&id=
 [enum uint 32 ReservedIndexGroups
-    ['0x0000F000' ADSIGRP_SYMTAB]
-    ['0x0000F001' ADSIGRP_SYMNAME]
-    ['0x0000F002' ADSIGRP_SYMVAL]
-    ['0x0000F003' ADSIGRP_SYM_HNDBYNAME]
-    ['0x0000F004' ADSIGRP_SYM_VALBYNAME]
-    ['0x0000F005' ADSIGRP_SYM_VALBYHND]
-    ['0x0000F006' ADSIGRP_SYM_RELEASEHND]
-    ['0x0000F007' ADSIGRP_SYM_INFOBYNAME]
-    ['0x0000F008' ADSIGRP_SYM_VERSION]
+    ['0x0000F000' ADSIGRP_SYMTAB                              ]
+    ['0x0000F001' ADSIGRP_SYMNAME                             ]
+    ['0x0000F002' ADSIGRP_SYMVAL                              ]
+    ['0x0000F003' ADSIGRP_SYM_HNDBYNAME                       ]
+    ['0x0000F004' ADSIGRP_SYM_VALBYNAME                       ]
+    ['0x0000F005' ADSIGRP_SYM_VALBYHND                        ]
+    ['0x0000F006' ADSIGRP_SYM_RELEASEHND                      ]
+    ['0x0000F007' ADSIGRP_SYM_INFOBYNAME                      ]
+    ['0x0000F008' ADSIGRP_SYM_VERSION                         ]
     // We can use this GID to read the type information of a given variable
     // in the operation mode in which we don't read the entire structures on
     // connection start.
-    ['0x0000F009' ADSIGRP_SYM_INFOBYNAMEEX]
-    ['0x0000F00A' ADSIGRP_SYM_DOWNLOAD]
+    ['0x0000F009' ADSIGRP_SYM_INFOBYNAMEEX                    ]
+    ['0x0000F00A' ADSIGRP_SYM_DOWNLOAD                        ]
     // Read the symbol-table (All variables defined in the PLC)
-    ['0x0000F00B' ADSIGRP_SYM_UPLOAD]
-    ['0x0000F00C' ADSIGRP_SYM_UPLOADINFO]
+    ['0x0000F00B' ADSIGRP_SYM_UPLOAD                          ]
+    ['0x0000F00C' ADSIGRP_SYM_UPLOADINFO                      ]
     // Read the data-type-table (All data-types defined in the PLC)
-    ['0x0000F00E' ADSIGRP_DATA_TYPE_TABLE_UPLOAD]
+    ['0x0000F00E' ADSIGRP_DATA_TYPE_TABLE_UPLOAD              ]
     // Read the sizes of the symbol and data-type-tables
-    ['0x0000F00F' ADSIGRP_SYMBOL_AND_DATA_TYPE_SIZES]
-    ['0x0000F010' ADSIGRP_SYMNOTE]
+    ['0x0000F00F' ADSIGRP_SYMBOL_AND_DATA_TYPE_SIZES          ]
+    ['0x0000F010' ADSIGRP_SYMNOTE                             ]
     // We can use this GIT to read the data-type information for a given
     // data type name in the operation mode in which we don't read the
     // entire structures on connection start.
-    ['0x0000F011' ADSIGRP_DT_INFOBYNAMEEX]
+    ['0x0000F011' ADSIGRP_DT_INFOBYNAMEEX                     ]
     // Access to the %I fields
-    ['0x0000F020' ADSIGRP_IOIMAGE_RWIB]
-    ['0x0000F021' ADSIGRP_IOIMAGE_RWIX]
-    ['0x0000F025' ADSIGRP_IOIMAGE_RISIZE]
+    ['0x0000F020' ADSIGRP_IOIMAGE_RWIB                        ]
+    ['0x0000F021' ADSIGRP_IOIMAGE_RWIX                        ]
+    ['0x0000F025' ADSIGRP_IOIMAGE_RISIZE                      ]
     // Access to the %Q fields
-    ['0x0000F030' ADSIGRP_IOIMAGE_RWOB]
-    ['0x0000F031' ADSIGRP_IOIMAGE_RWOX]
-    ['0x0000F035' ADSIGRP_IOIMAGE_RWOSIZE]
-    ['0x0000F040' ADSIGRP_IOIMAGE_CLEARI]
-    ['0x0000F050' ADSIGRP_IOIMAGE_CLEARO]
-    ['0x0000F060' ADSIGRP_IOIMAGE_RWIOB]
+    ['0x0000F030' ADSIGRP_IOIMAGE_RWOB                        ]
+    ['0x0000F031' ADSIGRP_IOIMAGE_RWOX                        ]
+    ['0x0000F035' ADSIGRP_IOIMAGE_RWOSIZE                     ]
+    ['0x0000F040' ADSIGRP_IOIMAGE_CLEARI                      ]
+    ['0x0000F050' ADSIGRP_IOIMAGE_CLEARO                      ]
+    ['0x0000F060' ADSIGRP_IOIMAGE_RWIOB                       ]
     // Sum Requests
-    ['0x0000F080' ADSIGRP_MULTIPLE_READ]
-    ['0x0000F081' ADSIGRP_MULTIPLE_WRITE]
-    ['0x0000F082' ADSIGRP_MULTIPLE_READ_WRITE]
-    ['0x0000F083' ADSIGRP_MULTIPLE_RELEASE_HANDLE]
-    ['0x0000F084' ADSIGRP_SUMUP_READEX2]
-    ['0x0000F085' ADSIGRP_MULTIPLE_ADD_DEVICE_NOTIFICATIONS]
+    ['0x0000F080' ADSIGRP_MULTIPLE_READ                       ]
+    ['0x0000F081' ADSIGRP_MULTIPLE_WRITE                      ]
+    ['0x0000F082' ADSIGRP_MULTIPLE_READ_WRITE                 ]
+    ['0x0000F083' ADSIGRP_MULTIPLE_RELEASE_HANDLE             ]
+    ['0x0000F084' ADSIGRP_SUMUP_READEX2                       ]
+    ['0x0000F085' ADSIGRP_MULTIPLE_ADD_DEVICE_NOTIFICATIONS   ]
     ['0x0000F086' ADSIGRP_MULTIPLE_DELETE_DEVICE_NOTIFICATIONS]
-    ['0x0000F100' ADSIGRP_DEVICE_DATA]
-    ['0x00000000' ADSIOFFS_DEVDATA_ADSSTATE]
-    ['0x00000002' ADSIOFFS_DEVDATA_DEVSTATE]
+    ['0x0000F100' ADSIGRP_DEVICE_DATA                         ]
+    // This Group Index makes ADS access data via AoE (ADS over EtherCAT) and
+    // can be used to access telemetry data on the DeviceManager or from attached
+    // EtherCAT devices.
+    // https://infosys.beckhoff.com/index.php?content=../content/1031/eap/1521731467.html
+    ['0x0000F302' ADS_OVER_ETHERCAT                           ]
+    ['0x00000000' ADSIOFFS_DEVDATA_ADSSTATE                   ]
+    ['0x00000002' ADSIOFFS_DEVDATA_DEVSTATE                   ]
 ]
 
 [enum uint 32 ReturnCode
diff --git a/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/EndToEndTest.java b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/EndToEndTest.java
index 523d32e36e..0717772c5b 100644
--- a/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/EndToEndTest.java
+++ b/sandbox/test-java-df1-driver/src/test/java/org/apache/plc4x/protocol/df1/EndToEndTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.protocol.df1;
 
-import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
@@ -32,7 +32,7 @@ public class EndToEndTest {
     @Test
     @Disabled("Seems to cause problems on Windows if no COM4 is available")
     public void helloDf1() {
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection("df1:serial:///COM4")) {
+        try (PlcConnection plcConnection = new DefaultPlcDriverManager().getConnection("df1:serial:///COM4")) {
             PlcReadRequest request = plcConnection.readRequestBuilder()
                 .addTagAddress("hurz", "5:INTEGER")
                 .build();