diff --git a/README.md b/README.md
index 4618d067e..f7754be89 100644
--- a/README.md
+++ b/README.md
@@ -102,7 +102,7 @@ If you use Gradle, just include the following inside your `build.gradle` file.
 
 ```groovy
 dependencies {
-    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client', version: '1.2.1'
+    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client2', version: '2.0.0'
 }
 ```
 
@@ -110,10 +110,10 @@ For optional features you can choose to include additional modules:
 
 ```groovy
 dependencies {
-    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client-websocket', version: '1.2.1'
-    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client-proxy', version: '1.2.1'
-    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client-epoll', version: '1.2.1'
-    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client-reactor', version: '1.2.1'
+    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client2-websocket', version: '2.0.0'
+    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client2-proxy', version: '2.0.0'
+    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client2-epoll', version: '2.0.0'
+    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client2-reactor', version: '2.0.0'
 }
 ```
 
@@ -127,8 +127,8 @@ If you use Maven, just include the following inside your `pom.xml` file.
     <dependencies>
         <dependency>
             <groupId>com.hivemq</groupId>
-            <artifactId>hivemq-mqtt-client</artifactId>
-            <version>1.2.1</version>
+            <artifactId>hivemq-mqtt-client2</artifactId>
+            <version>2.0.0</version>
         </dependency>
     </dependencies>
     ...
@@ -156,32 +156,32 @@ For optional features you can choose to include additional modules:
     <dependencies>
         <dependency>
             <groupId>com.hivemq</groupId>
-            <artifactId>hivemq-mqtt-client-websocket</artifactId>
-            <version>1.2.1</version>
+            <artifactId>hivemq-mqtt-client2-websocket</artifactId>
+            <version>2.0.0</version>
             <type>pom</type>
         </dependency>
     </dependencies>
     <dependencies>
         <dependency>
             <groupId>com.hivemq</groupId>
-            <artifactId>hivemq-mqtt-client-proxy</artifactId>
-            <version>1.2.1</version>
+            <artifactId>hivemq-mqtt-client2-proxy</artifactId>
+            <version>2.0.0</version>
             <type>pom</type>
         </dependency>
     </dependencies>
     <dependencies>
         <dependency>
             <groupId>com.hivemq</groupId>
-            <artifactId>hivemq-mqtt-client-epoll</artifactId>
-            <version>1.2.1</version>
+            <artifactId>hivemq-mqtt-client2-epoll</artifactId>
+            <version>2.0.0</version>
             <type>pom</type>
         </dependency>
     </dependencies>
     <dependencies>
         <dependency>
             <groupId>com.hivemq</groupId>
-            <artifactId>hivemq-mqtt-client-reactor</artifactId>
-            <version>1.2.1</version>
+            <artifactId>hivemq-mqtt-client2-reactor</artifactId>
+            <version>2.0.0</version>
         </dependency>
     </dependencies>
     ...
@@ -199,7 +199,7 @@ To use the shaded version just append `-shaded` to the artifact name.
 
 ```groovy
 dependencies {
-    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client-shaded', version: '1.2.1'
+    implementation group: 'com.hivemq', name: 'hivemq-mqtt-client2-shaded', version: '2.0.0'
 }
 ```
 
@@ -211,8 +211,8 @@ dependencies {
     <dependencies>
         <dependency>
             <groupId>com.hivemq</groupId>
-            <artifactId>hivemq-mqtt-client-shaded</artifactId>
-            <version>1.2.1</version>
+            <artifactId>hivemq-mqtt-client2-shaded</artifactId>
+            <version>2.0.0</version>
         </dependency>
     </dependencies>
     ...
@@ -232,13 +232,13 @@ repositories {
 }
 
 dependencies {
-    implementation 'com.github.hivemq.hivemq-mqtt-client:hivemq-mqtt-client:develop-SNAPSHOT'
+    implementation 'com.github.hivemq.hivemq-mqtt-client:hivemq-mqtt-client2:develop-SNAPSHOT'
     
     // snapshots for optional modules
-    implementation 'com.github.hivemq.hivemq-mqtt-client:hivemq-mqtt-client-websocket:develop-SNAPSHOT'
-    implementation 'com.github.hivemq.hivemq-mqtt-client:hivemq-mqtt-client-proxy:develop-SNAPSHOT'
-    implementation 'com.github.hivemq.hivemq-mqtt-client:hivemq-mqtt-client-epoll:develop-SNAPSHOT'
-    implementation 'com.github.hivemq.hivemq-mqtt-client:hivemq-mqtt-client-reactor:develop-SNAPSHOT'
+    implementation 'com.github.hivemq.hivemq-mqtt-client:hivemq-mqtt-client2-websocket:develop-SNAPSHOT'
+    implementation 'com.github.hivemq.hivemq-mqtt-client:hivemq-mqtt-client2-proxy:develop-SNAPSHOT'
+    implementation 'com.github.hivemq.hivemq-mqtt-client:hivemq-mqtt-client2-epoll:develop-SNAPSHOT'
+    implementation 'com.github.hivemq.hivemq-mqtt-client:hivemq-mqtt-client2-reactor:develop-SNAPSHOT'
 }
 ```
 
@@ -257,7 +257,7 @@ dependencies {
     <dependencies>
         <dependency>
             <groupId>com.github.hivemq.hivemq-mqtt-client</groupId>
-            <artifactId>hivemq-mqtt-client</artifactId>
+            <artifactId>hivemq-mqtt-client2</artifactId>
             <version>develop-SNAPSHOT</version>
         </dependency>
     </dependencies>
@@ -266,7 +266,7 @@ dependencies {
     <dependencies>
         <dependency>
             <groupId>com.github.hivemq.hivemq-mqtt-client</groupId>
-            <artifactId>hivemq-mqtt-client-websocket</artifactId>
+            <artifactId>hivemq-mqtt-client2-websocket</artifactId>
             <version>develop-SNAPSHOT</version>
             <type>pom</type>
         </dependency>
@@ -274,7 +274,7 @@ dependencies {
     <dependencies>
         <dependency>
             <groupId>com.github.hivemq.hivemq-mqtt-client</groupId>
-            <artifactId>hivemq-mqtt-client-proxy</artifactId>
+            <artifactId>hivemq-mqtt-client2-proxy</artifactId>
             <version>develop-SNAPSHOT</version>
             <type>pom</type>
         </dependency>
@@ -282,7 +282,7 @@ dependencies {
     <dependencies>
         <dependency>
             <groupId>com.github.hivemq.hivemq-mqtt-client</groupId>
-            <artifactId>hivemq-mqtt-client-epoll</artifactId>
+            <artifactId>hivemq-mqtt-client2-epoll</artifactId>
             <version>develop-SNAPSHOT</version>
             <type>pom</type>
         </dependency>
@@ -290,7 +290,7 @@ dependencies {
     <dependencies>
         <dependency>
             <groupId>com.github.hivemq.hivemq-mqtt-client</groupId>
-            <artifactId>hivemq-mqtt-client-reactor</artifactId>
+            <artifactId>hivemq-mqtt-client2-reactor</artifactId>
             <version>develop-SNAPSHOT</version>
         </dependency>
     </dependencies>
@@ -298,7 +298,7 @@ dependencies {
 </project>
 ```
 
-Change the artifact name to `hivemq-mqtt-client-shaded` to get snapshots of the shaded version.
+Change the artifact name to `hivemq-mqtt-client2-shaded` to get snapshots of the shaded version.
 
 JitPack works for all branches and also specific commits.
 Just specify `<branch>-SNAPSHOT` or the first 10 digits of the commit id in the version.
@@ -735,7 +735,7 @@ API but return `Completable`.
 
 [Semantic Versioning](https://semver.org/) is used.
 
-All code inside `com.hivemq.client.internal` packages must not be used directly. It can change at any time and is not
+All code inside `com.hivemq.client2.internal` packages must not be used directly. It can change at any time and is not
 part of the public API.
 
 Interfaces annotated with `DoNotImplement` must not be implemented. The implementation is provided by the library.
diff --git a/build.gradle.kts b/build.gradle.kts
index c30034384..17b3968d5 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -25,7 +25,7 @@ allprojects {
     plugins.apply("com.github.sgtsilvio.gradle.metadata")
 
     metadata {
-        moduleName.set("com.hivemq.client.mqtt")
+        moduleName.set("com.hivemq.client2.mqtt")
         readableName.set("HiveMQ MQTT Client")
         organization {
             name.set("HiveMQ and the HiveMQ Community")
@@ -74,7 +74,7 @@ allprojects {
 }
 
 dependencies {
-    api("io.reactivex.rxjava2:rxjava:${property("rxjava.version")}")
+    api("io.reactivex.rxjava3:rxjava:${property("rxjava.version")}")
     api("org.reactivestreams:reactive-streams:${property("reactive-streams.version")}")
 
     implementation("io.netty:netty-buffer:${property("netty.version")}")
@@ -166,10 +166,10 @@ allprojects {
 tasks.jar {
     withConvention(aQute.bnd.gradle.BundleTaskConvention::class) {
         bnd("Export-Package: " +
-                "com.hivemq.client.annotations.*," +
-                "com.hivemq.client.mqtt.*," +
-                "com.hivemq.client.rx.*," +
-                "com.hivemq.client.util.*")
+                "com.hivemq.client2.annotations.*," +
+                "com.hivemq.client2.mqtt.*," +
+                "com.hivemq.client2.rx.*," +
+                "com.hivemq.client2.util.*")
     }
 }
 
@@ -186,7 +186,7 @@ tasks.shadowJar {
         }
     })
 
-    val shadePrefix = "com.hivemq.client.internal.shaded."
+    val shadePrefix = "com.hivemq.client2.internal.shaded."
     val shadeFilePrefix = shadePrefix.replace(".", "_")
     relocate("io.netty", "${shadePrefix}io.netty")
     relocate("META-INF/native/libnetty", "META-INF/native/lib${shadeFilePrefix}netty")
diff --git a/epoll/build.gradle.kts b/epoll/build.gradle.kts
index a5e027963..69a9cb617 100644
--- a/epoll/build.gradle.kts
+++ b/epoll/build.gradle.kts
@@ -8,7 +8,7 @@ plugins {
 description = "Adds dependencies for the HiveMQ MQTT Client epoll module"
 
 metadata {
-    moduleName.set("com.hivemq.client.mqtt.epoll")
+    moduleName.set("com.hivemq.client2.mqtt.epoll")
     readableName.set("HiveMQ MQTT Client epoll module")
 }
 
diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts
index 1805aa5e1..b51360ecf 100644
--- a/examples/build.gradle.kts
+++ b/examples/build.gradle.kts
@@ -8,7 +8,7 @@ plugins {
 description = "Examples using the HiveMQ MQTT Client"
 
 metadata {
-    moduleName.set("com.hivemq.client.mqtt.examples")
+    moduleName.set("com.hivemq.client2.mqtt.examples")
     readableName.set("HiveMQ MQTT Client examples")
 }
 
diff --git a/examples/src/main/java/com/hivemq/client/mqtt/examples/AsyncDemo.java b/examples/src/main/java/com/hivemq/client2/mqtt/examples/AsyncDemo.java
similarity index 89%
rename from examples/src/main/java/com/hivemq/client/mqtt/examples/AsyncDemo.java
rename to examples/src/main/java/com/hivemq/client2/mqtt/examples/AsyncDemo.java
index 10ce0ce1f..64c4dfb22 100644
--- a/examples/src/main/java/com/hivemq/client/mqtt/examples/AsyncDemo.java
+++ b/examples/src/main/java/com/hivemq/client2/mqtt/examples/AsyncDemo.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.examples;
+package com.hivemq.client2.mqtt.examples;
 
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5AsyncClient;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5Client;
 
 import java.util.concurrent.TimeUnit;
 
diff --git a/examples/src/main/java/com/hivemq/client/mqtt/examples/Mqtt5Features.java b/examples/src/main/java/com/hivemq/client2/mqtt/examples/Mqtt5Features.java
similarity index 84%
rename from examples/src/main/java/com/hivemq/client/mqtt/examples/Mqtt5Features.java
rename to examples/src/main/java/com/hivemq/client2/mqtt/examples/Mqtt5Features.java
index 4fbd65106..fda9698b3 100644
--- a/examples/src/main/java/com/hivemq/client/mqtt/examples/Mqtt5Features.java
+++ b/examples/src/main/java/com/hivemq/client2/mqtt/examples/Mqtt5Features.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.examples;
-
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
+package com.hivemq.client2.mqtt.examples;
+
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5AsyncClient;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5BlockingClient;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5Client;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
 
 import java.util.concurrent.CountDownLatch;
 
@@ -40,13 +40,13 @@ public static void main(final String[] args)throws InterruptedException {
 
         final Mqtt5AsyncClient client = Mqtt5Client.builder()
                 .serverHost("broker.hivemq.com")
-                .automaticReconnectWithDefaultConfig()
+                .automaticReconnect()
                 .buildAsync();
 
         final Mqtt5ConnAck connAck = client.toBlocking().connectWith()
                 .cleanStart(false)          // resume a previous session
                 .sessionExpiryInterval(30)  // keep session state for 30s
-                .restrictions()
+                .restrictionsWith()
                     .receiveMaximum(10)             // receive max. 10 concurrent messages
                     .sendMaximum(10)                // send max. 10 concurrent messages
                     .maximumPacketSize(10_240)      // receive messages with max size of 10KB
@@ -54,14 +54,14 @@ public static void main(final String[] args)throws InterruptedException {
                     .topicAliasMaximum(0)           // the server should not use topic aliases
                     .sendTopicAliasMaximum(8)       // use up to 8 aliases for the most used topics (automatically traced)
                     .applyRestrictions()
-                .willPublish()
+                .willPublishWith()
                     .topic("demo/topic/will")
                     .qos(MqttQos.EXACTLY_ONCE)
                     .payload("rip".getBytes())
                     .contentType("text/plain")  // our payload is text
                     .messageExpiryInterval(120) // not so important, expire message after 2min if can not be delivered
                     .delayInterval(30)          // delay sending out the will message so we can try to reconnect immediately
-                    .userProperties()           // add some user properties to the will message
+                    .userPropertiesWith()           // add some user properties to the will message
                         .add("sender", "demo-sender-1")
                         .add("receiver", "you")
                         .applyUserProperties()
@@ -89,7 +89,7 @@ public static void main(final String[] args)throws InterruptedException {
                 .retain(true)
                 .contentType("text/plain")  // our payload is text
                 .messageExpiryInterval(120) // not so important, expire message after 2min if can not be delivered
-                .userProperties()           // add some user properties to the message
+                .userPropertiesWith()           // add some user properties to the message
                     .add("sender", "demo-sender-1")
                     .add("receiver", "you")
                     .applyUserProperties()
@@ -108,7 +108,7 @@ public static void main(final String[] args)throws InterruptedException {
         client2.publishWith()
                 .topic("demo/topic/a")
                 .retain(true)
-                .userProperties()
+                .userPropertiesWith()
                     .add("sender", "demo-sender-2")
                     .add("receiver", "you")
                     .applyUserProperties()
diff --git a/examples/src/main/java/com/hivemq/client/mqtt/examples/ReconnectStrategy.java b/examples/src/main/java/com/hivemq/client2/mqtt/examples/ReconnectStrategy.java
similarity index 87%
rename from examples/src/main/java/com/hivemq/client/mqtt/examples/ReconnectStrategy.java
rename to examples/src/main/java/com/hivemq/client2/mqtt/examples/ReconnectStrategy.java
index dfd65fb26..257225dba 100644
--- a/examples/src/main/java/com/hivemq/client/mqtt/examples/ReconnectStrategy.java
+++ b/examples/src/main/java/com/hivemq/client2/mqtt/examples/ReconnectStrategy.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.examples;
+package com.hivemq.client2.mqtt.examples;
 
-import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
-import com.hivemq.client.mqtt.mqtt5.lifecycle.Mqtt5ClientDisconnectedContext;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5BlockingClient;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5Client;
+import com.hivemq.client2.mqtt.mqtt5.lifecycle.Mqtt5DisconnectedContext;
 
 import java.time.LocalTime;
 import java.util.concurrent.CompletableFuture;
@@ -42,7 +42,7 @@ public static void defaultReconnect() {
 
         final Mqtt5BlockingClient client1 = Mqtt5Client.builder()
                 .serverHost("broker.hivemq.com")
-                .automaticReconnectWithDefaultConfig() // exponential backoff, 1s initial, doubled up to 2min, random delays +-25%
+                .automaticReconnect() // exponential backoff, 1s initial, doubled up to 2min, random delays +-25%
                 .buildBlocking();
     }
 
@@ -50,7 +50,7 @@ public static void customizedReconnect() throws InterruptedException {
 
         final Mqtt5BlockingClient client2 = Mqtt5Client.builder()
                 .serverHost("broker.hivemq.com")
-                .automaticReconnect()
+                .automaticReconnectWith()
                     .initialDelay(3, TimeUnit.SECONDS)
                     .maxDelay(10, TimeUnit.SECONDS)
                     .applyAutomaticReconnect()
@@ -76,12 +76,12 @@ private static void completelyCustom() {
                 })
                 // multiple DisconnectedListener can form a reconnect strategy
                 .addDisconnectedListener(context -> {
-                    final Mqtt5ClientDisconnectedContext context5 = (Mqtt5ClientDisconnectedContext) context;
+                    final Mqtt5DisconnectedContext context5 = (Mqtt5DisconnectedContext) context;
                     context5.getReconnector()
                             .reconnectWhen(getOAuthToken(), (token, throwable) -> { // first reconnect would be delayed 2s but OAuth server needs more time
                                 if (token != null) {
                                     context5.getReconnector().connectWith()
-                                            .simpleAuth().password(token).applySimpleAuth() // set OAuth token as password
+                                            .simpleAuthWith().password(token).applySimpleAuth() // set OAuth token as password
                                             .applyConnect();
                                 } else {
                                     context5.getReconnector().reconnect(false); // cancel reconnect if OAuth query failed
diff --git a/examples/src/main/java/com/hivemq/client/mqtt/examples/RequestResponse.java b/examples/src/main/java/com/hivemq/client2/mqtt/examples/RequestResponse.java
similarity index 92%
rename from examples/src/main/java/com/hivemq/client/mqtt/examples/RequestResponse.java
rename to examples/src/main/java/com/hivemq/client2/mqtt/examples/RequestResponse.java
index 7982d68fd..0493d6d86 100644
--- a/examples/src/main/java/com/hivemq/client/mqtt/examples/RequestResponse.java
+++ b/examples/src/main/java/com/hivemq/client2/mqtt/examples/RequestResponse.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.examples;
+package com.hivemq.client2.mqtt.examples;
 
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5Client;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
 
 /**
  * Shows how to implement a request/response pattern using response topic and correlation data.
diff --git a/gradle.properties b/gradle.properties
index 2a702bfe9..ce35c3ac4 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,30 +1,29 @@
-version=1.2.1
-prevVersion=1.2.0
+version=2.0.0
+prevVersion=2.0.0
 #
 # main dependencies
 #
-rxjava.version=2.2.19
+rxjava.version=3.0.11
 reactive-streams.version=1.0.3
-netty.version=4.1.48.Final
-jctools.version=2.1.2
-annotations.version=16.0.3
-dagger.version=2.27
+netty.version=4.1.60.Final
+jctools.version=3.3.0
+annotations.version=20.1.0
+dagger.version=2.33
 slf4j.version=1.7.30
-reactor.version=3.3.4.RELEASE
-reactor-adapter.version=3.3.3.RELEASE
+reactor.version=3.4.2
 #
 # test dependencies
 #
-junit-jupiter.version=5.5.1
-equalsverifier.version=3.1.7
-mockito.version=2.18.3
-guava.version=24.1-jre
-bouncycastle.version=1.59
-paho.version=1.2.0
+junit-jupiter.version=5.7.1
+equalsverifier.version=3.5.5
+mockito.version=3.8.0
+guava.version=30.1-jre
+bouncycastle.version=1.68
+paho.version=1.2.5
 #
 # plugins
 #
-plugin.shadow.version=5.2.0
+plugin.shadow.version=6.1.0
 plugin.bnd.version=5.3.0
 plugin.license.version=0.15.0
 plugin.bintray.version=1.8.5
diff --git a/gradle/japicc.gradle.kts b/gradle/japicc.gradle.kts
index 0b22ce41d..9f60a4068 100644
--- a/gradle/japicc.gradle.kts
+++ b/gradle/japicc.gradle.kts
@@ -93,7 +93,7 @@ allprojects {
                             val className = interfaceDef.split(Regex("[ <{]"), limit = 2)[0]
                             classNames.add(className)
 
-                            val annotationIndex = content.indexOf("@DoNotImplement", index)
+                            val annotationIndex = content.indexOf("@ApiStatus.NonExtendable", index)
                             if (annotationIndex == -1) break
 
                             if (annotationIndex < start) {
@@ -189,7 +189,7 @@ allprojects {
                         val command = listOf(
                                 "perl", bin.resolve("japi-compliance-checker.pl").path,
                                 "-lib", artifactId,
-                                "-skip-internal-packages", "com.hivemq.client.internal",
+                                "-skip-internal-packages", "com.hivemq.client2.internal",
                                 "-non-impl", nonImplFile.path,
                                 "-check-annotations", "-s",
                                 prevJar.path, jar.path)
diff --git a/proxy/build.gradle.kts b/proxy/build.gradle.kts
index 320c1565f..a7f1a160f 100644
--- a/proxy/build.gradle.kts
+++ b/proxy/build.gradle.kts
@@ -8,7 +8,7 @@ plugins {
 description = "Adds dependencies for the HiveMQ MQTT Client proxy module"
 
 metadata {
-    moduleName.set("com.hivemq.client.mqtt.proxy")
+    moduleName.set("com.hivemq.client2.mqtt.proxy")
     readableName.set("HiveMQ MQTT Client proxy module")
 }
 
diff --git a/reactor/build.gradle.kts b/reactor/build.gradle.kts
index aa092cecb..dd4aef70a 100644
--- a/reactor/build.gradle.kts
+++ b/reactor/build.gradle.kts
@@ -8,7 +8,7 @@ plugins {
 description = "Reactor API for the HiveMQ MQTT Client"
 
 metadata {
-    moduleName.set("com.hivemq.client.mqtt.reactor")
+    moduleName.set("com.hivemq.client2.mqtt.reactor")
     readableName.set("HiveMQ MQTT Client reactor module")
 }
 
@@ -19,7 +19,7 @@ dependencies {
     api(rootProject)
     api("io.projectreactor:reactor-core:${property("reactor.version")}")
 
-    implementation("io.projectreactor.addons:reactor-adapter:${property("reactor-adapter.version")}")
+    implementation("io.projectreactor.addons:reactor-adapter:${property("reactor.version")}")
     implementation("org.jetbrains:annotations:${property("annotations.version")}")
 }
 
@@ -37,8 +37,8 @@ dependencies {
 tasks.jar {
     withConvention(aQute.bnd.gradle.BundleTaskConvention::class) {
         bnd("Export-Package: " +
-                "com.hivemq.client.mqtt.mqtt3.reactor," +
-                "com.hivemq.client.mqtt.mqtt5.reactor," +
-                "com.hivemq.client.rx.reactor")
+                "com.hivemq.client2.mqtt.mqtt3.reactor," +
+                "com.hivemq.client2.mqtt.mqtt5.reactor," +
+                "com.hivemq.client2.rx.reactor")
     }
 }
diff --git a/reactor/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/reactor/Mqtt3ReactorClientView.java b/reactor/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/reactor/Mqtt3ReactorClientView.java
similarity index 65%
rename from reactor/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/reactor/Mqtt3ReactorClientView.java
rename to reactor/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/reactor/Mqtt3ReactorClientView.java
index 5cfb253bd..6b829bd7d 100644
--- a/reactor/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/reactor/Mqtt3ReactorClientView.java
+++ b/reactor/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/reactor/Mqtt3ReactorClientView.java
@@ -14,30 +14,31 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.mqtt3.reactor;
-
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeViewBuilder;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeViewBuilder;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3BlockingClient;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientConfig;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3RxClient;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
-import com.hivemq.client.mqtt.mqtt3.reactor.Mqtt3ReactorClient;
-import com.hivemq.client.rx.reactor.FluxWithSingle;
-import io.reactivex.Flowable;
+package com.hivemq.client2.internal.mqtt.mqtt3.reactor;
+
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeViewBuilder;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3AsyncClient;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3BlockingClient;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientConfig;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3RxClient;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt3.reactor.Mqtt3ReactorClient;
+import com.hivemq.client2.rx.reactor.FluxWithSingle;
+import io.reactivex.rxjava3.core.Flowable;
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Publisher;
-import reactor.adapter.rxjava.RxJava2Adapter;
+import reactor.adapter.rxjava.RxJava3Adapter;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
@@ -59,7 +60,7 @@ public Mqtt3ReactorClientView(final @NotNull Mqtt3RxClient delegate) {
 
     @Override
     public @NotNull Mono<Mqtt3ConnAck> connect(final @NotNull Mqtt3Connect connect) {
-        return RxJava2Adapter.singleToMono(delegate.connect(connect));
+        return RxJava3Adapter.singleToMono(delegate.connect(connect));
     }
 
     @Override
@@ -69,7 +70,7 @@ public Mqtt3ReactorClientView(final @NotNull Mqtt3RxClient delegate) {
 
     @Override
     public @NotNull Mono<Mqtt3SubAck> subscribe(final @NotNull Mqtt3Subscribe subscribe) {
-        return RxJava2Adapter.singleToMono(delegate.subscribe(subscribe));
+        return RxJava3Adapter.singleToMono(delegate.subscribe(subscribe));
     }
 
     @Override
@@ -105,27 +106,27 @@ public Mqtt3ReactorClientView(final @NotNull Mqtt3RxClient delegate) {
     public @NotNull Flux<Mqtt3Publish> publishes(
             final @NotNull MqttGlobalPublishFilter filter, final boolean manualAcknowledgement) {
 
-        return RxJava2Adapter.flowableToFlux(delegate.publishes(filter, manualAcknowledgement));
+        return RxJava3Adapter.flowableToFlux(delegate.publishes(filter, manualAcknowledgement));
     }
 
     @Override
-    public @NotNull Mono<Void> unsubscribe(final @NotNull Mqtt3Unsubscribe unsubscribe) {
-        return RxJava2Adapter.completableToMono(delegate.unsubscribe(unsubscribe));
+    public @NotNull Mono<Mqtt3UnsubAck> unsubscribe(final @NotNull Mqtt3Unsubscribe unsubscribe) {
+        return RxJava3Adapter.singleToMono(delegate.unsubscribe(unsubscribe));
     }
 
     @Override
-    public @NotNull Mqtt3UnsubscribeViewBuilder.Nested<Mono<Void>> unsubscribeWith() {
+    public @NotNull Mqtt3UnsubscribeViewBuilder.Nested<Mono<Mqtt3UnsubAck>> unsubscribeWith() {
         return new Mqtt3UnsubscribeViewBuilder.Nested<>(this::unsubscribe);
     }
 
     @Override
     public @NotNull Flux<Mqtt3PublishResult> publish(final @NotNull Publisher<Mqtt3Publish> publisher) {
-        return RxJava2Adapter.flowableToFlux(delegate.publish(Flowable.fromPublisher(publisher)));
+        return RxJava3Adapter.flowableToFlux(delegate.publish(Flowable.fromPublisher(publisher)));
     }
 
     @Override
     public @NotNull Mono<Void> disconnect() {
-        return RxJava2Adapter.completableToMono(delegate.disconnect());
+        return RxJava3Adapter.completableToMono(delegate.disconnect());
     }
 
     @Override
diff --git a/reactor/src/main/java/com/hivemq/client/internal/mqtt/reactor/MqttReactorClient.java b/reactor/src/main/java/com/hivemq/client2/internal/mqtt/reactor/MqttReactorClient.java
similarity index 68%
rename from reactor/src/main/java/com/hivemq/client/internal/mqtt/reactor/MqttReactorClient.java
rename to reactor/src/main/java/com/hivemq/client2/internal/mqtt/reactor/MqttReactorClient.java
index 351ed3ebe..c9089b8a6 100644
--- a/reactor/src/main/java/com/hivemq/client/internal/mqtt/reactor/MqttReactorClient.java
+++ b/reactor/src/main/java/com/hivemq/client2/internal/mqtt/reactor/MqttReactorClient.java
@@ -14,34 +14,34 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.reactor;
-
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectBuilder;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribeBuilder;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribeBuilder;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5RxClient;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
-import com.hivemq.client.mqtt.mqtt5.reactor.Mqtt5ReactorClient;
-import com.hivemq.client.rx.reactor.FluxWithSingle;
-import io.reactivex.Flowable;
+package com.hivemq.client2.internal.mqtt.reactor;
+
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectBuilder;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribeBuilder;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribeBuilder;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5AsyncClient;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5BlockingClient;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5RxClient;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.reactor.Mqtt5ReactorClient;
+import com.hivemq.client2.rx.reactor.FluxWithSingle;
+import io.reactivex.rxjava3.core.Flowable;
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Publisher;
-import reactor.adapter.rxjava.RxJava2Adapter;
+import reactor.adapter.rxjava.RxJava3Adapter;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
@@ -63,7 +63,7 @@ public MqttReactorClient(final @NotNull Mqtt5RxClient delegate) {
 
     @Override
     public @NotNull Mono<Mqtt5ConnAck> connect(final @NotNull Mqtt5Connect connect) {
-        return RxJava2Adapter.singleToMono(delegate.connect(connect));
+        return RxJava3Adapter.singleToMono(delegate.connect(connect));
     }
 
     @Override
@@ -73,7 +73,7 @@ public MqttReactorClient(final @NotNull Mqtt5RxClient delegate) {
 
     @Override
     public @NotNull Mono<Mqtt5SubAck> subscribe(final @NotNull Mqtt5Subscribe subscribe) {
-        return RxJava2Adapter.singleToMono(delegate.subscribe(subscribe));
+        return RxJava3Adapter.singleToMono(delegate.subscribe(subscribe));
     }
 
     @Override
@@ -109,12 +109,12 @@ public MqttReactorClient(final @NotNull Mqtt5RxClient delegate) {
     public @NotNull Flux<Mqtt5Publish> publishes(
             final @NotNull MqttGlobalPublishFilter filter, final boolean manualAcknowledgement) {
 
-        return RxJava2Adapter.flowableToFlux(delegate.publishes(filter, manualAcknowledgement));
+        return RxJava3Adapter.flowableToFlux(delegate.publishes(filter, manualAcknowledgement));
     }
 
     @Override
     public @NotNull Mono<Mqtt5UnsubAck> unsubscribe(final @NotNull Mqtt5Unsubscribe unsubscribe) {
-        return RxJava2Adapter.singleToMono(delegate.unsubscribe(unsubscribe));
+        return RxJava3Adapter.singleToMono(delegate.unsubscribe(unsubscribe));
     }
 
     @Override
@@ -124,12 +124,12 @@ public MqttReactorClient(final @NotNull Mqtt5RxClient delegate) {
 
     @Override
     public @NotNull Flux<Mqtt5PublishResult> publish(final @NotNull Publisher<Mqtt5Publish> publisher) {
-        return RxJava2Adapter.flowableToFlux(delegate.publish(Flowable.fromPublisher(publisher)));
+        return RxJava3Adapter.flowableToFlux(delegate.publish(Flowable.fromPublisher(publisher)));
     }
 
     @Override
     public @NotNull Mono<Void> reauth() {
-        return RxJava2Adapter.completableToMono(delegate.reauth());
+        return RxJava3Adapter.completableToMono(delegate.reauth());
     }
 
     @Override
@@ -139,7 +139,7 @@ public MqttReactorClient(final @NotNull Mqtt5RxClient delegate) {
 
     @Override
     public @NotNull Mono<Void> disconnect(final @NotNull Mqtt5Disconnect disconnect) {
-        return RxJava2Adapter.completableToMono(delegate.disconnect(disconnect));
+        return RxJava3Adapter.completableToMono(delegate.disconnect(disconnect));
     }
 
     @Override
diff --git a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/CoreWithSingleConditionalSubscriber.java b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/CoreWithSingleConditionalSubscriber.java
similarity index 88%
rename from reactor/src/main/java/com/hivemq/client/internal/rx/reactor/CoreWithSingleConditionalSubscriber.java
rename to reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/CoreWithSingleConditionalSubscriber.java
index 11f16d2f0..91be44e2f 100644
--- a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/CoreWithSingleConditionalSubscriber.java
+++ b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/CoreWithSingleConditionalSubscriber.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.reactor;
+package com.hivemq.client2.internal.rx.reactor;
 
-import com.hivemq.client.rx.reactor.CoreWithSingleSubscriber;
+import com.hivemq.client2.rx.reactor.CoreWithSingleSubscriber;
 import reactor.core.Fuseable;
 
 /**
diff --git a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/CoreWithSingleStrictSubscriber.java b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/CoreWithSingleStrictSubscriber.java
similarity index 80%
rename from reactor/src/main/java/com/hivemq/client/internal/rx/reactor/CoreWithSingleStrictSubscriber.java
rename to reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/CoreWithSingleStrictSubscriber.java
index 334ea086f..9bcce5074 100644
--- a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/CoreWithSingleStrictSubscriber.java
+++ b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/CoreWithSingleStrictSubscriber.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.reactor;
+package com.hivemq.client2.internal.rx.reactor;
 
-import com.hivemq.client.internal.rx.WithSingleStrictSubscriber;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import com.hivemq.client.rx.reactor.CoreWithSingleSubscriber;
+import com.hivemq.client2.internal.rx.WithSingleStrictSubscriber;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import com.hivemq.client2.rx.reactor.CoreWithSingleSubscriber;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleCombine.java b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleCombine.java
similarity index 97%
rename from reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleCombine.java
rename to reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleCombine.java
index cbcfe4962..3f6ec1b93 100644
--- a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleCombine.java
+++ b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleCombine.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.reactor.operators;
+package com.hivemq.client2.internal.rx.reactor.operators;
 
-import com.hivemq.client.internal.rx.reactor.CoreWithSingleConditionalSubscriber;
-import com.hivemq.client.rx.reactor.CoreWithSingleSubscriber;
-import com.hivemq.client.rx.reactor.FluxWithSingle;
+import com.hivemq.client2.internal.rx.reactor.CoreWithSingleConditionalSubscriber;
+import com.hivemq.client2.rx.reactor.CoreWithSingleSubscriber;
+import com.hivemq.client2.rx.reactor.FluxWithSingle;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscription;
diff --git a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleFrom.java b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleFrom.java
similarity index 84%
rename from reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleFrom.java
rename to reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleFrom.java
index 172e5d413..dbb2a7454 100644
--- a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleFrom.java
+++ b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleFrom.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.reactor.operators;
+package com.hivemq.client2.internal.rx.reactor.operators;
 
-import com.hivemq.client.rx.reactivestreams.PublisherWithSingle;
-import com.hivemq.client.rx.reactor.CoreWithSingleSubscriber;
-import com.hivemq.client.rx.reactor.FluxWithSingle;
+import com.hivemq.client2.rx.reactivestreams.PublisherWithSingle;
+import com.hivemq.client2.rx.reactor.CoreWithSingleSubscriber;
+import com.hivemq.client2.rx.reactor.FluxWithSingle;
 import org.jetbrains.annotations.NotNull;
 import reactor.core.CoreSubscriber;
 
diff --git a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleMap.java b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleMap.java
similarity index 96%
rename from reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleMap.java
rename to reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleMap.java
index 897fa6569..7ff3e5d22 100644
--- a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleMap.java
+++ b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleMap.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.reactor.operators;
+package com.hivemq.client2.internal.rx.reactor.operators;
 
-import com.hivemq.client.internal.rx.reactor.CoreWithSingleConditionalSubscriber;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.rx.reactor.CoreWithSingleSubscriber;
-import com.hivemq.client.rx.reactor.FluxWithSingle;
+import com.hivemq.client2.internal.rx.reactor.CoreWithSingleConditionalSubscriber;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.rx.reactor.CoreWithSingleSubscriber;
+import com.hivemq.client2.rx.reactor.FluxWithSingle;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscription;
diff --git a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleOperator.java b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleOperator.java
similarity index 89%
rename from reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleOperator.java
rename to reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleOperator.java
index c62be9886..cffcf6b4c 100644
--- a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSingleOperator.java
+++ b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSingleOperator.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.reactor.operators;
+package com.hivemq.client2.internal.rx.reactor.operators;
 
-import com.hivemq.client.rx.reactor.FluxWithSingle;
+import com.hivemq.client2.rx.reactor.FluxWithSingle;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSinglePublishOn.java b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSinglePublishOn.java
similarity index 91%
rename from reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSinglePublishOn.java
rename to reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSinglePublishOn.java
index e4d45f2a6..9581ba1bf 100644
--- a/reactor/src/main/java/com/hivemq/client/internal/rx/reactor/operators/FluxWithSinglePublishOn.java
+++ b/reactor/src/main/java/com/hivemq/client2/internal/rx/reactor/operators/FluxWithSinglePublishOn.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.reactor.operators;
+package com.hivemq.client2.internal.rx.reactor.operators;
 
-import com.hivemq.client.rx.reactor.CoreWithSingleSubscriber;
-import com.hivemq.client.rx.reactor.FluxWithSingle;
+import com.hivemq.client2.rx.reactor.CoreWithSingleSubscriber;
+import com.hivemq.client2.rx.reactor.FluxWithSingle;
 import org.jetbrains.annotations.NotNull;
 import reactor.core.CoreSubscriber;
 import reactor.core.scheduler.Scheduler;
diff --git a/reactor/src/main/java/com/hivemq/client/mqtt/mqtt3/reactor/Mqtt3ReactorClient.java b/reactor/src/main/java/com/hivemq/client2/mqtt/mqtt3/reactor/Mqtt3ReactorClient.java
similarity index 87%
rename from reactor/src/main/java/com/hivemq/client/mqtt/mqtt3/reactor/Mqtt3ReactorClient.java
rename to reactor/src/main/java/com/hivemq/client2/mqtt/mqtt3/reactor/Mqtt3ReactorClient.java
index 9ec071eef..e26467802 100644
--- a/reactor/src/main/java/com/hivemq/client/mqtt/mqtt3/reactor/Mqtt3ReactorClient.java
+++ b/reactor/src/main/java/com/hivemq/client2/mqtt/mqtt3/reactor/Mqtt3ReactorClient.java
@@ -14,24 +14,25 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.reactor;
+package com.hivemq.client2.mqtt.mqtt3.reactor;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.mqtt3.reactor.Mqtt3ReactorClientView;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3Client;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubscribeBuilder;
-import com.hivemq.client.rx.reactor.FluxWithSingle;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.mqtt.mqtt3.reactor.Mqtt3ReactorClientView;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3Client;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubscribeBuilder;
+import com.hivemq.client2.rx.reactor.FluxWithSingle;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Publisher;
 import reactor.core.publisher.Flux;
@@ -43,7 +44,7 @@
  * @author Silvio Giebl
  * @since 1.2
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3ReactorClient extends Mqtt3Client {
 
     /**
@@ -82,7 +83,7 @@ public interface Mqtt3ReactorClient extends Mqtt3Client {
      * @return the {@link Mono} which
      *         <ul>
      *           <li>succeeds with the ConnAck message if it does not contain an Error Code (connected successfully),
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3ConnAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3ConnAckException
      *             Mqtt3ConnAckException} wrapping the ConnAck message if it contains an Error Code or
      *           <li>errors with a different exception if an error occurred before the Connect message was sent or
      *             before the ConnAck message was received.
@@ -119,7 +120,7 @@ public interface Mqtt3ReactorClient extends Mqtt3Client {
      *         <ul>
      *           <li>succeeds with the SubAck message if at least one subscription of the Subscribe message was
      *             successful (the SubAck message contains at least one Return Code that is not an Error Code),
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3SubAckException
      *             Mqtt3SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent or
      *             before a SubAck message was received.
@@ -157,11 +158,11 @@ public interface Mqtt3ReactorClient extends Mqtt3Client {
      *             Error Code) and then emits the Publish messages matching the successful subscriptions of the
      *             Subscribe message,
      *           <li>completes when all subscriptions of the Subscribe message were unsubscribed,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3SubAckException
      *             Mqtt3SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent,
      *             before a SubAck message was received or when a error occurs before all subscriptions of the Subscribe
-     *             message were unsubscribed (e.g. {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *             message were unsubscribed (e.g. {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException}).
      *         </ul>
      * @see #subscribePublishes(Mqtt3Subscribe, boolean)
@@ -186,11 +187,11 @@ public interface Mqtt3ReactorClient extends Mqtt3Client {
      *             Error Code) and then emits the Publish messages matching the successful subscriptions of the
      *             Subscribe message,
      *           <li>completes when all subscriptions of the Subscribe message were unsubscribed,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3SubAckException
      *             Mqtt3SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent,
      *             before a SubAck message was received or when a error occurs before all subscriptions of the Subscribe
-     *             message were unsubscribed (e.g. {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *             message were unsubscribed (e.g. {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException}).
      *         </ul>
      * @see #subscribePublishes(Mqtt3Subscribe)
@@ -224,7 +225,7 @@ public interface Mqtt3ReactorClient extends Mqtt3Client {
      *         <ul>
      *           <li>emits the incoming Publish messages matching the given filter,
      *           <li>never completes but
-     *           <li>errors with a {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException} when the MQTT session expires.
      *         </ul>
      * @see #publishes(MqttGlobalPublishFilter, boolean)
@@ -245,7 +246,7 @@ public interface Mqtt3ReactorClient extends Mqtt3Client {
      *         <ul>
      *           <li>emits the incoming Publish messages matching the given filter,
      *           <li>never completes but
-     *           <li>errors with a {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException} when the MQTT session expires.
      *         </ul>
      * @see #publishes(MqttGlobalPublishFilter)
@@ -263,13 +264,13 @@ public interface Mqtt3ReactorClient extends Mqtt3Client {
      * @param unsubscribe the Unsubscribe message sent to the broker during unsubscribe.
      * @return the {@link Mono} which
      *         <ul>
-     *           <li>succeeds when the corresponding UnsubAck message was received or
+     *           <li>succeeds with the UnsubAck message or
      *           <li>errors if an error occurred before the Unsubscribe message was sent or before a UnsubAck message
      *             was received.
      *         </ul>
      */
     @CheckReturnValue
-    @NotNull Mono<Void> unsubscribe(@NotNull Mqtt3Unsubscribe unsubscribe);
+    @NotNull Mono<Mqtt3UnsubAck> unsubscribe(@NotNull Mqtt3Unsubscribe unsubscribe);
 
     /**
      * Fluent counterpart of {@link #unsubscribe(Mqtt3Unsubscribe)}.
@@ -282,7 +283,7 @@ public interface Mqtt3ReactorClient extends Mqtt3Client {
      * @see #unsubscribe(Mqtt3Unsubscribe)
      */
     @CheckReturnValue
-    @NotNull Mqtt3UnsubscribeBuilder.Nested.Start<Mono<Void>> unsubscribeWith();
+    @NotNull Mqtt3UnsubscribeBuilder.Nested.Start<Mono<Mqtt3UnsubAck>> unsubscribeWith();
 
     /**
      * Creates a {@link Flux} for publishing the Publish messages emitted by the given {@link Publisher}.
diff --git a/reactor/src/main/java/com/hivemq/client/mqtt/mqtt5/reactor/Mqtt5ReactorClient.java b/reactor/src/main/java/com/hivemq/client2/mqtt/mqtt5/reactor/Mqtt5ReactorClient.java
similarity index 88%
rename from reactor/src/main/java/com/hivemq/client/mqtt/mqtt5/reactor/Mqtt5ReactorClient.java
rename to reactor/src/main/java/com/hivemq/client2/mqtt/mqtt5/reactor/Mqtt5ReactorClient.java
index 76c64eb4b..038e61fd2 100644
--- a/reactor/src/main/java/com/hivemq/client/mqtt/mqtt5/reactor/Mqtt5ReactorClient.java
+++ b/reactor/src/main/java/com/hivemq/client2/mqtt/mqtt5/reactor/Mqtt5ReactorClient.java
@@ -14,27 +14,27 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.reactor;
+package com.hivemq.client2.mqtt.mqtt5.reactor;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.reactor.MqttReactorClient;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
-import com.hivemq.client.rx.reactor.FluxWithSingle;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.mqtt.reactor.MqttReactorClient;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5Client;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder;
+import com.hivemq.client2.rx.reactor.FluxWithSingle;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Publisher;
 import reactor.core.publisher.Flux;
@@ -46,7 +46,7 @@
  * @author Silvio Giebl
  * @since 1.2
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ReactorClient extends Mqtt5Client {
 
     /**
@@ -85,7 +85,7 @@ public interface Mqtt5ReactorClient extends Mqtt5Client {
      * @return the {@link Mono} which
      *         <ul>
      *           <li>succeeds with the ConnAck message if it does not contain an Error Code (connected successfully),
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5ConnAckException
      *             Mqtt5ConnAckException} wrapping the ConnAck message if it contains an Error Code or
      *           <li>errors with a different exception if an error occurred before the Connect message was sent or
      *             before the ConnAck message was received.
@@ -122,7 +122,7 @@ public interface Mqtt5ReactorClient extends Mqtt5Client {
      *         <ul>
      *           <li>succeeds with the SubAck message if at least one subscription of the Subscribe message was
      *             successful (the SubAck message contains at least one Reason Code that is not an Error Code),
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5SubAckException
      *             Mqtt5SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent or
      *             before a SubAck message was received.
@@ -160,11 +160,11 @@ public interface Mqtt5ReactorClient extends Mqtt5Client {
      *             Error Code) and then emits the Publish messages matching the successful subscriptions of the
      *             Subscribe message,
      *           <li>completes when all subscriptions of the Subscribe message were unsubscribed,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5SubAckException
      *             Mqtt5SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent,
      *             before a SubAck message was received or when a error occurs before all subscriptions of the Subscribe
-     *             message were unsubscribed (e.g. {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *             message were unsubscribed (e.g. {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException}).
      *         </ul>
      * @see #subscribePublishes(Mqtt5Subscribe, boolean)
@@ -189,11 +189,11 @@ public interface Mqtt5ReactorClient extends Mqtt5Client {
      *             Error Code) and then emits the Publish messages matching the successful subscriptions of the
      *             Subscribe message,
      *           <li>completes when all subscriptions of the Subscribe message were unsubscribed,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5SubAckException
      *             Mqtt5SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent,
      *             before a SubAck message was received or when a error occurs before all subscriptions of the Subscribe
-     *             message were unsubscribed (e.g. {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *             message were unsubscribed (e.g. {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException}).
      *         </ul>
      * @see #subscribePublishes(Mqtt5Subscribe)
@@ -227,7 +227,7 @@ public interface Mqtt5ReactorClient extends Mqtt5Client {
      *         <ul>
      *           <li>emits the incoming Publish messages matching the given filter,
      *           <li>never completes but
-     *           <li>errors with a {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException} when the MQTT session expires.
      *         </ul>
      * @see #publishes(MqttGlobalPublishFilter, boolean)
@@ -248,7 +248,7 @@ public interface Mqtt5ReactorClient extends Mqtt5Client {
      *         <ul>
      *           <li>emits the incoming Publish messages matching the given filter,
      *           <li>never completes but
-     *           <li>errors with a {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException} when the MQTT session expires.
      *         </ul>
      * @see #publishes(MqttGlobalPublishFilter)
@@ -269,7 +269,7 @@ public interface Mqtt5ReactorClient extends Mqtt5Client {
      *           <li>succeeds with the UnsubAck message if at least one Topic Filter of the Unsubscribe message was
      *             successfully unsubscribed (the UnsubAck message contains at least one Reason Code that is not an
      *             Error Code),
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException
      *             Mqtt5UnsubAckException} wrapping the UnsubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Unsubscribe message was sent or
      *             before a UnsubAck message was received.
@@ -321,7 +321,7 @@ public interface Mqtt5ReactorClient extends Mqtt5Client {
      * @return the {@link Mono} which
      *         <ul>
      *           <li>completes when the client was successfully re-authenticated,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5AuthException Mqtt5AuthException}
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5AuthException Mqtt5AuthException}
      *             wrapping the Auth message with the Error Code if not re-authenticated successfully or
      *           <li>errors with a different exception if an error occurred before the first Auth message was sent or
      *             before the last Auth message was received.
diff --git a/reactor/src/main/java/com/hivemq/client/rx/reactor/CorePublisherWithSingle.java b/reactor/src/main/java/com/hivemq/client2/rx/reactor/CorePublisherWithSingle.java
similarity index 91%
rename from reactor/src/main/java/com/hivemq/client/rx/reactor/CorePublisherWithSingle.java
rename to reactor/src/main/java/com/hivemq/client2/rx/reactor/CorePublisherWithSingle.java
index 770586fc0..9cc7191f1 100644
--- a/reactor/src/main/java/com/hivemq/client/rx/reactor/CorePublisherWithSingle.java
+++ b/reactor/src/main/java/com/hivemq/client2/rx/reactor/CorePublisherWithSingle.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx.reactor;
+package com.hivemq.client2.rx.reactor;
 
-import com.hivemq.client.rx.reactivestreams.PublisherWithSingle;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
+import com.hivemq.client2.rx.reactivestreams.PublisherWithSingle;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Publisher;
 import org.reactivestreams.Subscriber;
diff --git a/reactor/src/main/java/com/hivemq/client/rx/reactor/CoreWithSingleSubscriber.java b/reactor/src/main/java/com/hivemq/client2/rx/reactor/CoreWithSingleSubscriber.java
similarity index 91%
rename from reactor/src/main/java/com/hivemq/client/rx/reactor/CoreWithSingleSubscriber.java
rename to reactor/src/main/java/com/hivemq/client2/rx/reactor/CoreWithSingleSubscriber.java
index bd495af0d..1a9be33d8 100644
--- a/reactor/src/main/java/com/hivemq/client/rx/reactor/CoreWithSingleSubscriber.java
+++ b/reactor/src/main/java/com/hivemq/client2/rx/reactor/CoreWithSingleSubscriber.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx.reactor;
+package com.hivemq.client2.rx.reactor;
 
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
 import reactor.core.CoreSubscriber;
 
 /**
diff --git a/reactor/src/main/java/com/hivemq/client/rx/reactor/FluxWithSingle.java b/reactor/src/main/java/com/hivemq/client2/rx/reactor/FluxWithSingle.java
similarity index 97%
rename from reactor/src/main/java/com/hivemq/client/rx/reactor/FluxWithSingle.java
rename to reactor/src/main/java/com/hivemq/client2/rx/reactor/FluxWithSingle.java
index 3a598770b..4808c1153 100644
--- a/reactor/src/main/java/com/hivemq/client/rx/reactor/FluxWithSingle.java
+++ b/reactor/src/main/java/com/hivemq/client2/rx/reactor/FluxWithSingle.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx.reactor;
-
-import com.hivemq.client.internal.rx.reactor.CoreWithSingleStrictSubscriber;
-import com.hivemq.client.internal.rx.reactor.operators.FluxWithSingleFrom;
-import com.hivemq.client.internal.rx.reactor.operators.FluxWithSingleMap;
-import com.hivemq.client.internal.rx.reactor.operators.FluxWithSinglePublishOn;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.rx.reactivestreams.PublisherWithSingle;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
+package com.hivemq.client2.rx.reactor;
+
+import com.hivemq.client2.internal.rx.reactor.CoreWithSingleStrictSubscriber;
+import com.hivemq.client2.internal.rx.reactor.operators.FluxWithSingleFrom;
+import com.hivemq.client2.internal.rx.reactor.operators.FluxWithSingleMap;
+import com.hivemq.client2.internal.rx.reactor.operators.FluxWithSinglePublishOn;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.rx.reactivestreams.PublisherWithSingle;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/reactor/src/test/java/com/hivemq/client/rx/reactor/FluxWithSingleItem.java b/reactor/src/test/java/com/hivemq/client2/rx/reactor/FluxWithSingleItem.java
similarity index 98%
rename from reactor/src/test/java/com/hivemq/client/rx/reactor/FluxWithSingleItem.java
rename to reactor/src/test/java/com/hivemq/client2/rx/reactor/FluxWithSingleItem.java
index c6c6d1a16..d6b7b393f 100644
--- a/reactor/src/test/java/com/hivemq/client/rx/reactor/FluxWithSingleItem.java
+++ b/reactor/src/test/java/com/hivemq/client2/rx/reactor/FluxWithSingleItem.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx.reactor;
+package com.hivemq.client2.rx.reactor;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/reactor/src/test/java/com/hivemq/client/rx/reactor/FluxWithSingleSplit.java b/reactor/src/test/java/com/hivemq/client2/rx/reactor/FluxWithSingleSplit.java
similarity index 97%
rename from reactor/src/test/java/com/hivemq/client/rx/reactor/FluxWithSingleSplit.java
rename to reactor/src/test/java/com/hivemq/client2/rx/reactor/FluxWithSingleSplit.java
index d84d2bd87..218d5f419 100644
--- a/reactor/src/test/java/com/hivemq/client/rx/reactor/FluxWithSingleSplit.java
+++ b/reactor/src/test/java/com/hivemq/client2/rx/reactor/FluxWithSingleSplit.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx.reactor;
+package com.hivemq.client2.rx.reactor;
 
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/reactor/src/test/java/com/hivemq/client/rx/reactor/FluxWithSingleTest.java b/reactor/src/test/java/com/hivemq/client2/rx/reactor/FluxWithSingleTest.java
similarity index 99%
rename from reactor/src/test/java/com/hivemq/client/rx/reactor/FluxWithSingleTest.java
rename to reactor/src/test/java/com/hivemq/client2/rx/reactor/FluxWithSingleTest.java
index 0872ecae9..e4af4c602 100644
--- a/reactor/src/test/java/com/hivemq/client/rx/reactor/FluxWithSingleTest.java
+++ b/reactor/src/test/java/com/hivemq/client2/rx/reactor/FluxWithSingleTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx.reactor;
+package com.hivemq.client2.rx.reactor;
 
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.function.ThrowingSupplier;
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 6658e9120..c71c3ac7c 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -15,7 +15,7 @@ pluginManagement {
     }
 }
 
-rootProject.name = "hivemq-mqtt-client"
+rootProject.name = "hivemq-mqtt-client2"
 
 listOf("websocket", "proxy", "epoll", "reactor", "examples").forEach { module ->
     include("${rootProject.name}-$module")
diff --git a/src/main/java/com/hivemq/client/annotations/DoNotImplement.java b/src/main/java/com/hivemq/client/annotations/DoNotImplement.java
deleted file mode 100644
index 6048c2ed2..000000000
--- a/src/main/java/com/hivemq/client/annotations/DoNotImplement.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2018-present HiveMQ and the HiveMQ Community
- *
- * Licensed 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
- *
- *     http://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 com.hivemq.client.annotations;
-
-import java.lang.annotation.*;
-
-/**
- * Documents that an interface MUST NOT be implemented by the user.
- * <p>
- * The implementation is provided by the library.
- * <p>
- * This allows the library to later add methods to the interface without breaking backwards compatibility with
- * implementing classes.
- *
- * @author Silvio Giebl
- */
-@Documented
-@Retention(RetentionPolicy.CLASS)
-@Target(ElementType.TYPE)
-public @interface DoNotImplement {}
diff --git a/src/main/java/com/hivemq/client/annotations/Immutable.java b/src/main/java/com/hivemq/client/annotations/Immutable.java
deleted file mode 100644
index 400561cbc..000000000
--- a/src/main/java/com/hivemq/client/annotations/Immutable.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2018-present HiveMQ and the HiveMQ Community
- *
- * Licensed 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
- *
- *     http://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 com.hivemq.client.annotations;
-
-import java.lang.annotation.*;
-
-/**
- * Documents that the annotated type is immutable. This means that its state can not be seen to change and can not be
- * changed by callers.
- *
- * @author Silvio Giebl
- */
-@Documented
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE, ElementType.TYPE_USE})
-public @interface Immutable {}
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/advanced/interceptor/MqttClientInterceptors.java b/src/main/java/com/hivemq/client/internal/mqtt/advanced/interceptor/MqttClientInterceptors.java
deleted file mode 100644
index d2f857942..000000000
--- a/src/main/java/com/hivemq/client/internal/mqtt/advanced/interceptor/MqttClientInterceptors.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2018-present HiveMQ and the HiveMQ Community
- *
- * Licensed 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
- *
- *     http://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 com.hivemq.client.internal.mqtt.advanced.interceptor;
-
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptors;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5IncomingQos1Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5OutgoingQos1Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5IncomingQos2Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5OutgoingQos2Interceptor;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Objects;
-
-/**
- * @author Silvio Giebl
- */
-public class MqttClientInterceptors implements Mqtt5ClientInterceptors {
-
-    private final @Nullable Mqtt5IncomingQos1Interceptor incomingQos1Interceptor;
-    private final @Nullable Mqtt5OutgoingQos1Interceptor outgoingQos1Interceptor;
-    private final @Nullable Mqtt5IncomingQos2Interceptor incomingQos2Interceptor;
-    private final @Nullable Mqtt5OutgoingQos2Interceptor outgoingQos2Interceptor;
-
-    MqttClientInterceptors(
-            final @Nullable Mqtt5IncomingQos1Interceptor incomingQos1Interceptor,
-            final @Nullable Mqtt5OutgoingQos1Interceptor outgoingQos1Interceptor,
-            final @Nullable Mqtt5IncomingQos2Interceptor incomingQos2Interceptor,
-            final @Nullable Mqtt5OutgoingQos2Interceptor outgoingQos2Interceptor) {
-
-        this.incomingQos1Interceptor = incomingQos1Interceptor;
-        this.outgoingQos1Interceptor = outgoingQos1Interceptor;
-        this.incomingQos2Interceptor = incomingQos2Interceptor;
-        this.outgoingQos2Interceptor = outgoingQos2Interceptor;
-    }
-
-    @Override
-    public @Nullable Mqtt5IncomingQos1Interceptor getIncomingQos1Interceptor() {
-        return incomingQos1Interceptor;
-    }
-
-    @Override
-    public @Nullable Mqtt5OutgoingQos1Interceptor getOutgoingQos1Interceptor() {
-        return outgoingQos1Interceptor;
-    }
-
-    @Override
-    public @Nullable Mqtt5IncomingQos2Interceptor getIncomingQos2Interceptor() {
-        return incomingQos2Interceptor;
-    }
-
-    @Override
-    public @Nullable Mqtt5OutgoingQos2Interceptor getOutgoingQos2Interceptor() {
-        return outgoingQos2Interceptor;
-    }
-
-    @Override
-    public MqttClientInterceptorsBuilder.@NotNull Default extend() {
-        return new MqttClientInterceptorsBuilder.Default(this);
-    }
-
-    @Override
-    public boolean equals(final @Nullable Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof MqttClientInterceptors)) {
-            return false;
-        }
-        final MqttClientInterceptors that = (MqttClientInterceptors) o;
-
-        return Objects.equals(incomingQos1Interceptor, that.incomingQos1Interceptor) &&
-                Objects.equals(outgoingQos1Interceptor, that.outgoingQos1Interceptor) &&
-                Objects.equals(incomingQos2Interceptor, that.incomingQos2Interceptor) &&
-                Objects.equals(outgoingQos2Interceptor, that.outgoingQos2Interceptor);
-    }
-
-    @Override
-    public int hashCode() {
-        int result = Objects.hashCode(incomingQos1Interceptor);
-        result = 31 * result + Objects.hashCode(outgoingQos1Interceptor);
-        result = 31 * result + Objects.hashCode(incomingQos2Interceptor);
-        result = 31 * result + Objects.hashCode(outgoingQos2Interceptor);
-        return result;
-    }
-}
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ClientModule.java b/src/main/java/com/hivemq/client/internal/mqtt/ioc/ClientModule.java
deleted file mode 100644
index 6ba0c6022..000000000
--- a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ClientModule.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2018-present HiveMQ and the HiveMQ Community
- *
- * Licensed 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
- *
- *     http://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 com.hivemq.client.internal.mqtt.ioc;
-
-import dagger.Module;
-
-/**
- * @author Silvio Giebl
- */
-@Module
-abstract class ClientModule {}
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/MqttCommonReasonCode.java b/src/main/java/com/hivemq/client/internal/mqtt/message/MqttCommonReasonCode.java
deleted file mode 100644
index 0a0357b29..000000000
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/MqttCommonReasonCode.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2018-present HiveMQ and the HiveMQ Community
- *
- * Licensed 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
- *
- *     http://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 com.hivemq.client.internal.mqtt.message;
-
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * MQTT Reason Codes that are used in 2 ore more MQTT packets according to the MQTT 5 specification.
- *
- * @author Silvio Giebl
- */
-public enum MqttCommonReasonCode implements Mqtt5ReasonCode {
-
-    SUCCESS(0x00),
-    NO_MATCHING_SUBSCRIBERS(0x10),
-    UNSPECIFIED_ERROR(0x80),
-    MALFORMED_PACKET(0x81),
-    PROTOCOL_ERROR(0x82),
-    IMPLEMENTATION_SPECIFIC_ERROR(0x83),
-    NOT_AUTHORIZED(0x87),
-    SERVER_BUSY(0x89),
-    BAD_AUTHENTICATION_METHOD(0x8C),
-    TOPIC_FILTER_INVALID(0x8F),
-    TOPIC_NAME_INVALID(0x90),
-    PACKET_IDENTIFIER_IN_USE(0x91),
-    PACKET_IDENTIFIER_NOT_FOUND(0x92),
-    PACKET_TOO_LARGE(0x95),
-    QUOTA_EXCEEDED(0x97),
-    PAYLOAD_FORMAT_INVALID(0x99),
-    RETAIN_NOT_SUPPORTED(0x9A),
-    QOS_NOT_SUPPORTED(0x9B),
-    USE_ANOTHER_SERVER(0x9C),
-    SERVER_MOVED(0x9D),
-    SHARED_SUBSCRIPTIONS_NOT_SUPPORTED(0x9E),
-    CONNECTION_RATE_EXCEEDED(0x9F),
-    SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED(0xA1),
-    WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED(0xA2);
-
-    private final int code;
-
-    MqttCommonReasonCode(final int code) {
-        this.code = code;
-    }
-
-    @Override
-    public int getCode() {
-        return code;
-    }
-
-    public static boolean allErrors(final @NotNull ImmutableList<? extends Mqtt5ReasonCode> reasonCodes) {
-        //noinspection ForLoopReplaceableByForEach
-        for (int i = 0; i < reasonCodes.size(); i++) {
-            if (!reasonCodes.get(i).isError()) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/com/hivemq/client/internal/rx/RxFutureConverter.java b/src/main/java/com/hivemq/client/internal/rx/RxFutureConverter.java
deleted file mode 100644
index fa15aff6d..000000000
--- a/src/main/java/com/hivemq/client/internal/rx/RxFutureConverter.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright 2018-present HiveMQ and the HiveMQ Community
- *
- * Licensed 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
- *
- *     http://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 com.hivemq.client.internal.rx;
-
-import io.reactivex.*;
-import io.reactivex.disposables.Disposable;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.BiConsumer;
-
-/**
- * @author Silvio Giebl
- */
-public final class RxFutureConverter {
-
-    public static @NotNull CompletableFuture<Void> toFuture(final @NotNull Completable completable) {
-        return new RxCompletableFuture(completable);
-    }
-
-    public static <T> @NotNull CompletableFuture<@NotNull Optional<T>> toFuture(final @NotNull Maybe<T> maybe) {
-        return new RxMaybeFuture<>(maybe);
-    }
-
-    public static <T> @NotNull CompletableFuture<@NotNull T> toFuture(final @NotNull Single<T> single) {
-        return new RxSingleFuture<>(single);
-    }
-
-    private static abstract class RxFuture<T> extends CompletableFuture<T> {
-
-        volatile @Nullable Disposable disposable;
-        volatile boolean cancelled;
-
-        public void onSubscribe(final @NotNull Disposable d) {
-            disposable = d;
-            if (cancelled) {
-                d.dispose();
-            }
-        }
-
-        public void onError(final @NotNull Throwable e) {
-            if (!cancelled) {
-                completeExceptionally(e);
-            }
-        }
-
-        @Override
-        public boolean cancel(final boolean mayInterruptIfRunning) {
-            cancelled = true;
-            final Disposable disposable = this.disposable;
-            if (disposable != null) {
-                disposable.dispose();
-            }
-            return super.cancel(mayInterruptIfRunning);
-        }
-    }
-
-    private static class RxCompletableFuture extends RxFuture<Void> implements CompletableObserver {
-
-        RxCompletableFuture(final @NotNull Completable completable) {
-            completable.subscribe(this);
-        }
-
-        @Override
-        public void onComplete() {
-            if (!cancelled) {
-                complete(null);
-            }
-        }
-    }
-
-    private static class RxMaybeFuture<T> extends RxFuture<Optional<T>> implements MaybeObserver<T> {
-
-        RxMaybeFuture(final @NotNull Maybe<T> maybe) {
-            maybe.subscribe(this);
-        }
-
-        @Override
-        public void onSuccess(final @NotNull T t) {
-            if (!cancelled) {
-                complete(Optional.of(t));
-            }
-        }
-
-        @Override
-        public void onComplete() {
-            if (!cancelled) {
-                complete(Optional.empty());
-            }
-        }
-    }
-
-    private static class RxSingleFuture<T> extends RxFuture<T> implements SingleObserver<T> {
-
-        RxSingleFuture(final @NotNull Single<T> single) {
-            single.subscribe(this);
-        }
-
-        @Override
-        public void onSuccess(final @NotNull T t) {
-            if (!cancelled) {
-                complete(t);
-            }
-        }
-    }
-
-    public static @NotNull Completable toCompletable(final @NotNull CompletableFuture<?> future) {
-        return new FutureCompletable(future);
-    }
-
-    public static <T> @NotNull Maybe<T> toMaybe(final @NotNull CompletableFuture<@NotNull Optional<T>> future) {
-        return new FutureMaybe<>(future);
-    }
-
-    public static <T> @NotNull Single<T> toSingle(final @NotNull CompletableFuture<@NotNull T> future) {
-        return new FutureSingle<>(future);
-    }
-
-    private static final int INITIAL = 0;
-    private static final int SUBSCRIBED_OR_COMPLETE = 1;
-    private static final int SUBSCRIBED_AND_COMPLETE_OR_CANCELLED = 2;
-
-    private static boolean checkComplete(final @NotNull AtomicInteger done) {
-        return !done.compareAndSet(INITIAL, SUBSCRIBED_OR_COMPLETE) &&
-                done.compareAndSet(SUBSCRIBED_OR_COMPLETE, SUBSCRIBED_AND_COMPLETE_OR_CANCELLED);
-    }
-
-    private static void dispose(final @NotNull AtomicInteger done, final @NotNull CompletableFuture<?> future) {
-        done.set(SUBSCRIBED_AND_COMPLETE_OR_CANCELLED);
-        future.cancel(false);
-    }
-
-    private static boolean isDisposed(final @NotNull AtomicInteger done) {
-        return done.get() == SUBSCRIBED_AND_COMPLETE_OR_CANCELLED;
-    }
-
-    private static class FutureCompletable extends Completable implements Disposable, BiConsumer<Object, Throwable> {
-
-        private final @NotNull CompletableFuture<?> future;
-        private volatile @Nullable CompletableObserver observer;
-        private volatile @Nullable Throwable throwable;
-        private final @NotNull AtomicInteger done = new AtomicInteger(INITIAL);
-
-        FutureCompletable(final @NotNull CompletableFuture<?> future) {
-            this.future = future;
-            future.whenComplete(this);
-        }
-
-        @Override
-        protected void subscribeActual(final @NotNull CompletableObserver observer) {
-            this.observer = observer;
-            observer.onSubscribe(this);
-            if (checkComplete(done)) {
-                complete(observer, throwable);
-            }
-        }
-
-        @Override
-        public void dispose() {
-            RxFutureConverter.dispose(done, future);
-        }
-
-        @Override
-        public boolean isDisposed() {
-            return RxFutureConverter.isDisposed(done);
-        }
-
-        @Override
-        public void accept(final @Nullable Object o, final @Nullable Throwable throwable) {
-            this.throwable = throwable;
-            if (checkComplete(done)) {
-                final CompletableObserver observer = this.observer;
-                assert observer != null;
-                complete(observer, throwable);
-            }
-        }
-
-        private static void complete(final @NotNull CompletableObserver observer, final @Nullable Throwable throwable) {
-            if (throwable == null) {
-                observer.onComplete();
-            } else {
-                observer.onError(throwable);
-            }
-        }
-    }
-
-    private static class FutureMaybe<T> extends Maybe<T> implements Disposable, BiConsumer<Optional<T>, Throwable> {
-
-        private final @NotNull CompletableFuture<Optional<T>> future;
-        private volatile @Nullable MaybeObserver<? super T> observer;
-        private volatile @Nullable T t;
-        private volatile @Nullable Throwable throwable;
-        private final @NotNull AtomicInteger done = new AtomicInteger(INITIAL);
-
-        FutureMaybe(final @NotNull CompletableFuture<Optional<T>> future) {
-            this.future = future;
-            future.whenComplete(this);
-        }
-
-        @Override
-        protected void subscribeActual(final @NotNull MaybeObserver<? super T> observer) {
-            this.observer = observer;
-            observer.onSubscribe(this);
-            if (checkComplete(done)) {
-                complete(observer, t, throwable);
-            }
-        }
-
-        @Override
-        public void dispose() {
-            RxFutureConverter.dispose(done, future);
-        }
-
-        @Override
-        public boolean isDisposed() {
-            return RxFutureConverter.isDisposed(done);
-        }
-
-        @Override
-        @SuppressWarnings("OptionalAssignedToNull")
-        public void accept(final @Nullable Optional<T> t, final @Nullable Throwable throwable) {
-            final T t1;
-            final Throwable throwable1;
-            if (throwable == null) {
-                if (t == null) {
-                    t1 = null;
-                    throwable1 = new NullPointerException();
-                } else {
-                    t1 = t.orElse(null);
-                    throwable1 = null;
-                }
-            } else {
-                t1 = null;
-                throwable1 = throwable;
-            }
-            this.t = t1;
-            this.throwable = throwable1;
-            if (checkComplete(done)) {
-                final MaybeObserver<? super T> observer = this.observer;
-                assert observer != null;
-                complete(observer, t1, throwable1);
-            }
-        }
-
-        private static <T> void complete(
-                final @NotNull MaybeObserver<? super T> observer,
-                final @Nullable T t,
-                final @Nullable Throwable throwable) {
-
-            if (throwable != null) {
-                observer.onError(throwable);
-            } else if (t != null) {
-                observer.onSuccess(t);
-            } else {
-                observer.onComplete();
-            }
-        }
-    }
-
-    private static class FutureSingle<T> extends Single<T> implements Disposable, BiConsumer<T, Throwable> {
-
-        private final @NotNull CompletableFuture<T> future;
-        private volatile @Nullable SingleObserver<? super T> observer;
-        private volatile @Nullable T t;
-        private volatile @Nullable Throwable throwable;
-        private final @NotNull AtomicInteger done = new AtomicInteger(INITIAL);
-
-        FutureSingle(final @NotNull CompletableFuture<T> future) {
-            this.future = future;
-            future.whenComplete(this);
-        }
-
-        @Override
-        protected void subscribeActual(final @NotNull SingleObserver<? super T> observer) {
-            this.observer = observer;
-            observer.onSubscribe(this);
-            if (checkComplete(done)) {
-                complete(observer, t, throwable);
-            }
-        }
-
-        @Override
-        public void dispose() {
-            RxFutureConverter.dispose(done, future);
-        }
-
-        @Override
-        public boolean isDisposed() {
-            return RxFutureConverter.isDisposed(done);
-        }
-
-        @Override
-        public void accept(final @Nullable T t, final @Nullable Throwable throwable) {
-            this.t = t;
-            this.throwable = throwable;
-            if (checkComplete(done)) {
-                final SingleObserver<? super T> observer = this.observer;
-                assert observer != null;
-                complete(observer, t, throwable);
-            }
-        }
-
-        private static <T> void complete(
-                final @NotNull SingleObserver<? super T> observer,
-                final @Nullable T t,
-                final @Nullable Throwable throwable) {
-
-            if (t != null) {
-                observer.onSuccess(t);
-            } else {
-                observer.onError((throwable != null) ? throwable : new NullPointerException());
-            }
-        }
-    }
-
-    private RxFutureConverter() {}
-}
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientBuilderBase.java b/src/main/java/com/hivemq/client/mqtt/MqttClientBuilderBase.java
deleted file mode 100644
index c954888e7..000000000
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientBuilderBase.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright 2018-present HiveMQ and the HiveMQ Community
- *
- * Licensed 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
- *
- *     http://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 com.hivemq.client.mqtt;
-
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttClientIdentifier;
-import com.hivemq.client.mqtt.lifecycle.MqttClientAutoReconnect;
-import com.hivemq.client.mqtt.lifecycle.MqttClientAutoReconnectBuilder;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedListener;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-
-/**
- * Builder base for an {@link MqttClient}.
- *
- * @param <B> the type of the builder.
- * @author Silvio Giebl
- * @since 1.0
- */
-@DoNotImplement
-public interface MqttClientBuilderBase<B extends MqttClientBuilderBase<B>> {
-
-    /**
-     * Sets the {@link MqttClientConfig#getClientIdentifier() Client Identifier}.
-     *
-     * @param identifier the string representation of the Client Identifier.
-     * @return the builder.
-     */
-    @CheckReturnValue
-    @NotNull B identifier(@NotNull String identifier);
-
-    /**
-     * Sets the {@link MqttClientConfig#getClientIdentifier() Client Identifier}.
-     *
-     * @param identifier the Client Identifier.
-     * @return the builder.
-     */
-    @CheckReturnValue
-    @NotNull B identifier(@NotNull MqttClientIdentifier identifier);
-
-    /**
-     * Sets the {@link MqttClientConfig#getServerAddress() server address} to connect to.
-     *
-     * @param address the server address.
-     * @return the builder
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B serverAddress(@NotNull InetSocketAddress address);
-
-    /**
-     * Sets the {@link MqttClientConfig#getServerHost() server host} to connect to.
-     *
-     * @param host the server host.
-     * @return the builder.
-     */
-    @CheckReturnValue
-    @NotNull B serverHost(@NotNull String host);
-
-    /**
-     * Sets the {@link MqttClientConfig#getServerHost() server host} to connect to.
-     *
-     * @param host the server host.
-     * @return the builder.
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B serverHost(@NotNull InetAddress host);
-
-    /**
-     * Sets the {@link MqttClientConfig#getServerPort() server port} to connect to.
-     *
-     * @param port the server port.
-     * @return the builder.
-     */
-    @CheckReturnValue
-    @NotNull B serverPort(int port);
-
-    /**
-     * Use {@link #sslWithDefaultConfig()}.
-     *
-     * @return use {@link #sslWithDefaultConfig()}.
-     * @deprecated use {@link #sslWithDefaultConfig()}.
-     */
-    @Deprecated
-    default @NotNull B useSslWithDefaultConfig() {
-        return sslWithDefaultConfig();
-    }
-
-    /**
-     * Sets the {@link MqttClientConfig#getSslConfig() secure transport configuration} to the default configuration.
-     * <p>
-     * This means that the systems default trust store, ciphers and protocols are used.
-     *
-     * @return the builder.
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B sslWithDefaultConfig();
-
-    /**
-     * Use {@link #sslConfig(MqttClientSslConfig)}.
-     *
-     * @param sslConfig use {@link #sslConfig(MqttClientSslConfig)}.
-     * @return use {@link #sslConfig(MqttClientSslConfig)}.
-     * @deprecated use {@link #sslConfig(MqttClientSslConfig)}.
-     */
-    @Deprecated
-    default @NotNull B useSsl(final @Nullable MqttClientSslConfig sslConfig) {
-        return sslConfig(sslConfig);
-    }
-
-    /**
-     * Sets the optional {@link MqttClientConfig#getSslConfig() secure transport configuration}.
-     *
-     * @param sslConfig the secure transport configuration or <code>null</code> to remove any previously set secure
-     *                  transport configuration.
-     * @return the builder.
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B sslConfig(@Nullable MqttClientSslConfig sslConfig);
-
-    /**
-     * Use {@link #sslConfig()}.
-     *
-     * @return use {@link #sslConfig()}.
-     * @deprecated use {@link #sslConfig()}.
-     */
-    @Deprecated
-    default MqttClientSslConfigBuilder.@NotNull Nested<? extends B> useSsl() {
-        return sslConfig();
-    }
-
-    /**
-     * Fluent counterpart of {@link #sslConfig(MqttClientSslConfig)}.
-     * <p>
-     * Calling {@link MqttClientSslConfigBuilder.Nested#applySslConfig()} on the returned builder has the effect of
-     * extending the current secure transport configuration.
-     *
-     * @return the fluent builder for the secure transport configuration.
-     * @see #sslConfig(MqttClientSslConfig)
-     * @since 1.1
-     */
-    @CheckReturnValue
-    MqttClientSslConfigBuilder.@NotNull Nested<? extends B> sslConfig();
-
-    /**
-     * Use {@link #webSocketWithDefaultConfig()}.
-     *
-     * @return use {@link #webSocketWithDefaultConfig()}.
-     * @deprecated use {@link #webSocketWithDefaultConfig()}.
-     */
-    @Deprecated
-    default @NotNull B useWebSocketWithDefaultConfig() {
-        return webSocketWithDefaultConfig();
-    }
-
-    /**
-     * Sets the {@link MqttClientConfig#getWebSocketConfig() WebSocket transport configuration} to the default
-     * configuration.
-     *
-     * @return the builder.
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B webSocketWithDefaultConfig();
-
-    /**
-     * Use {@link #webSocketConfig(MqttWebSocketConfig)}.
-     *
-     * @param webSocketConfig use {@link #webSocketConfig(MqttWebSocketConfig)}.
-     * @return use {@link #webSocketConfig(MqttWebSocketConfig)}.
-     * @deprecated use {@link #webSocketConfig(MqttWebSocketConfig)}.
-     */
-    @Deprecated
-    default @NotNull B useWebSocket(final @Nullable MqttWebSocketConfig webSocketConfig) {
-        return webSocketConfig(webSocketConfig);
-    }
-
-    /**
-     * Sets the optional {@link MqttClientConfig#getWebSocketConfig() WebSocket transport configuration}.
-     *
-     * @param webSocketConfig the WebSocket transport configuration or <code>null</code> to remove any previously set
-     *                        WebSocket transport configuration.
-     * @return the builder.
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B webSocketConfig(@Nullable MqttWebSocketConfig webSocketConfig);
-
-    /**
-     * Use {@link #webSocketConfig()}.
-     *
-     * @return use {@link #webSocketConfig()}.
-     * @deprecated use {@link #webSocketConfig()}.
-     */
-    @Deprecated
-    default MqttWebSocketConfigBuilder.@NotNull Nested<? extends B> useWebSocket() {
-        return webSocketConfig();
-    }
-
-    /**
-     * Fluent counterpart of {@link #webSocketConfig(MqttWebSocketConfig)}.
-     * <p>
-     * Calling {@link MqttWebSocketConfigBuilder.Nested#applyWebSocketConfig()} on the returned builder has the effect
-     * of extending the current WebSocket transport configuration.
-     *
-     * @return the fluent builder for the WebSocket configuration.
-     * @see #webSocketConfig(MqttWebSocketConfig)
-     * @since 1.1
-     */
-    @CheckReturnValue
-    MqttWebSocketConfigBuilder.@NotNull Nested<? extends B> webSocketConfig();
-
-    /**
-     * Sets the {@link MqttClientConfig#getTransportConfig() transport configuration}.
-     *
-     * @param transportConfig the transport configuration.
-     * @return the builder.
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B transportConfig(@NotNull MqttClientTransportConfig transportConfig);
-
-    /**
-     * Fluent counterpart of {@link #transportConfig(MqttClientTransportConfig)}.
-     * <p>
-     * Calling {@link MqttClientTransportConfigBuilder.Nested#applyTransportConfig()} on the returned builder has the
-     * effect of extending the current transport configuration.
-     *
-     * @return the fluent builder for the transport configuration.
-     * @see #transportConfig(MqttClientTransportConfig)
-     * @since 1.1
-     */
-    @CheckReturnValue
-    MqttClientTransportConfigBuilder.@NotNull Nested<? extends B> transportConfig();
-
-    /**
-     * Sets the {@link MqttClientConfig#getExecutorConfig() executor configuration}.
-     *
-     * @param executorConfig the executor configuration.
-     * @return the builder.
-     */
-    @CheckReturnValue
-    @NotNull B executorConfig(@NotNull MqttClientExecutorConfig executorConfig);
-
-    /**
-     * Fluent counterpart of {@link #executorConfig(MqttClientExecutorConfig)}.
-     * <p>
-     * Calling {@link MqttClientExecutorConfigBuilder.Nested#applyExecutorConfig()} on the returned builder has the
-     * effect of extending the current executor configuration.
-     *
-     * @return the fluent builder for the executor configuration.
-     * @see #executorConfig(MqttClientExecutorConfig)
-     */
-    @CheckReturnValue
-    MqttClientExecutorConfigBuilder.@NotNull Nested<? extends B> executorConfig();
-
-    /**
-     * Uses automatic reconnect with the default configuration.
-     *
-     * @return the builder.
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B automaticReconnectWithDefaultConfig();
-
-    /**
-     * Sets the optional {@link MqttClientConfig#getAutomaticReconnect() automatic reconnect strategy}.
-     *
-     * @param autoReconnect the automatic reconnect strategy or <code>null</code> to remove any previously set automatic
-     *                      reconnect strategy.
-     * @return the builder.
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B automaticReconnect(@Nullable MqttClientAutoReconnect autoReconnect);
-
-    /**
-     * Fluent counterpart of {@link #automaticReconnect(MqttClientAutoReconnect)}.
-     * <p>
-     * Calling {@link MqttClientAutoReconnectBuilder.Nested#applyAutomaticReconnect()} on the returned builder has the
-     * effect of extending the current automatic reconnect strategy.
-     *
-     * @return the fluent builder for the automatic reconnect strategy.
-     * @see #automaticReconnect(MqttClientAutoReconnect)
-     * @since 1.1
-     */
-    @CheckReturnValue
-    MqttClientAutoReconnectBuilder.@NotNull Nested<? extends B> automaticReconnect();
-
-    /**
-     * Adds a listener which is notified when the client is connected (a successful ConnAck message is received).
-     * <p>
-     * The listeners are called in the same order in which they are added.
-     *
-     * @param connectedListener the listener to add.
-     * @return the builder.
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B addConnectedListener(@NotNull MqttClientConnectedListener connectedListener);
-
-    /**
-     * Adds a listener which is notified when the client is disconnected (with or without a Disconnect message) or the
-     * connection fails.
-     * <p>
-     * The listeners are called in the same order in which they are added.
-     *
-     * @param disconnectedListener the listener to add.
-     * @return the builder.
-     * @since 1.1
-     */
-    @CheckReturnValue
-    @NotNull B addDisconnectedListener(@NotNull MqttClientDisconnectedListener disconnectedListener);
-}
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/Mqtt5ClientAdvancedConfigBuilder.java b/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/Mqtt5ClientAdvancedConfigBuilder.java
deleted file mode 100644
index 9804156b8..000000000
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/Mqtt5ClientAdvancedConfigBuilder.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2018-present HiveMQ and the HiveMQ Community
- *
- * Licensed 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
- *
- *     http://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 com.hivemq.client.mqtt.mqtt5.advanced;
-
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Builder for a {@link Mqtt5ClientAdvancedConfig}.
- *
- * @author Silvio Giebl
- * @since 1.0
- */
-@DoNotImplement
-public interface Mqtt5ClientAdvancedConfigBuilder
-        extends Mqtt5ClientAdvancedConfigBuilderBase<Mqtt5ClientAdvancedConfigBuilder> {
-
-    /**
-     * Builds the {@link Mqtt5ClientAdvancedConfig}.
-     *
-     * @return the built {@link Mqtt5ClientAdvancedConfig}.
-     */
-    @CheckReturnValue
-    @NotNull Mqtt5ClientAdvancedConfig build();
-
-    /**
-     * Builder for a {@link Mqtt5ClientAdvancedConfig} that is applied to a parent.
-     *
-     * @param <P> the type of the result when the built {@link Mqtt5ClientAdvancedConfig} is applied to the parent.
-     */
-    @DoNotImplement
-    interface Nested<P> extends Mqtt5ClientAdvancedConfigBuilderBase<Nested<P>> {
-
-        /**
-         * Builds the {@link Mqtt5ClientAdvancedConfig} and applies it to the parent.
-         *
-         * @return the result when the built {@link Mqtt5ClientAdvancedConfig} is applied to the parent.
-         */
-        @NotNull P applyAdvancedConfig();
-    }
-}
diff --git a/src/main/java/com/hivemq/client/annotations/CheckReturnValue.java b/src/main/java/com/hivemq/client2/annotations/CheckReturnValue.java
similarity index 95%
rename from src/main/java/com/hivemq/client/annotations/CheckReturnValue.java
rename to src/main/java/com/hivemq/client2/annotations/CheckReturnValue.java
index 10cfbf60d..70e697dfe 100644
--- a/src/main/java/com/hivemq/client/annotations/CheckReturnValue.java
+++ b/src/main/java/com/hivemq/client2/annotations/CheckReturnValue.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.annotations;
+package com.hivemq.client2.annotations;
 
 import java.lang.annotation.*;
 
diff --git a/src/main/java/com/hivemq/client/internal/annotations/CallByThread.java b/src/main/java/com/hivemq/client2/internal/annotations/CallByThread.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/annotations/CallByThread.java
rename to src/main/java/com/hivemq/client2/internal/annotations/CallByThread.java
index 680e06f01..bd7894d25 100644
--- a/src/main/java/com/hivemq/client/internal/annotations/CallByThread.java
+++ b/src/main/java/com/hivemq/client2/internal/annotations/CallByThread.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.annotations;
+package com.hivemq.client2.internal.annotations;
 
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/annotations/NotThreadSafe.java b/src/main/java/com/hivemq/client2/internal/annotations/NotThreadSafe.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/annotations/NotThreadSafe.java
rename to src/main/java/com/hivemq/client2/internal/annotations/NotThreadSafe.java
index b61792038..3ffd00d25 100644
--- a/src/main/java/com/hivemq/client/internal/annotations/NotThreadSafe.java
+++ b/src/main/java/com/hivemq/client2/internal/annotations/NotThreadSafe.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.annotations;
+package com.hivemq.client2.internal.annotations;
 
 import java.lang.annotation.*;
 
diff --git a/src/main/java/com/hivemq/client/internal/annotations/ThreadSafe.java b/src/main/java/com/hivemq/client2/internal/annotations/ThreadSafe.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/annotations/ThreadSafe.java
rename to src/main/java/com/hivemq/client2/internal/annotations/ThreadSafe.java
index ea5653dac..161af114e 100644
--- a/src/main/java/com/hivemq/client/internal/annotations/ThreadSafe.java
+++ b/src/main/java/com/hivemq/client2/internal/annotations/ThreadSafe.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.annotations;
+package com.hivemq.client2.internal.annotations;
 
 import java.lang.annotation.*;
 
diff --git a/src/main/java/com/hivemq/client/internal/checkpoint/Confirmable.java b/src/main/java/com/hivemq/client2/internal/checkpoint/Confirmable.java
similarity index 93%
rename from src/main/java/com/hivemq/client/internal/checkpoint/Confirmable.java
rename to src/main/java/com/hivemq/client2/internal/checkpoint/Confirmable.java
index 4c5f346ac..eeefa3515 100644
--- a/src/main/java/com/hivemq/client/internal/checkpoint/Confirmable.java
+++ b/src/main/java/com/hivemq/client2/internal/checkpoint/Confirmable.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.checkpoint;
+package com.hivemq.client2.internal.checkpoint;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/logging/InternalLogger.java b/src/main/java/com/hivemq/client2/internal/logging/InternalLogger.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/logging/InternalLogger.java
rename to src/main/java/com/hivemq/client2/internal/logging/InternalLogger.java
index 3326953d0..bad153ae5 100644
--- a/src/main/java/com/hivemq/client/internal/logging/InternalLogger.java
+++ b/src/main/java/com/hivemq/client2/internal/logging/InternalLogger.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.logging;
+package com.hivemq.client2.internal.logging;
 
 import org.jetbrains.annotations.NotNull;
 
@@ -36,4 +36,18 @@ public interface InternalLogger {
     void warn(@NotNull String format, @NotNull Object arg);
 
     void warn(@NotNull String format, @NotNull Object arg1, @NotNull Object arg2);
+
+    void debug(@NotNull String message);
+
+    void debug(@NotNull String format, @NotNull Object arg);
+
+    void debug(@NotNull String format, @NotNull Object arg1, @NotNull Object arg2);
+
+    void debug(@NotNull String format, @NotNull Object arg1, @NotNull Object arg2, @NotNull Object arg3);
+
+    void trace(@NotNull String message);
+
+    void trace(@NotNull String format, @NotNull Object arg);
+
+    void trace(@NotNull String format, @NotNull Object arg1, @NotNull Object arg2);
 }
diff --git a/src/main/java/com/hivemq/client/internal/logging/InternalLoggerFactory.java b/src/main/java/com/hivemq/client2/internal/logging/InternalLoggerFactory.java
similarity index 92%
rename from src/main/java/com/hivemq/client/internal/logging/InternalLoggerFactory.java
rename to src/main/java/com/hivemq/client2/internal/logging/InternalLoggerFactory.java
index e171be152..c5f6594df 100644
--- a/src/main/java/com/hivemq/client/internal/logging/InternalLoggerFactory.java
+++ b/src/main/java/com/hivemq/client2/internal/logging/InternalLoggerFactory.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.logging;
+package com.hivemq.client2.internal.logging;
 
-import com.hivemq.client.internal.util.ClassUtil;
+import com.hivemq.client2.internal.util.ClassUtil;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/logging/InternalNoopLogger.java b/src/main/java/com/hivemq/client2/internal/logging/InternalNoopLogger.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/logging/InternalNoopLogger.java
rename to src/main/java/com/hivemq/client2/internal/logging/InternalNoopLogger.java
index ceecb2479..fd2d26f30 100644
--- a/src/main/java/com/hivemq/client/internal/logging/InternalNoopLogger.java
+++ b/src/main/java/com/hivemq/client2/internal/logging/InternalNoopLogger.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.logging;
+package com.hivemq.client2.internal.logging;
 
 import org.jetbrains.annotations.NotNull;
 
@@ -47,4 +47,26 @@ public void warn(final @NotNull String format, final @NotNull Object arg) {}
 
     @Override
     public void warn(final @NotNull String format, final @NotNull Object arg1, final @NotNull Object arg2) {}
+
+    @Override
+    public void debug(@NotNull String message) {}
+
+    @Override
+    public void debug(@NotNull String format, @NotNull Object arg) {}
+
+    @Override
+    public void debug(@NotNull String format, @NotNull Object arg1, @NotNull Object arg2) {}
+
+    @Override
+    public void debug(@NotNull String format, @NotNull Object arg1, @NotNull Object arg2, @NotNull Object arg3) {}
+
+    @Override
+    public void trace(@NotNull String message) {}
+
+    @Override
+    public void trace(@NotNull String format, @NotNull Object arg) {}
+
+    @Override
+    public void trace(@NotNull String format, @NotNull Object arg1, @NotNull Object arg2) {}
+
 }
diff --git a/src/main/java/com/hivemq/client/internal/logging/InternalSlf4jLogger.java b/src/main/java/com/hivemq/client2/internal/logging/InternalSlf4jLogger.java
similarity index 66%
rename from src/main/java/com/hivemq/client/internal/logging/InternalSlf4jLogger.java
rename to src/main/java/com/hivemq/client2/internal/logging/InternalSlf4jLogger.java
index a95831987..bec9d7681 100644
--- a/src/main/java/com/hivemq/client/internal/logging/InternalSlf4jLogger.java
+++ b/src/main/java/com/hivemq/client2/internal/logging/InternalSlf4jLogger.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.logging;
+package com.hivemq.client2.internal.logging;
 
 import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
@@ -65,4 +65,39 @@ public void warn(final @NotNull String format, final @NotNull Object arg) {
     public void warn(final @NotNull String format, final @NotNull Object arg1, final @NotNull Object arg2) {
         delegate.warn(format, arg1, arg2);
     }
+
+    @Override
+    public void debug(@NotNull String message) {
+        delegate.debug(message);
+    }
+
+    @Override
+    public void debug(@NotNull String format, @NotNull Object arg) {
+        delegate.debug(format, arg);
+    }
+
+    @Override
+    public void debug(@NotNull String format, @NotNull Object arg1, @NotNull Object arg2) {
+        delegate.debug(format, arg1, arg2);
+    }
+
+    @Override
+    public void debug(@NotNull String format, @NotNull Object arg1, @NotNull Object arg2, @NotNull Object arg3) {
+        delegate.debug(format, arg1, arg2, arg3);
+    }
+
+    @Override
+    public void trace(@NotNull String message) {
+        delegate.trace(message);
+    }
+
+    @Override
+    public void trace(@NotNull String format, @NotNull Object arg) {
+        delegate.trace(format, arg);
+    }
+
+    @Override
+    public void trace(@NotNull String format, @NotNull Object arg1, @NotNull Object arg2) {
+        delegate.trace(format, arg1, arg2);
+    }
 }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttAsyncClient.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttAsyncClient.java
similarity index 77%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttAsyncClient.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttAsyncClient.java
index e9c768431..365b41714 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttAsyncClient.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttAsyncClient.java
@@ -14,34 +14,33 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
-
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectBuilder;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribeBuilder;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribeBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.rx.RxFutureConverter;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
-import io.reactivex.FlowableSubscriber;
-import io.reactivex.schedulers.Schedulers;
+package com.hivemq.client2.internal.mqtt;
+
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectBuilder;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishBuilder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribeBuilder;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribeBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5AsyncClient;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+import io.reactivex.rxjava3.core.FlowableSubscriber;
+import io.reactivex.rxjava3.schedulers.Schedulers;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscription;
@@ -113,7 +112,7 @@ public class MqttAsyncClient implements Mqtt5AsyncClient {
     public @NotNull CompletableFuture<@NotNull Mqtt5ConnAck> connect(final @Nullable Mqtt5Connect connect) {
         final MqttConnect mqttConnect = MqttChecks.connect(connect);
 
-        return RxFutureConverter.toFuture(delegate.connect(mqttConnect));
+        return delegate.connect(mqttConnect).toCompletionStage().toCompletableFuture();
     }
 
     @Override
@@ -125,7 +124,7 @@ public class MqttAsyncClient implements Mqtt5AsyncClient {
     public @NotNull CompletableFuture<@NotNull Mqtt5SubAck> subscribe(final @Nullable Mqtt5Subscribe subscribe) {
         final MqttSubscribe mqttSubscribe = MqttChecks.subscribe(subscribe);
 
-        return handleSubAck(RxFutureConverter.toFuture(delegate.subscribe(mqttSubscribe)), mqttSubscribe);
+        return handleSubAck(delegate.subscribe(mqttSubscribe).toCompletionStage().toCompletableFuture(), mqttSubscribe);
     }
 
     @Override
@@ -169,13 +168,13 @@ public class MqttAsyncClient implements Mqtt5AsyncClient {
         Checks.notNull(executor, "Executor");
 
         return handleSubAck(delegate.subscribePublishesUnsafe(mqttSubscribe, manualAcknowledgement)
-                .observeOnBoth(Schedulers.from(executor), true)
+                .observeBothOn(Schedulers.from(executor), true)
                 .subscribeSingleFuture(new CallbackSubscriber(callback)), mqttSubscribe);
     }
 
     @Override
-    public @NotNull MqttSubscribeAndCallbackBuilder subscribeWith() {
-        return new MqttSubscribeAndCallbackBuilder();
+    public @NotNull SubscribeBuilder subscribeWith() {
+        return new SubscribeBuilder();
     }
 
     @Override
@@ -228,7 +227,8 @@ public void publishes(
 
         final MqttUnsubscribe mqttUnsubscribe = MqttChecks.unsubscribe(unsubscribe);
 
-        return handleUnsubAck(RxFutureConverter.toFuture(delegate.unsubscribe(mqttUnsubscribe)), mqttUnsubscribe);
+        return handleUnsubAck(
+                delegate.unsubscribe(mqttUnsubscribe).toCompletionStage().toCompletableFuture(), mqttUnsubscribe);
     }
 
     @Override
@@ -240,7 +240,7 @@ public void publishes(
     public @NotNull CompletableFuture<@NotNull Mqtt5PublishResult> publish(final @Nullable Mqtt5Publish publish) {
         final MqttPublish mqttPublish = MqttChecks.publish(publish);
 
-        return RxFutureConverter.toFuture(delegate.publish(mqttPublish));
+        return delegate.publish(mqttPublish).toCompletionStage().toCompletableFuture();
     }
 
     @Override
@@ -250,7 +250,7 @@ public void publishes(
 
     @Override
     public @NotNull CompletableFuture<Void> reauth() {
-        return RxFutureConverter.toFuture(delegate.reauth());
+        return delegate.reauth().toCompletionStage((Void) null).toCompletableFuture();
     }
 
     @Override
@@ -262,7 +262,7 @@ public void publishes(
     public @NotNull CompletableFuture<Void> disconnect(final @Nullable Mqtt5Disconnect disconnect) {
         final MqttDisconnect mqttDisconnect = MqttChecks.disconnect(disconnect);
 
-        return RxFutureConverter.toFuture(delegate.disconnect(mqttDisconnect));
+        return delegate.disconnect(mqttDisconnect).toCompletionStage((Void) null).toCompletableFuture();
     }
 
     @Override
@@ -310,32 +310,33 @@ public void onComplete() {}
         public void onError(final @NotNull Throwable t) {}
     }
 
-    private class MqttSubscribeAndCallbackBuilder extends MqttSubscribeBuilder<MqttSubscribeAndCallbackBuilder>
-            implements Mqtt5SubscribeAndCallbackBuilder.Start.Complete, Mqtt5SubscribeAndCallbackBuilder.Call.Ex {
+    private class SubscribeBuilder extends MqttSubscribeBuilder<SubscribeBuilder>
+            implements Mqtt5AsyncClient.SubscribeBuilder.Start.Complete,
+            Mqtt5AsyncClient.SubscribeBuilder.AfterCallback {
 
         private @Nullable Consumer<Mqtt5Publish> callback;
         private @Nullable Executor executor;
         private boolean manualAcknowledgement;
 
         @Override
-        protected @NotNull MqttSubscribeAndCallbackBuilder self() {
+        protected @NotNull SubscribeBuilder self() {
             return this;
         }
 
         @Override
-        public @NotNull MqttSubscribeAndCallbackBuilder callback(final @Nullable Consumer<Mqtt5Publish> callback) {
+        public @NotNull SubscribeBuilder callback(final @Nullable Consumer<Mqtt5Publish> callback) {
             this.callback = Checks.notNull(callback, "Callback");
             return this;
         }
 
         @Override
-        public @NotNull MqttSubscribeAndCallbackBuilder executor(final @Nullable Executor executor) {
+        public @NotNull SubscribeBuilder executor(final @Nullable Executor executor) {
             this.executor = Checks.notNull(executor, "Executor");
             return this;
         }
 
         @Override
-        public @NotNull MqttSubscribeAndCallbackBuilder manualAcknowledgement(final boolean manualAcknowledgement) {
+        public @NotNull SubscribeBuilder manualAcknowledgement(final boolean manualAcknowledgement) {
             this.manualAcknowledgement = manualAcknowledgement;
             return this;
         }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttBlockingClient.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttBlockingClient.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttBlockingClient.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttBlockingClient.java
index 2103c73da..6b2b57310 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttBlockingClient.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttBlockingClient.java
@@ -14,39 +14,39 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
-
-import com.hivemq.client.internal.mqtt.exceptions.MqttClientStateExceptions;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectBuilder;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribeBuilder;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribeBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
-import io.reactivex.Flowable;
-import io.reactivex.FlowableSubscriber;
-import io.reactivex.internal.subscriptions.SubscriptionHelper;
+package com.hivemq.client2.internal.mqtt;
+
+import com.hivemq.client2.internal.mqtt.exceptions.MqttClientStateExceptions;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectBuilder;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishBuilder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribeBuilder;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribeBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5BlockingClient;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5SubAckException;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.FlowableSubscriber;
+import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscription;
@@ -126,17 +126,17 @@ public class MqttBlockingClient implements Mqtt5BlockingClient {
     }
 
     @Override
-    public @NotNull Mqtt5Publishes publishes(final @Nullable MqttGlobalPublishFilter filter) {
+    public @NotNull Publishes publishes(final @Nullable MqttGlobalPublishFilter filter) {
         return publishes(filter, false);
     }
 
     @Override
-    public @NotNull Mqtt5Publishes publishes(
+    public @NotNull Publishes publishes(
             final @Nullable MqttGlobalPublishFilter filter, final boolean manualAcknowledgement) {
 
         Checks.notNull(filter, "Global publish filter");
 
-        return new MqttPublishes(delegate.publishesUnsafe(filter, manualAcknowledgement));
+        return new Publishes(delegate.publishesUnsafe(filter, manualAcknowledgement));
     }
 
     @Override
@@ -216,14 +216,14 @@ public void disconnect(final @NotNull Mqtt5Disconnect disconnect) {
         return delegate.toAsync();
     }
 
-    private static class MqttPublishes implements Mqtt5Publishes, FlowableSubscriber<Mqtt5Publish> {
+    private static class Publishes implements Mqtt5BlockingClient.Publishes, FlowableSubscriber<Mqtt5Publish> {
 
         private final @NotNull AtomicReference<@Nullable Subscription> subscription = new AtomicReference<>();
         private final @NotNull LinkedList<Entry> entries = new LinkedList<>();
         private @Nullable Mqtt5Publish queuedPublish;
         private @Nullable Throwable error;
 
-        MqttPublishes(final @NotNull Flowable<Mqtt5Publish> publishes) {
+        Publishes(final @NotNull Flowable<Mqtt5Publish> publishes) {
             publishes.subscribe(this);
         }
 
@@ -319,9 +319,6 @@ public void onError(final @NotNull Throwable t) {
         public @NotNull Optional<Mqtt5Publish> receive(final long timeout, final @Nullable TimeUnit timeUnit)
                 throws InterruptedException {
 
-            if (timeout < 0) {
-                throw new IllegalArgumentException("Timeout must be greater than 0.");
-            }
             Checks.notNull(timeUnit, "Time unit");
 
             final Entry entry;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientConfig.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttClientConfig.java
similarity index 74%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttClientConfig.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttClientConfig.java
index 5c291f44b..67f7aa708 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientConfig.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttClientConfig.java
@@ -14,28 +14,28 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
-
-import com.hivemq.client.internal.mqtt.advanced.MqttClientAdvancedConfig;
-import com.hivemq.client.internal.mqtt.datatypes.MqttClientIdentifierImpl;
-import com.hivemq.client.internal.mqtt.ioc.ClientComponent;
-import com.hivemq.client.internal.mqtt.ioc.SingletonComponent;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.netty.NettyEventLoopProvider;
-import com.hivemq.client.internal.util.ExecutorUtil;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.MqttClientState;
-import com.hivemq.client.mqtt.MqttVersion;
-import com.hivemq.client.mqtt.datatypes.MqttClientIdentifier;
-import com.hivemq.client.mqtt.lifecycle.MqttClientAutoReconnect;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedListener;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConnectionConfig;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
+package com.hivemq.client2.internal.mqtt;
+
+import com.hivemq.client2.internal.mqtt.advanced.MqttAdvancedConfig;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttClientIdentifierImpl;
+import com.hivemq.client2.internal.mqtt.ioc.ClientComponent;
+import com.hivemq.client2.internal.mqtt.ioc.SingletonComponent;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.netty.NettyEventLoopProvider;
+import com.hivemq.client2.internal.util.ExecutorUtil;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.MqttClientState;
+import com.hivemq.client2.mqtt.MqttVersion;
+import com.hivemq.client2.mqtt.datatypes.MqttClientIdentifier;
+import com.hivemq.client2.mqtt.lifecycle.MqttAutoReconnect;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedListener;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedListener;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConnectionConfig;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
 import io.netty.channel.EventLoop;
 import io.netty.handler.ssl.SslContext;
 import org.jetbrains.annotations.NotNull;
@@ -51,12 +51,12 @@ public class MqttClientConfig implements Mqtt5ClientConfig {
 
     private final @NotNull MqttVersion mqttVersion;
     private volatile @NotNull MqttClientIdentifierImpl clientIdentifier;
-    private final @NotNull MqttClientTransportConfigImpl transportConfig;
-    private final @NotNull MqttClientExecutorConfigImpl executorConfig;
-    private final @NotNull MqttClientAdvancedConfig advancedConfig;
+    private final @NotNull MqttTransportConfigImpl transportConfig;
+    private final @NotNull MqttExecutorConfigImpl executorConfig;
+    private final @NotNull MqttAdvancedConfig advancedConfig;
     private final @NotNull ConnectDefaults connectDefaults;
-    private final @NotNull ImmutableList<MqttClientConnectedListener> connectedListeners;
-    private final @NotNull ImmutableList<MqttClientDisconnectedListener> disconnectedListeners;
+    private final @NotNull ImmutableList<MqttConnectedListener> connectedListeners;
+    private final @NotNull ImmutableList<MqttDisconnectedListener> disconnectedListeners;
 
     private final @NotNull ClientComponent clientComponent;
 
@@ -66,7 +66,7 @@ public class MqttClientConfig implements Mqtt5ClientConfig {
 
     private final @NotNull AtomicReference<@NotNull MqttClientState> state;
     private volatile @Nullable MqttClientConnectionConfig connectionConfig;
-    private @NotNull MqttClientTransportConfigImpl currentTransportConfig;
+    private @NotNull MqttTransportConfigImpl currentTransportConfig;
     private @Nullable SslContext currentSslContext;
     private boolean resubscribeIfSessionExpired;
     private boolean republishIfSessionExpired;
@@ -74,12 +74,12 @@ public class MqttClientConfig implements Mqtt5ClientConfig {
     public MqttClientConfig(
             final @NotNull MqttVersion mqttVersion,
             final @NotNull MqttClientIdentifierImpl clientIdentifier,
-            final @NotNull MqttClientTransportConfigImpl transportConfig,
-            final @NotNull MqttClientExecutorConfigImpl executorConfig,
-            final @NotNull MqttClientAdvancedConfig advancedConfig,
+            final @NotNull MqttTransportConfigImpl transportConfig,
+            final @NotNull MqttExecutorConfigImpl executorConfig,
+            final @NotNull MqttAdvancedConfig advancedConfig,
             final @NotNull ConnectDefaults connectDefaults,
-            final @NotNull ImmutableList<MqttClientConnectedListener> connectedListeners,
-            final @NotNull ImmutableList<MqttClientDisconnectedListener> disconnectedListeners) {
+            final @NotNull ImmutableList<MqttConnectedListener> connectedListeners,
+            final @NotNull ImmutableList<MqttDisconnectedListener> disconnectedListeners) {
 
         this.mqttVersion = mqttVersion;
         this.clientIdentifier = clientIdentifier;
@@ -102,7 +102,7 @@ public MqttClientConfig(
     }
 
     @Override
-    public @NotNull Optional<MqttClientIdentifier> getClientIdentifier() {
+    public @NotNull Optional<MqttClientIdentifier> getIdentifier() {
         return (clientIdentifier == MqttClientIdentifierImpl.REQUEST_CLIENT_IDENTIFIER_FROM_SERVER) ? Optional.empty() :
                 Optional.of(clientIdentifier);
     }
@@ -116,17 +116,17 @@ public void setClientIdentifier(final @NotNull MqttClientIdentifierImpl clientId
     }
 
     @Override
-    public @NotNull MqttClientTransportConfigImpl getTransportConfig() {
+    public @NotNull MqttTransportConfigImpl getTransportConfig() {
         return transportConfig;
     }
 
     @Override
-    public @NotNull MqttClientExecutorConfigImpl getExecutorConfig() {
+    public @NotNull MqttExecutorConfigImpl getExecutorConfig() {
         return executorConfig;
     }
 
     @Override
-    public @NotNull MqttClientAdvancedConfig getAdvancedConfig() {
+    public @NotNull MqttAdvancedConfig getAdvancedConfig() {
         return advancedConfig;
     }
 
@@ -150,22 +150,22 @@ public void setClientIdentifier(final @NotNull MqttClientIdentifierImpl clientId
     }
 
     @Override
-    public @NotNull Optional<MqttClientAutoReconnect> getAutomaticReconnect() {
-        for (final MqttClientDisconnectedListener disconnectedListener : disconnectedListeners) {
-            if (disconnectedListener instanceof MqttClientAutoReconnect) {
-                return Optional.of((MqttClientAutoReconnect) disconnectedListener);
+    public @NotNull Optional<MqttAutoReconnect> getAutomaticReconnect() {
+        for (final MqttDisconnectedListener disconnectedListener : disconnectedListeners) {
+            if (disconnectedListener instanceof MqttAutoReconnect) {
+                return Optional.of((MqttAutoReconnect) disconnectedListener);
             }
         }
         return Optional.empty();
     }
 
     @Override
-    public @NotNull ImmutableList<MqttClientConnectedListener> getConnectedListeners() {
+    public @NotNull ImmutableList<MqttConnectedListener> getConnectedListeners() {
         return connectedListeners;
     }
 
     @Override
-    public @NotNull ImmutableList<MqttClientDisconnectedListener> getDisconnectedListeners() {
+    public @NotNull ImmutableList<MqttDisconnectedListener> getDisconnectedListeners() {
         return disconnectedListeners;
     }
 
@@ -236,11 +236,11 @@ public void setConnectionConfig(final @Nullable MqttClientConnectionConfig conne
         this.connectionConfig = connectionConfig;
     }
 
-    public @NotNull MqttClientTransportConfigImpl getCurrentTransportConfig() {
+    public @NotNull MqttTransportConfigImpl getCurrentTransportConfig() {
         return currentTransportConfig;
     }
 
-    public void setCurrentTransportConfig(final @NotNull MqttClientTransportConfigImpl currentTransportConfig) {
+    public void setCurrentTransportConfig(final @NotNull MqttTransportConfigImpl currentTransportConfig) {
         if (!this.currentTransportConfig.equals(currentTransportConfig)) {
             this.currentTransportConfig = currentTransportConfig;
             currentSslContext = null;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientConnectionConfig.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttClientConnectionConfig.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttClientConnectionConfig.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttClientConnectionConfig.java
index b48f1c175..80a2d144e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientConnectionConfig.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttClientConnectionConfig.java
@@ -14,18 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
-
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttTopicAliasAutoMapping;
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttTopicAliasMapping;
-import com.hivemq.client.internal.util.UnsignedDataTypes;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientConnectionConfig;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConnectionConfig;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+package com.hivemq.client2.internal.mqtt;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttTopicAliasAutoMapping;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttTopicAliasMapping;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientConnectionConfig;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConnectionConfig;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
 import io.netty.channel.Channel;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.util.Optional;
 
@@ -48,37 +50,37 @@ public class MqttClientConnectionConfig
     private static final int FLAG_CLEAN_START = 1 << 8;
     private static final int FLAG_CLEAN_STOP = 1 << 9;
 
-    private final @NotNull MqttClientTransportConfigImpl transportConfig;
-    private final short keepAlive;
-    private volatile int sessionExpiryInterval;
+    private final @NotNull MqttTransportConfigImpl transportConfig;
+    private final /*unsigned*/ short keepAlive;
+    private volatile /*unsigned*/ int sessionExpiryInterval;
     private final @Nullable Mqtt5EnhancedAuthMechanism enhancedAuthMechanism;
-    private final short receiveMaximum;
-    private final int maximumPacketSize;
-    private final short topicAliasMaximum;
-    private final short sendMaximum;
-    private final int sendMaximumPacketSize;
+    private final /*unsigned*/ short receiveMaximum;
+    private final @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int maximumPacketSize;
+    private final /*unsigned*/ short topicAliasMaximum;
+    private final /*unsigned*/ short sendMaximum;
+    private final @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int sendMaximumPacketSize;
     private final @Nullable MqttTopicAliasMapping sendTopicAliasMapping;
     private final @NotNull MqttQos maximumQos;
     private final @NotNull Channel channel;
     private final int flags;
 
     public MqttClientConnectionConfig(
-            final @NotNull MqttClientTransportConfigImpl transportConfig,
-            final int keepAlive,
+            final @NotNull MqttTransportConfigImpl transportConfig,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int keepAlive,
             final boolean cleanStart,
             final boolean cleanStop,
-            final long sessionExpiryInterval,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval,
             final boolean hasSimpleAuth,
             final boolean hasWillPublish,
             final @Nullable Mqtt5EnhancedAuthMechanism enhancedAuthMechanism,
-            final int receiveMaximum,
-            final int maximumPacketSize,
-            final int topicAliasMaximum,
+            final @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int receiveMaximum,
+            final @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int maximumPacketSize,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int topicAliasMaximum,
             final boolean problemInformationRequested,
             final boolean responseInformationRequested,
-            final int sendMaximum,
-            final int sendMaximumPacketSize,
-            final int sendTopicAliasMaximum,
+            final @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int sendMaximum,
+            final @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int sendMaximumPacketSize,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int sendTopicAliasMaximum,
             final @NotNull MqttQos maximumQos,
             final boolean retainAvailable,
             final boolean wildcardSubscriptionAvailable,
@@ -135,12 +137,12 @@ public MqttClientConnectionConfig(
     }
 
     @Override
-    public @NotNull MqttClientTransportConfigImpl getTransportConfig() {
+    public @NotNull MqttTransportConfigImpl getTransportConfig() {
         return transportConfig;
     }
 
     @Override
-    public int getKeepAlive() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getKeepAlive() {
         return keepAlive & UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE;
     }
 
@@ -153,11 +155,13 @@ public boolean isCleanStop() {
     }
 
     @Override
-    public long getSessionExpiryInterval() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long getSessionExpiryInterval() {
         return sessionExpiryInterval & UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE;
     }
 
-    public void setSessionExpiryInterval(final long sessionExpiryInterval) {
+    public void setSessionExpiryInterval(
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval) {
+
         this.sessionExpiryInterval = (int) sessionExpiryInterval;
     }
 
@@ -191,17 +195,17 @@ public boolean hasWillPublish() {
     }
 
     @Override
-    public int getReceiveMaximum() {
+    public @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getReceiveMaximum() {
         return receiveMaximum & UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE;
     }
 
     @Override
-    public int getMaximumPacketSize() {
+    public @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int getMaximumPacketSize() {
         return maximumPacketSize;
     }
 
     @Override
-    public int getTopicAliasMaximum() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getTopicAliasMaximum() {
         return topicAliasMaximum & UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE;
     }
 
@@ -216,17 +220,17 @@ public boolean isResponseInformationRequested() {
     }
 
     @Override
-    public int getSendMaximum() {
+    public @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getSendMaximum() {
         return sendMaximum & UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE;
     }
 
     @Override
-    public int getSendMaximumPacketSize() {
+    public @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int getSendMaximumPacketSize() {
         return sendMaximumPacketSize;
     }
 
     @Override
-    public int getSendTopicAliasMaximum() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getSendTopicAliasMaximum() {
         return (sendTopicAliasMapping == null) ? 0 : sendTopicAliasMapping.getTopicAliasMaximum();
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientExecutorConfigImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttExecutorConfigImpl.java
similarity index 71%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttClientExecutorConfigImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttExecutorConfigImpl.java
index 4f1b290f9..91b5986b2 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientExecutorConfigImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttExecutorConfigImpl.java
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
-import com.hivemq.client.mqtt.MqttClientExecutorConfig;
-import io.reactivex.Scheduler;
+import com.hivemq.client2.mqtt.MqttExecutorConfig;
+import io.reactivex.rxjava3.core.Scheduler;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.Objects;
 import java.util.Optional;
@@ -29,19 +31,20 @@
 /**
  * @author Silvio Giebl
  */
-public class MqttClientExecutorConfigImpl implements MqttClientExecutorConfig {
+@Unmodifiable
+public class MqttExecutorConfigImpl implements MqttExecutorConfig {
 
     public static final int DEFAULT_NETTY_THREADS = 0;
-    public static final @NotNull MqttClientExecutorConfigImpl DEFAULT =
-            new MqttClientExecutorConfigImpl(null, DEFAULT_NETTY_THREADS, DEFAULT_APPLICATION_SCHEDULER);
+    public static final @NotNull MqttExecutorConfigImpl DEFAULT =
+            new MqttExecutorConfigImpl(null, DEFAULT_NETTY_THREADS, DEFAULT_APPLICATION_SCHEDULER);
 
     private final @Nullable Executor nettyExecutor;
-    private final int nettyThreads;
+    private final @Range(from = 0, to = Integer.MAX_VALUE) int nettyThreads;
     private final @NotNull Scheduler applicationScheduler;
 
-    MqttClientExecutorConfigImpl(
+    MqttExecutorConfigImpl(
             final @Nullable Executor nettyExecutor,
-            final int nettyThreads,
+            final @Range(from = 0, to = Integer.MAX_VALUE) int nettyThreads,
             final @NotNull Scheduler applicationScheduler) {
 
         this.nettyExecutor = nettyExecutor;
@@ -63,7 +66,7 @@ public class MqttClientExecutorConfigImpl implements MqttClientExecutorConfig {
         return (nettyThreads == DEFAULT_NETTY_THREADS) ? OptionalInt.empty() : OptionalInt.of(nettyThreads);
     }
 
-    public int getRawNettyThreads() {
+    public @Range(from = 0, to = Integer.MAX_VALUE) int getRawNettyThreads() {
         return nettyThreads;
     }
 
@@ -73,8 +76,8 @@ public int getRawNettyThreads() {
     }
 
     @Override
-    public MqttClientExecutorConfigImplBuilder.@NotNull Default extend() {
-        return new MqttClientExecutorConfigImplBuilder.Default(this);
+    public MqttExecutorConfigImplBuilder.@NotNull Default extend() {
+        return new MqttExecutorConfigImplBuilder.Default(this);
     }
 
     @Override
@@ -82,10 +85,10 @@ public boolean equals(final @Nullable Object o) {
         if (this == o) {
             return true;
         }
-        if (!(o instanceof MqttClientExecutorConfigImpl)) {
+        if (!(o instanceof MqttExecutorConfigImpl)) {
             return false;
         }
-        final MqttClientExecutorConfigImpl that = (MqttClientExecutorConfigImpl) o;
+        final MqttExecutorConfigImpl that = (MqttExecutorConfigImpl) o;
 
         return Objects.equals(nettyExecutor, that.nettyExecutor) && (nettyThreads == that.nettyThreads) &&
                 applicationScheduler.equals(that.applicationScheduler);
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientExecutorConfigImplBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttExecutorConfigImplBuilder.java
similarity index 61%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttClientExecutorConfigImplBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttExecutorConfigImplBuilder.java
index 6c68726af..0053293a7 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientExecutorConfigImplBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttExecutorConfigImplBuilder.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttClientExecutorConfigBuilder;
-import io.reactivex.Scheduler;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttExecutorConfigBuilder;
+import io.reactivex.rxjava3.core.Scheduler;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.util.concurrent.Executor;
 import java.util.function.Function;
@@ -28,15 +29,15 @@
 /**
  * @author Silvio Giebl
  */
-public abstract class MqttClientExecutorConfigImplBuilder<B extends MqttClientExecutorConfigImplBuilder<B>> {
+public abstract class MqttExecutorConfigImplBuilder<B extends MqttExecutorConfigImplBuilder<B>> {
 
     private @Nullable Executor nettyExecutor;
-    private int nettyThreads = MqttClientExecutorConfigImpl.DEFAULT_NETTY_THREADS;
-    private @NotNull Scheduler applicationScheduler = MqttClientExecutorConfigImpl.DEFAULT_APPLICATION_SCHEDULER;
+    private @Range(from = 0, to = Integer.MAX_VALUE) int nettyThreads = MqttExecutorConfigImpl.DEFAULT_NETTY_THREADS;
+    private @NotNull Scheduler applicationScheduler = MqttExecutorConfigImpl.DEFAULT_APPLICATION_SCHEDULER;
 
-    MqttClientExecutorConfigImplBuilder() {}
+    MqttExecutorConfigImplBuilder() {}
 
-    MqttClientExecutorConfigImplBuilder(final @NotNull MqttClientExecutorConfigImpl executorConfig) {
+    MqttExecutorConfigImplBuilder(final @NotNull MqttExecutorConfigImpl executorConfig) {
         nettyExecutor = executorConfig.getRawNettyExecutor();
         nettyThreads = executorConfig.getRawNettyThreads();
         applicationScheduler = executorConfig.getApplicationScheduler();
@@ -63,16 +64,15 @@ public abstract class MqttClientExecutorConfigImplBuilder<B extends MqttClientEx
         return self();
     }
 
-    public @NotNull MqttClientExecutorConfigImpl build() {
-        return new MqttClientExecutorConfigImpl(nettyExecutor, nettyThreads, applicationScheduler);
+    public @NotNull MqttExecutorConfigImpl build() {
+        return new MqttExecutorConfigImpl(nettyExecutor, nettyThreads, applicationScheduler);
     }
 
-    public static class Default extends MqttClientExecutorConfigImplBuilder<Default>
-            implements MqttClientExecutorConfigBuilder {
+    public static class Default extends MqttExecutorConfigImplBuilder<Default> implements MqttExecutorConfigBuilder {
 
         public Default() {}
 
-        Default(final @NotNull MqttClientExecutorConfigImpl executorConfig) {
+        Default(final @NotNull MqttExecutorConfigImpl executorConfig) {
             super(executorConfig);
         }
 
@@ -82,14 +82,14 @@ public Default() {}
         }
     }
 
-    public static class Nested<P> extends MqttClientExecutorConfigImplBuilder<Nested<P>>
-            implements MqttClientExecutorConfigBuilder.Nested<P> {
+    public static class Nested<P> extends MqttExecutorConfigImplBuilder<Nested<P>>
+            implements MqttExecutorConfigBuilder.Nested<P> {
 
-        private final @NotNull Function<? super MqttClientExecutorConfigImpl, P> parentConsumer;
+        private final @NotNull Function<? super MqttExecutorConfigImpl, P> parentConsumer;
 
         Nested(
-                final @NotNull MqttClientExecutorConfigImpl executorConfig,
-                final @NotNull Function<? super MqttClientExecutorConfigImpl, P> parentConsumer) {
+                final @NotNull MqttExecutorConfigImpl executorConfig,
+                final @NotNull Function<? super MqttExecutorConfigImpl, P> parentConsumer) {
 
             super(executorConfig);
             this.parentConsumer = parentConsumer;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttProxyConfigImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttProxyConfigImpl.java
similarity index 86%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttProxyConfigImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttProxyConfigImpl.java
index 080c3fb0f..017619572 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttProxyConfigImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttProxyConfigImpl.java
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
-import com.hivemq.client.mqtt.MqttProxyConfig;
-import com.hivemq.client.mqtt.MqttProxyProtocol;
+import com.hivemq.client2.mqtt.MqttProxyConfig;
+import com.hivemq.client2.mqtt.MqttProxyProtocol;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.net.InetSocketAddress;
 import java.util.Objects;
@@ -28,20 +30,21 @@
 /**
  * @author Silvio Giebl
  */
+@Unmodifiable
 public class MqttProxyConfigImpl implements MqttProxyConfig {
 
     private final @NotNull MqttProxyProtocol protocol;
     private final @NotNull InetSocketAddress address;
     private final @Nullable String username;
     private final @Nullable String password;
-    private final int handshakeTimeoutMs;
+    private final @Range(from = 0, to = Integer.MAX_VALUE) int handshakeTimeoutMs;
 
     MqttProxyConfigImpl(
             final @NotNull MqttProxyProtocol protocol,
             final @NotNull InetSocketAddress address,
             final @Nullable String username,
             final @Nullable String password,
-            final int handshakeTimeoutMs) {
+            final @Range(from = 0, to = Integer.MAX_VALUE) int handshakeTimeoutMs) {
 
         this.protocol = protocol;
         this.address = address;
@@ -79,7 +82,7 @@ public class MqttProxyConfigImpl implements MqttProxyConfig {
     }
 
     @Override
-    public int getHandshakeTimeoutMs() {
+    public @Range(from = 0, to = Integer.MAX_VALUE) int getHandshakeTimeoutMs() {
         return handshakeTimeoutMs;
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttProxyConfigImplBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttProxyConfigImplBuilder.java
similarity index 92%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttProxyConfigImplBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttProxyConfigImplBuilder.java
index d074c9e06..b9bf2cde5 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttProxyConfigImplBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttProxyConfigImplBuilder.java
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.InetSocketAddressUtil;
-import com.hivemq.client.mqtt.MqttProxyConfigBuilder;
-import com.hivemq.client.mqtt.MqttProxyProtocol;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.InetSocketAddressUtil;
+import com.hivemq.client2.mqtt.MqttProxyConfigBuilder;
+import com.hivemq.client2.mqtt.MqttProxyProtocol;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
@@ -39,7 +40,8 @@ public abstract class MqttProxyConfigImplBuilder<B extends MqttProxyConfigImplBu
     private int port = -1;
     private @Nullable String username;
     private @Nullable String password;
-    private int handshakeTimeoutMs = MqttProxyConfigImpl.DEFAULT_HANDSHAKE_TIMEOUT_MS;
+    private @Range(from = 0, to = Integer.MAX_VALUE) int handshakeTimeoutMs =
+            MqttProxyConfigImpl.DEFAULT_HANDSHAKE_TIMEOUT_MS;
 
     MqttProxyConfigImplBuilder() {}
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttRxClient.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttRxClient.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttRxClient.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttRxClient.java
index c9fa963ea..30ce1f783 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttRxClient.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttRxClient.java
@@ -14,49 +14,50 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
-
-import com.hivemq.client.internal.mqtt.handler.auth.MqttReAuthCompletable;
-import com.hivemq.client.internal.mqtt.handler.connect.MqttConnAckSingle;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectCompletable;
-import com.hivemq.client.internal.mqtt.handler.publish.incoming.MqttGlobalIncomingPublishFlowable;
-import com.hivemq.client.internal.mqtt.handler.publish.incoming.MqttSubscribedPublishFlowable;
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttAckFlowable;
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttAckSingle;
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttAckSingleFlowable;
-import com.hivemq.client.internal.mqtt.handler.subscribe.MqttSubAckSingle;
-import com.hivemq.client.internal.mqtt.handler.subscribe.MqttUnsubAckSingle;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectBuilder;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribeBuilder;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribeBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5RxClient;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
-import com.hivemq.client.rx.FlowableWithSingle;
-import io.reactivex.Completable;
-import io.reactivex.Flowable;
-import io.reactivex.Scheduler;
-import io.reactivex.Single;
-import io.reactivex.functions.Function;
-import io.reactivex.internal.fuseable.ScalarCallable;
+package com.hivemq.client2.internal.mqtt;
+
+import com.hivemq.client2.internal.mqtt.handler.auth.MqttReAuthCompletable;
+import com.hivemq.client2.internal.mqtt.handler.connect.MqttConnAckSingle;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectCompletable;
+import com.hivemq.client2.internal.mqtt.handler.publish.incoming.MqttGlobalIncomingPublishFlowable;
+import com.hivemq.client2.internal.mqtt.handler.publish.incoming.MqttSubscribedPublishFlowable;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttAckFlowable;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttAckSingle;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttAckSingleFlowable;
+import com.hivemq.client2.internal.mqtt.handler.subscribe.MqttSubAckSingle;
+import com.hivemq.client2.internal.mqtt.handler.subscribe.MqttUnsubAckSingle;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectBuilder;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribeBuilder;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribeBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5RxClient;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+import com.hivemq.client2.rx.FlowableWithSingle;
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.Scheduler;
+import io.reactivex.rxjava3.core.Single;
+import io.reactivex.rxjava3.functions.Function;
+import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.reactivestreams.Publisher;
 
 /**
  * @author Silvio Giebl
@@ -112,18 +113,6 @@ public MqttRxClient(final @NotNull MqttClientConfig clientConfig) {
         return new MqttSubscribeBuilder.Nested<>(this::subscribe);
     }
 
-    @Override
-    public @NotNull FlowableWithSingle<Mqtt5Publish, Mqtt5SubAck> subscribeStream(
-            final @NotNull Mqtt5Subscribe subscribe) {
-
-        return subscribePublishes(subscribe);
-    }
-
-    @Override
-    public MqttSubscribeBuilder.@NotNull Nested<FlowableWithSingle<Mqtt5Publish, Mqtt5SubAck>> subscribeStreamWith() {
-        return new MqttSubscribeBuilder.Nested<>(this::subscribeStream);
-    }
-
     @Override
     public @NotNull FlowableWithSingle<Mqtt5Publish, Mqtt5SubAck> subscribePublishes(
             final @Nullable Mqtt5Subscribe subscribe) {
@@ -141,7 +130,7 @@ public MqttRxClient(final @NotNull MqttClientConfig clientConfig) {
     @NotNull FlowableWithSingle<Mqtt5Publish, Mqtt5SubAck> subscribePublishes(
             final @NotNull MqttSubscribe subscribe, final boolean manualAcknowledgement) {
 
-        return subscribePublishesUnsafe(subscribe, manualAcknowledgement).observeOnBoth(
+        return subscribePublishesUnsafe(subscribe, manualAcknowledgement).observeBothOn(
                 clientConfig.getExecutorConfig().getApplicationScheduler(), true);
     }
 
@@ -204,19 +193,19 @@ public MqttRxClient(final @NotNull MqttClientConfig clientConfig) {
     }
 
     @Override
-    public @NotNull Flowable<Mqtt5PublishResult> publish(final @Nullable Flowable<Mqtt5Publish> publishFlowable) {
-        Checks.notNull(publishFlowable, "Publish flowable");
+    public @NotNull Flowable<Mqtt5PublishResult> publish(final @NotNull Publisher<Mqtt5Publish> publisher) {
+        Checks.notNull(publisher, "Publisher");
 
-        return publish(publishFlowable, PUBLISH_MAPPER);
+        return publish(publisher, PUBLISH_MAPPER);
     }
 
     public <P> @NotNull Flowable<Mqtt5PublishResult> publish(
-            final @NotNull Flowable<P> publishFlowable, final @NotNull Function<P, MqttPublish> publishMapper) {
+            final @NotNull Publisher<P> publisher, final @NotNull Function<P, MqttPublish> publishMapper) {
 
         final Scheduler applicationScheduler = clientConfig.getExecutorConfig().getApplicationScheduler();
-        if (publishFlowable instanceof ScalarCallable) {
+        if (publisher instanceof ScalarSupplier) {
             //noinspection unchecked
-            final P publish = ((ScalarCallable<P>) publishFlowable).call();
+            final P publish = ((ScalarSupplier<P>) publisher).get();
             if (publish == null) {
                 return Flowable.empty();
             }
@@ -229,7 +218,8 @@ public MqttRxClient(final @NotNull MqttClientConfig clientConfig) {
             return new MqttAckSingleFlowable(clientConfig, mqttPublish).observeOn(applicationScheduler, true);
         }
         return new MqttAckFlowable(
-                clientConfig, publishFlowable.subscribeOn(applicationScheduler).map(publishMapper)).observeOn(
+                clientConfig,
+                Flowable.fromPublisher(publisher).subscribeOn(applicationScheduler).map(publishMapper)).observeOn(
                 applicationScheduler, true);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttRxClientBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttRxClientBuilder.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttRxClientBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttRxClientBuilder.java
index f1f1ed2d0..4f3961ba8 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttRxClientBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttRxClientBuilder.java
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
-
-import com.hivemq.client.internal.mqtt.advanced.MqttClientAdvancedConfig;
-import com.hivemq.client.internal.mqtt.advanced.MqttClientAdvancedConfigBuilder;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuthBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttVersion;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientBuilder;
-import com.hivemq.client.mqtt.mqtt5.advanced.Mqtt5ClientAdvancedConfig;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
+package com.hivemq.client2.internal.mqtt;
+
+import com.hivemq.client2.internal.mqtt.advanced.MqttAdvancedConfig;
+import com.hivemq.client2.internal.mqtt.advanced.MqttAdvancedConfigBuilder;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuthBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttVersion;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientBuilder;
+import com.hivemq.client2.mqtt.mqtt5.advanced.Mqtt5AdvancedConfig;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -38,7 +38,7 @@
  */
 public class MqttRxClientBuilder extends MqttRxClientBuilderBase<MqttRxClientBuilder> implements Mqtt5ClientBuilder {
 
-    private @NotNull MqttClientAdvancedConfig advancedConfig = MqttClientAdvancedConfig.DEFAULT;
+    private @NotNull MqttAdvancedConfig advancedConfig = MqttAdvancedConfig.DEFAULT;
     private @Nullable MqttSimpleAuth simpleAuth;
     private @Nullable Mqtt5EnhancedAuthMechanism enhancedAuthMechanism;
     private @Nullable MqttWillPublish willPublish;
@@ -55,14 +55,14 @@ public MqttRxClientBuilder() {}
     }
 
     @Override
-    public @NotNull MqttRxClientBuilder advancedConfig(final @NotNull Mqtt5ClientAdvancedConfig advancedConfig) {
-        this.advancedConfig = Checks.notImplemented(advancedConfig, MqttClientAdvancedConfig.class, "Advanced config");
+    public @NotNull MqttRxClientBuilder advancedConfig(final @NotNull Mqtt5AdvancedConfig advancedConfig) {
+        this.advancedConfig = Checks.notImplemented(advancedConfig, MqttAdvancedConfig.class, "Advanced config");
         return this;
     }
 
     @Override
-    public MqttClientAdvancedConfigBuilder.@NotNull Nested<MqttRxClientBuilder> advancedConfig() {
-        return new MqttClientAdvancedConfigBuilder.Nested<>(advancedConfig, this::advancedConfig);
+    public MqttAdvancedConfigBuilder.@NotNull Nested<MqttRxClientBuilder> advancedConfigWith() {
+        return new MqttAdvancedConfigBuilder.Nested<>(advancedConfig, this::advancedConfig);
     }
 
     @Override
@@ -72,7 +72,7 @@ public MqttRxClientBuilder() {}
     }
 
     @Override
-    public MqttSimpleAuthBuilder.@NotNull Nested<MqttRxClientBuilder> simpleAuth() {
+    public MqttSimpleAuthBuilder.@NotNull Nested<MqttRxClientBuilder> simpleAuthWith() {
         return new MqttSimpleAuthBuilder.Nested<>(this::simpleAuth);
     }
 
@@ -90,7 +90,7 @@ public MqttRxClientBuilder() {}
     }
 
     @Override
-    public MqttPublishBuilder.@NotNull WillNested<MqttRxClientBuilder> willPublish() {
+    public MqttPublishBuilder.@NotNull WillNested<MqttRxClientBuilder> willPublishWith() {
         return new MqttPublishBuilder.WillNested<>(this::willPublish);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttRxClientBuilderBase.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttRxClientBuilderBase.java
similarity index 53%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttRxClientBuilderBase.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttRxClientBuilderBase.java
index 0fd42b948..1d766c880 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttRxClientBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttRxClientBuilderBase.java
@@ -14,40 +14,41 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
-
-import com.hivemq.client.internal.mqtt.advanced.MqttClientAdvancedConfig;
-import com.hivemq.client.internal.mqtt.datatypes.MqttClientIdentifierImpl;
-import com.hivemq.client.internal.mqtt.lifecycle.MqttClientAutoReconnectImpl;
-import com.hivemq.client.internal.mqtt.lifecycle.MqttClientAutoReconnectImplBuilder;
-import com.hivemq.client.internal.mqtt.mqtt3.Mqtt3RxClientViewBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.*;
-import com.hivemq.client.mqtt.datatypes.MqttClientIdentifier;
-import com.hivemq.client.mqtt.lifecycle.MqttClientAutoReconnect;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedListener;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener;
+package com.hivemq.client2.internal.mqtt;
+
+import com.hivemq.client2.internal.mqtt.advanced.MqttAdvancedConfig;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttClientIdentifierImpl;
+import com.hivemq.client2.internal.mqtt.lifecycle.MqttAutoReconnectImpl;
+import com.hivemq.client2.internal.mqtt.lifecycle.MqttAutoReconnectImplBuilder;
+import com.hivemq.client2.internal.mqtt.mqtt3.Mqtt3RxClientViewBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.*;
+import com.hivemq.client2.mqtt.datatypes.MqttClientIdentifier;
+import com.hivemq.client2.mqtt.lifecycle.MqttAutoReconnect;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedListener;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedListener;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @author Silvio Giebl
  */
 public abstract class MqttRxClientBuilderBase<B extends MqttRxClientBuilderBase<B>>
-        extends MqttClientTransportConfigImplBuilder<B> {
+        extends MqttTransportConfigImplBuilder<B> {
 
     private @NotNull MqttClientIdentifierImpl identifier =
             MqttClientIdentifierImpl.REQUEST_CLIENT_IDENTIFIER_FROM_SERVER;
-    private @Nullable MqttClientTransportConfigImpl transportConfig = MqttClientTransportConfigImpl.DEFAULT;
-    private @NotNull MqttClientExecutorConfigImpl executorConfig = MqttClientExecutorConfigImpl.DEFAULT;
-    private @Nullable MqttClientAutoReconnectImpl autoReconnect;
-    private ImmutableList.@Nullable Builder<MqttClientConnectedListener> connectedListenersBuilder;
-    private ImmutableList.@Nullable Builder<MqttClientDisconnectedListener> disconnectedListenersBuilder;
+    private @Nullable MqttTransportConfigImpl transportConfig = MqttTransportConfigImpl.DEFAULT;
+    private @NotNull MqttExecutorConfigImpl executorConfig = MqttExecutorConfigImpl.DEFAULT;
+    private @Nullable MqttAutoReconnectImpl autoReconnect;
+    private ImmutableList.@Nullable Builder<MqttConnectedListener> connectedListenersBuilder;
+    private ImmutableList.@Nullable Builder<MqttDisconnectedListener> disconnectedListenersBuilder;
 
     protected MqttRxClientBuilderBase() {}
 
@@ -98,20 +99,43 @@ protected MqttRxClientBuilderBase(final @NotNull MqttRxClientBuilderBase<?> clie
     }
 
     @Override
-    public @NotNull B sslWithDefaultConfig() {
+    public @NotNull B localAddress(final @Nullable InetSocketAddress address) {
         transportConfig = null;
-        return super.sslWithDefaultConfig();
+        return super.localAddress(address);
     }
 
     @Override
-    public @NotNull B sslConfig(final @Nullable MqttClientSslConfig sslConfig) {
-        return super.sslConfig(sslConfig);
+    public @NotNull B localAddress(final @Nullable String address) {
+        transportConfig = null;
+        return super.localAddress(address);
     }
 
     @Override
-    public @NotNull B webSocketWithDefaultConfig() {
+    public @NotNull B localAddress(final @Nullable InetAddress address) {
+        transportConfig = null;
+        return super.localAddress(address);
+    }
+
+    @Override
+    public @NotNull B localPort(final int port) {
+        transportConfig = null;
+        return super.localPort(port);
+    }
+
+    public @NotNull B tls() {
         transportConfig = null;
-        return super.webSocketWithDefaultConfig();
+        return super.tls();
+    }
+
+    @Override
+    public @NotNull B tlsConfig(final @Nullable MqttTlsConfig tlsConfig) {
+        transportConfig = null;
+        return super.tlsConfig(tlsConfig);
+    }
+
+    public @NotNull B webSocket() {
+        transportConfig = null;
+        return super.webSocket();
     }
 
     @Override
@@ -120,43 +144,60 @@ protected MqttRxClientBuilderBase(final @NotNull MqttRxClientBuilderBase<?> clie
         return super.webSocketConfig(webSocketConfig);
     }
 
-    public @NotNull B transportConfig(final @Nullable MqttClientTransportConfig transportConfig) {
+    @Override
+    public @NotNull B proxyConfig(final @Nullable MqttProxyConfig proxyConfig) {
+        transportConfig = null;
+        return super.proxyConfig(proxyConfig);
+    }
+
+    @Override
+    public @NotNull B socketConnectTimeout(final long timeout, final @Nullable TimeUnit timeUnit) {
+        transportConfig = null;
+        return super.socketConnectTimeout(timeout, timeUnit);
+    }
+
+    @Override
+    public @NotNull B mqttConnectTimeout(final long timeout, final @Nullable TimeUnit timeUnit) {
+        transportConfig = null;
+        return super.mqttConnectTimeout(timeout, timeUnit);
+    }
+
+    public @NotNull B transportConfig(final @Nullable MqttTransportConfig transportConfig) {
         this.transportConfig =
-                Checks.notImplemented(transportConfig, MqttClientTransportConfigImpl.class, "Transport config");
+                Checks.notImplemented(transportConfig, MqttTransportConfigImpl.class, "Transport config");
         set(this.transportConfig);
         return self();
     }
 
-    public MqttClientTransportConfigImplBuilder.@NotNull Nested<B> transportConfig() {
-        return new MqttClientTransportConfigImplBuilder.Nested<>(this, this::transportConfig);
+    public MqttTransportConfigImplBuilder.@NotNull Nested<B> transportConfigWith() {
+        return new MqttTransportConfigImplBuilder.Nested<>(this, this::transportConfig);
     }
 
-    public @NotNull B executorConfig(final @Nullable MqttClientExecutorConfig executorConfig) {
-        this.executorConfig =
-                Checks.notImplemented(executorConfig, MqttClientExecutorConfigImpl.class, "Executor config");
+    public @NotNull B executorConfig(final @Nullable MqttExecutorConfig executorConfig) {
+        this.executorConfig = Checks.notImplemented(executorConfig, MqttExecutorConfigImpl.class, "Executor config");
         return self();
     }
 
-    public MqttClientExecutorConfigImplBuilder.@NotNull Nested<B> executorConfig() {
-        return new MqttClientExecutorConfigImplBuilder.Nested<>(executorConfig, this::executorConfig);
+    public MqttExecutorConfigImplBuilder.@NotNull Nested<B> executorConfigWith() {
+        return new MqttExecutorConfigImplBuilder.Nested<>(executorConfig, this::executorConfig);
     }
 
-    public @NotNull B automaticReconnectWithDefaultConfig() {
-        this.autoReconnect = MqttClientAutoReconnectImpl.DEFAULT;
+    public @NotNull B automaticReconnect() {
+        this.autoReconnect = MqttAutoReconnectImpl.DEFAULT;
         return self();
     }
 
-    public @NotNull B automaticReconnect(final @Nullable MqttClientAutoReconnect autoReconnect) {
+    public @NotNull B automaticReconnect(final @Nullable MqttAutoReconnect autoReconnect) {
         this.autoReconnect =
-                Checks.notImplementedOrNull(autoReconnect, MqttClientAutoReconnectImpl.class, "Automatic reconnect");
+                Checks.notImplementedOrNull(autoReconnect, MqttAutoReconnectImpl.class, "Automatic reconnect");
         return self();
     }
 
-    public MqttClientAutoReconnectImplBuilder.@NotNull Nested<B> automaticReconnect() {
-        return new MqttClientAutoReconnectImplBuilder.Nested<>(autoReconnect, this::automaticReconnect);
+    public MqttAutoReconnectImplBuilder.@NotNull Nested<B> automaticReconnectWith() {
+        return new MqttAutoReconnectImplBuilder.Nested<>(autoReconnect, this::automaticReconnect);
     }
 
-    public @NotNull B addConnectedListener(final @Nullable MqttClientConnectedListener connectedListener) {
+    public @NotNull B addConnectedListener(final @Nullable MqttConnectedListener connectedListener) {
         Checks.notNull(connectedListener, "Connected listener");
         if (connectedListenersBuilder == null) {
             connectedListenersBuilder = ImmutableList.builder();
@@ -165,7 +206,7 @@ protected MqttRxClientBuilderBase(final @NotNull MqttRxClientBuilderBase<?> clie
         return self();
     }
 
-    public @NotNull B addDisconnectedListener(final @Nullable MqttClientDisconnectedListener disconnectedListener) {
+    public @NotNull B addDisconnectedListener(final @Nullable MqttDisconnectedListener disconnectedListener) {
         Checks.notNull(disconnectedListener, "Disconnected listener");
         if (disconnectedListenersBuilder == null) {
             disconnectedListenersBuilder = ImmutableList.builder();
@@ -175,21 +216,21 @@ protected MqttRxClientBuilderBase(final @NotNull MqttRxClientBuilderBase<?> clie
     }
 
     @Override
-    @NotNull MqttClientTransportConfigImpl buildTransportConfig() {
+    @NotNull MqttTransportConfigImpl buildTransportConfig() {
         if (transportConfig == null) {
             return super.buildTransportConfig();
         }
         return transportConfig;
     }
 
-    private @NotNull ImmutableList<MqttClientConnectedListener> buildConnectedListeners() {
+    private @NotNull ImmutableList<MqttConnectedListener> buildConnectedListeners() {
         if (connectedListenersBuilder == null) {
             return ImmutableList.of();
         }
         return connectedListenersBuilder.build();
     }
 
-    private @NotNull ImmutableList<MqttClientDisconnectedListener> buildDisconnectedListeners() {
+    private @NotNull ImmutableList<MqttDisconnectedListener> buildDisconnectedListeners() {
         if (disconnectedListenersBuilder == null) {
             if (autoReconnect == null) {
                 return ImmutableList.of();
@@ -199,14 +240,13 @@ protected MqttRxClientBuilderBase(final @NotNull MqttRxClientBuilderBase<?> clie
         if (autoReconnect == null) {
             return disconnectedListenersBuilder.build();
         }
-        return ImmutableList.<MqttClientDisconnectedListener>builder().add(autoReconnect)
-                .addAll(disconnectedListenersBuilder.build())
-                .build();
+        return ImmutableList.<MqttDisconnectedListener>builder(disconnectedListenersBuilder.getSize() + 1).add(
+                autoReconnect).addAll(disconnectedListenersBuilder.build()).build();
     }
 
     protected @NotNull MqttClientConfig buildClientConfig(
             final @NotNull MqttVersion mqttVersion,
-            final @NotNull MqttClientAdvancedConfig advancedConfig,
+            final @NotNull MqttAdvancedConfig advancedConfig,
             final @NotNull MqttClientConfig.ConnectDefaults connectDefaults) {
 
         return new MqttClientConfig(mqttVersion, identifier, buildTransportConfig(), executorConfig, advancedConfig,
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientSslConfigImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttTlsConfigImpl.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttClientSslConfigImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttTlsConfigImpl.java
index d0f02d20a..717fe636e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientSslConfigImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttTlsConfigImpl.java
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.MqttClientSslConfig;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.MqttTlsConfig;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import javax.net.ssl.*;
 import java.util.List;
@@ -30,7 +32,8 @@
  * @author David Katz
  * @author Silvio Giebl
  */
-public class MqttClientSslConfigImpl implements MqttClientSslConfig {
+@Unmodifiable
+public class MqttTlsConfigImpl implements MqttTlsConfig {
 
     static final @Nullable HostnameVerifier DEFAULT_HOSTNAME_VERIFIER;
 
@@ -44,23 +47,22 @@ public class MqttClientSslConfigImpl implements MqttClientSslConfig {
         DEFAULT_HOSTNAME_VERIFIER = hostnameVerifier;
     }
 
-    static final @NotNull MqttClientSslConfigImpl DEFAULT =
-            new MqttClientSslConfigImpl(null, null, null, null, (int) DEFAULT_HANDSHAKE_TIMEOUT_MS,
-                    DEFAULT_HOSTNAME_VERIFIER);
+    static final @NotNull MqttTlsConfigImpl DEFAULT =
+            new MqttTlsConfigImpl(null, null, null, null, DEFAULT_HANDSHAKE_TIMEOUT_MS, DEFAULT_HOSTNAME_VERIFIER);
 
     private final @Nullable KeyManagerFactory keyManagerFactory;
     private final @Nullable TrustManagerFactory trustManagerFactory;
     private final @Nullable ImmutableList<String> cipherSuites;
     private final @Nullable ImmutableList<String> protocols;
-    private final int handshakeTimeoutMs;
+    private final @Range(from = 0, to = Integer.MAX_VALUE) int handshakeTimeoutMs;
     private final @Nullable HostnameVerifier hostnameVerifier;
 
-    MqttClientSslConfigImpl(
+    MqttTlsConfigImpl(
             final @Nullable KeyManagerFactory keyManagerFactory,
             final @Nullable TrustManagerFactory trustManagerFactory,
             final @Nullable ImmutableList<String> cipherSuites,
             final @Nullable ImmutableList<String> protocols,
-            final int handshakeTimeoutMs,
+            final @Range(from = 0, to = Integer.MAX_VALUE) int handshakeTimeoutMs,
             final @Nullable HostnameVerifier hostnameVerifier) {
 
         this.keyManagerFactory = keyManagerFactory;
@@ -108,7 +110,7 @@ public class MqttClientSslConfigImpl implements MqttClientSslConfig {
     }
 
     @Override
-    public long getHandshakeTimeoutMs() {
+    public @Range(from = 0, to = Integer.MAX_VALUE) int getHandshakeTimeoutMs() {
         return handshakeTimeoutMs;
     }
 
@@ -122,8 +124,8 @@ public long getHandshakeTimeoutMs() {
     }
 
     @Override
-    public MqttClientSslConfigImplBuilder.@NotNull Default extend() {
-        return new MqttClientSslConfigImplBuilder.Default(this);
+    public MqttTlsConfigImplBuilder.@NotNull Default extend() {
+        return new MqttTlsConfigImplBuilder.Default(this);
     }
 
     @Override
@@ -131,10 +133,10 @@ public boolean equals(final @Nullable Object o) {
         if (this == o) {
             return true;
         }
-        if (!(o instanceof MqttClientSslConfigImpl)) {
+        if (!(o instanceof MqttTlsConfigImpl)) {
             return false;
         }
-        final MqttClientSslConfigImpl that = (MqttClientSslConfigImpl) o;
+        final MqttTlsConfigImpl that = (MqttTlsConfigImpl) o;
 
         return Objects.equals(keyManagerFactory, that.keyManagerFactory) &&
                 Objects.equals(trustManagerFactory, that.trustManagerFactory) &&
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientSslConfigImplBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttTlsConfigImplBuilder.java
similarity index 61%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttClientSslConfigImplBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttTlsConfigImplBuilder.java
index f5fa63816..6b8b8a2f7 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientSslConfigImplBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttTlsConfigImplBuilder.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.MqttClientSslConfigBuilder;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.MqttTlsConfigBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.KeyManagerFactory;
@@ -32,25 +33,26 @@
 /**
  * @author Silvio Giebl
  */
-public abstract class MqttClientSslConfigImplBuilder<B extends MqttClientSslConfigImplBuilder<B>> {
+public abstract class MqttTlsConfigImplBuilder<B extends MqttTlsConfigImplBuilder<B>> {
 
     private @Nullable KeyManagerFactory keyManagerFactory;
     private @Nullable TrustManagerFactory trustManagerFactory;
     private @Nullable ImmutableList<String> cipherSuites;
     private @Nullable ImmutableList<String> protocols;
-    private int handshakeTimeoutMs = (int) MqttClientSslConfigImpl.DEFAULT_HANDSHAKE_TIMEOUT_MS;
-    private @Nullable HostnameVerifier hostnameVerifier = MqttClientSslConfigImpl.DEFAULT_HOSTNAME_VERIFIER;
-
-    MqttClientSslConfigImplBuilder() {}
-
-    MqttClientSslConfigImplBuilder(final @Nullable MqttClientSslConfigImpl sslConfig) {
-        if (sslConfig != null) {
-            keyManagerFactory = sslConfig.getRawKeyManagerFactory();
-            trustManagerFactory = sslConfig.getRawTrustManagerFactory();
-            cipherSuites = sslConfig.getRawCipherSuites();
-            protocols = sslConfig.getRawProtocols();
-            handshakeTimeoutMs = (int) sslConfig.getHandshakeTimeoutMs();
-            hostnameVerifier = sslConfig.getRawHostnameVerifier();
+    private @Range(from = 0, to = Integer.MAX_VALUE) int handshakeTimeoutMs =
+            MqttTlsConfigImpl.DEFAULT_HANDSHAKE_TIMEOUT_MS;
+    private @Nullable HostnameVerifier hostnameVerifier = MqttTlsConfigImpl.DEFAULT_HOSTNAME_VERIFIER;
+
+    MqttTlsConfigImplBuilder() {}
+
+    MqttTlsConfigImplBuilder(final @Nullable MqttTlsConfigImpl tlsConfig) {
+        if (tlsConfig != null) {
+            keyManagerFactory = tlsConfig.getRawKeyManagerFactory();
+            trustManagerFactory = tlsConfig.getRawTrustManagerFactory();
+            cipherSuites = tlsConfig.getRawCipherSuites();
+            protocols = tlsConfig.getRawProtocols();
+            handshakeTimeoutMs = tlsConfig.getHandshakeTimeoutMs();
+            hostnameVerifier = tlsConfig.getRawHostnameVerifier();
         }
     }
 
@@ -85,21 +87,21 @@ public abstract class MqttClientSslConfigImplBuilder<B extends MqttClientSslConf
 
     public @NotNull B hostnameVerifier(final @Nullable HostnameVerifier hostnameVerifier) {
         this.hostnameVerifier =
-                (hostnameVerifier == null) ? MqttClientSslConfigImpl.DEFAULT_HOSTNAME_VERIFIER : hostnameVerifier;
+                (hostnameVerifier == null) ? MqttTlsConfigImpl.DEFAULT_HOSTNAME_VERIFIER : hostnameVerifier;
         return self();
     }
 
-    public @NotNull MqttClientSslConfigImpl build() {
-        return new MqttClientSslConfigImpl(
+    public @NotNull MqttTlsConfigImpl build() {
+        return new MqttTlsConfigImpl(
                 keyManagerFactory, trustManagerFactory, cipherSuites, protocols, handshakeTimeoutMs, hostnameVerifier);
     }
 
-    public static class Default extends MqttClientSslConfigImplBuilder<Default> implements MqttClientSslConfigBuilder {
+    public static class Default extends MqttTlsConfigImplBuilder<Default> implements MqttTlsConfigBuilder {
 
         public Default() {}
 
-        Default(final @Nullable MqttClientSslConfigImpl sslConfig) {
-            super(sslConfig);
+        Default(final @Nullable MqttTlsConfigImpl tlsConfig) {
+            super(tlsConfig);
         }
 
         @Override
@@ -108,16 +110,16 @@ public Default() {}
         }
     }
 
-    public static class Nested<P> extends MqttClientSslConfigImplBuilder<Nested<P>>
-            implements MqttClientSslConfigBuilder.Nested<P> {
+    public static class Nested<P> extends MqttTlsConfigImplBuilder<Nested<P>>
+            implements MqttTlsConfigBuilder.Nested<P> {
 
-        private final @NotNull Function<? super MqttClientSslConfigImpl, P> parentConsumer;
+        private final @NotNull Function<? super MqttTlsConfigImpl, P> parentConsumer;
 
         Nested(
-                final @Nullable MqttClientSslConfigImpl sslConfig,
-                final @NotNull Function<? super MqttClientSslConfigImpl, P> parentConsumer) {
+                final @Nullable MqttTlsConfigImpl tlsConfig,
+                final @NotNull Function<? super MqttTlsConfigImpl, P> parentConsumer) {
 
-            super(sslConfig);
+            super(tlsConfig);
             this.parentConsumer = parentConsumer;
         }
 
@@ -127,7 +129,7 @@ public static class Nested<P> extends MqttClientSslConfigImplBuilder<Nested<P>>
         }
 
         @Override
-        public @NotNull P applySslConfig() {
+        public @NotNull P applyTlsConfig() {
             return parentConsumer.apply(build());
         }
     }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientTransportConfigImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttTransportConfigImpl.java
similarity index 64%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttClientTransportConfigImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttTransportConfigImpl.java
index fa2489853..3fca7e302 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientTransportConfigImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttTransportConfigImpl.java
@@ -14,12 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
-import com.hivemq.client.internal.util.InetSocketAddressUtil;
-import com.hivemq.client.mqtt.*;
+import com.hivemq.client2.internal.util.InetSocketAddressUtil;
+import com.hivemq.client2.mqtt.MqttProxyConfig;
+import com.hivemq.client2.mqtt.MqttTlsConfig;
+import com.hivemq.client2.mqtt.MqttTransportConfig;
+import com.hivemq.client2.mqtt.MqttWebSocketConfig;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.net.InetSocketAddress;
 import java.util.Objects;
@@ -28,32 +33,33 @@
 /**
  * @author Silvio Giebl
  */
-public class MqttClientTransportConfigImpl implements MqttClientTransportConfig {
+@Unmodifiable
+public class MqttTransportConfigImpl implements MqttTransportConfig {
 
-    public static final @NotNull MqttClientTransportConfigImpl DEFAULT = new MqttClientTransportConfigImpl(
-            InetSocketAddressUtil.create(MqttClient.DEFAULT_SERVER_HOST, MqttClient.DEFAULT_SERVER_PORT), null, null,
-            null, null, DEFAULT_SOCKET_CONNECT_TIMEOUT_MS, DEFAULT_MQTT_CONNECT_TIMEOUT_MS);
+    public static final @NotNull MqttTransportConfigImpl DEFAULT =
+            new MqttTransportConfigImpl(InetSocketAddressUtil.create(DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT), null,
+                    null, null, null, DEFAULT_SOCKET_CONNECT_TIMEOUT_MS, DEFAULT_MQTT_CONNECT_TIMEOUT_MS);
 
     private final @NotNull InetSocketAddress serverAddress;
     private final @Nullable InetSocketAddress localAddress;
-    private final @Nullable MqttClientSslConfigImpl sslConfig;
+    private final @Nullable MqttTlsConfigImpl tlsConfig;
     private final @Nullable MqttWebSocketConfigImpl webSocketConfig;
     private final @Nullable MqttProxyConfigImpl proxyConfig;
-    private final int socketConnectTimeoutMs;
-    private final int mqttConnectTimeoutMs;
+    private final @Range(from = 0, to = Integer.MAX_VALUE) int socketConnectTimeoutMs;
+    private final @Range(from = 0, to = Integer.MAX_VALUE) int mqttConnectTimeoutMs;
 
-    MqttClientTransportConfigImpl(
+    MqttTransportConfigImpl(
             final @NotNull InetSocketAddress serverAddress,
             final @Nullable InetSocketAddress localAddress,
-            final @Nullable MqttClientSslConfigImpl sslConfig,
+            final @Nullable MqttTlsConfigImpl tlsConfig,
             final @Nullable MqttWebSocketConfigImpl webSocketConfig,
             final @Nullable MqttProxyConfigImpl proxyConfig,
-            final int socketConnectTimeoutMs,
-            final int mqttConnectTimeoutMs) {
+            final @Range(from = 0, to = Integer.MAX_VALUE) int socketConnectTimeoutMs,
+            final @Range(from = 0, to = Integer.MAX_VALUE) int mqttConnectTimeoutMs) {
 
         this.serverAddress = serverAddress;
         this.localAddress = localAddress;
-        this.sslConfig = sslConfig;
+        this.tlsConfig = tlsConfig;
         this.webSocketConfig = webSocketConfig;
         this.proxyConfig = proxyConfig;
         this.socketConnectTimeoutMs = socketConnectTimeoutMs;
@@ -79,12 +85,12 @@ public class MqttClientTransportConfigImpl implements MqttClientTransportConfig
     }
 
     @Override
-    public @NotNull Optional<MqttClientSslConfig> getSslConfig() {
-        return Optional.ofNullable(sslConfig);
+    public @NotNull Optional<MqttTlsConfig> getTlsConfig() {
+        return Optional.ofNullable(tlsConfig);
     }
 
-    public @Nullable MqttClientSslConfigImpl getRawSslConfig() {
-        return sslConfig;
+    public @Nullable MqttTlsConfigImpl getRawTlsConfig() {
+        return tlsConfig;
     }
 
     @Override
@@ -106,18 +112,18 @@ public class MqttClientTransportConfigImpl implements MqttClientTransportConfig
     }
 
     @Override
-    public int getSocketConnectTimeoutMs() {
+    public @Range(from = 0, to = Integer.MAX_VALUE) int getSocketConnectTimeoutMs() {
         return socketConnectTimeoutMs;
     }
 
     @Override
-    public int getMqttConnectTimeoutMs() {
+    public @Range(from = 0, to = Integer.MAX_VALUE) int getMqttConnectTimeoutMs() {
         return mqttConnectTimeoutMs;
     }
 
     @Override
-    public MqttClientTransportConfigImplBuilder.@NotNull Default extend() {
-        return new MqttClientTransportConfigImplBuilder.Default(this);
+    public MqttTransportConfigImplBuilder.@NotNull Default extend() {
+        return new MqttTransportConfigImplBuilder.Default(this);
     }
 
     @Override
@@ -125,13 +131,13 @@ public boolean equals(final @Nullable Object o) {
         if (this == o) {
             return true;
         }
-        if (!(o instanceof MqttClientTransportConfigImpl)) {
+        if (!(o instanceof MqttTransportConfigImpl)) {
             return false;
         }
-        final MqttClientTransportConfigImpl that = (MqttClientTransportConfigImpl) o;
+        final MqttTransportConfigImpl that = (MqttTransportConfigImpl) o;
 
         return serverAddress.equals(that.serverAddress) && Objects.equals(localAddress, that.localAddress) &&
-                Objects.equals(sslConfig, that.sslConfig) && Objects.equals(webSocketConfig, that.webSocketConfig) &&
+                Objects.equals(tlsConfig, that.tlsConfig) && Objects.equals(webSocketConfig, that.webSocketConfig) &&
                 Objects.equals(proxyConfig, that.proxyConfig) &&
                 (socketConnectTimeoutMs == that.socketConnectTimeoutMs) &&
                 (mqttConnectTimeoutMs == that.mqttConnectTimeoutMs);
@@ -141,7 +147,7 @@ public boolean equals(final @Nullable Object o) {
     public int hashCode() {
         int result = serverAddress.hashCode();
         result = 31 * result + Objects.hashCode(localAddress);
-        result = 31 * result + Objects.hashCode(sslConfig);
+        result = 31 * result + Objects.hashCode(tlsConfig);
         result = 31 * result + Objects.hashCode(webSocketConfig);
         result = 31 * result + Objects.hashCode(proxyConfig);
         result = 31 * result + Integer.hashCode(socketConnectTimeoutMs);
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientTransportConfigImplBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttTransportConfigImplBuilder.java
similarity index 72%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttClientTransportConfigImplBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttTransportConfigImplBuilder.java
index 69aa1186d..a121d501e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttClientTransportConfigImplBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttTransportConfigImplBuilder.java
@@ -14,61 +14,62 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
-
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.InetSocketAddressUtil;
-import com.hivemq.client.mqtt.MqttClientSslConfig;
-import com.hivemq.client.mqtt.MqttClientTransportConfigBuilder;
-import com.hivemq.client.mqtt.MqttProxyConfig;
-import com.hivemq.client.mqtt.MqttWebSocketConfig;
+package com.hivemq.client2.internal.mqtt;
+
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.InetSocketAddressUtil;
+import com.hivemq.client2.mqtt.MqttProxyConfig;
+import com.hivemq.client2.mqtt.MqttTlsConfig;
+import com.hivemq.client2.mqtt.MqttTransportConfigBuilder;
+import com.hivemq.client2.mqtt.MqttWebSocketConfig;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 
-import static com.hivemq.client.mqtt.MqttClient.*;
-
 /**
  * @author Silvio Giebl
  */
-public abstract class MqttClientTransportConfigImplBuilder<B extends MqttClientTransportConfigImplBuilder<B>> {
+public abstract class MqttTransportConfigImplBuilder<B extends MqttTransportConfigImplBuilder<B>> {
 
     private @Nullable InetSocketAddress serverAddress;
-    private @NotNull Object serverHost = DEFAULT_SERVER_HOST; // String or InetAddress
+    private @NotNull Object serverHost = MqttTransportConfigImpl.DEFAULT_SERVER_HOST; // String or InetAddress
     private int serverPort = -1;
     private @Nullable InetSocketAddress localAddress;
-    private @Nullable MqttClientSslConfigImpl sslConfig;
+    private @Nullable MqttTlsConfigImpl tlsConfig;
     private @Nullable MqttWebSocketConfigImpl webSocketConfig;
     private @Nullable MqttProxyConfigImpl proxyConfig;
-    private int socketConnectTimeoutMs = MqttClientTransportConfigImpl.DEFAULT_SOCKET_CONNECT_TIMEOUT_MS;
-    private int mqttConnectTimeoutMs = MqttClientTransportConfigImpl.DEFAULT_MQTT_CONNECT_TIMEOUT_MS;
+    private @Range(from = 0, to = Integer.MAX_VALUE) int socketConnectTimeoutMs =
+            MqttTransportConfigImpl.DEFAULT_SOCKET_CONNECT_TIMEOUT_MS;
+    private @Range(from = 0, to = Integer.MAX_VALUE) int mqttConnectTimeoutMs =
+            MqttTransportConfigImpl.DEFAULT_MQTT_CONNECT_TIMEOUT_MS;
 
-    MqttClientTransportConfigImplBuilder() {}
+    MqttTransportConfigImplBuilder() {}
 
-    MqttClientTransportConfigImplBuilder(final @NotNull MqttClientTransportConfigImpl transportConfig) {
+    MqttTransportConfigImplBuilder(final @NotNull MqttTransportConfigImpl transportConfig) {
         set(transportConfig);
     }
 
-    MqttClientTransportConfigImplBuilder(final @NotNull MqttClientTransportConfigImplBuilder<?> builder) {
+    MqttTransportConfigImplBuilder(final @NotNull MqttTransportConfigImplBuilder<?> builder) {
         serverAddress = builder.serverAddress;
         serverHost = builder.serverHost;
         serverPort = builder.serverPort;
         localAddress = builder.localAddress;
-        sslConfig = builder.sslConfig;
+        tlsConfig = builder.tlsConfig;
         webSocketConfig = builder.webSocketConfig;
         proxyConfig = builder.proxyConfig;
         socketConnectTimeoutMs = builder.socketConnectTimeoutMs;
         mqttConnectTimeoutMs = builder.mqttConnectTimeoutMs;
     }
 
-    void set(final @NotNull MqttClientTransportConfigImpl transportConfig) {
+    void set(final @NotNull MqttTransportConfigImpl transportConfig) {
         serverAddress = transportConfig.getServerAddress();
         localAddress = transportConfig.getRawLocalAddress();
-        sslConfig = transportConfig.getRawSslConfig();
+        tlsConfig = transportConfig.getRawTlsConfig();
         webSocketConfig = transportConfig.getRawWebSocketConfig();
         proxyConfig = transportConfig.getRawProxyConfig();
         socketConnectTimeoutMs = transportConfig.getSocketConnectTimeoutMs();
@@ -177,21 +178,21 @@ private int getLocalPort() {
         return self();
     }
 
-    public @NotNull B sslWithDefaultConfig() {
-        this.sslConfig = MqttClientSslConfigImpl.DEFAULT;
+    public @NotNull B tls() {
+        this.tlsConfig = MqttTlsConfigImpl.DEFAULT;
         return self();
     }
 
-    public @NotNull B sslConfig(final @Nullable MqttClientSslConfig sslConfig) {
-        this.sslConfig = Checks.notImplementedOrNull(sslConfig, MqttClientSslConfigImpl.class, "SSL config");
+    public @NotNull B tlsConfig(final @Nullable MqttTlsConfig tlsConfig) {
+        this.tlsConfig = Checks.notImplementedOrNull(tlsConfig, MqttTlsConfigImpl.class, "TLS config");
         return self();
     }
 
-    public MqttClientSslConfigImplBuilder.@NotNull Nested<B> sslConfig() {
-        return new MqttClientSslConfigImplBuilder.Nested<>(sslConfig, this::sslConfig);
+    public MqttTlsConfigImplBuilder.@NotNull Nested<B> tlsConfigWith() {
+        return new MqttTlsConfigImplBuilder.Nested<>(tlsConfig, this::tlsConfig);
     }
 
-    public @NotNull B webSocketWithDefaultConfig() {
+    public @NotNull B webSocket() {
         this.webSocketConfig = MqttWebSocketConfigImpl.DEFAULT;
         return self();
     }
@@ -202,7 +203,7 @@ private int getLocalPort() {
         return self();
     }
 
-    public MqttWebSocketConfigImplBuilder.@NotNull Nested<B> webSocketConfig() {
+    public MqttWebSocketConfigImplBuilder.@NotNull Nested<B> webSocketConfigWith() {
         return new MqttWebSocketConfigImplBuilder.Nested<>(webSocketConfig, this::webSocketConfig);
     }
 
@@ -211,7 +212,7 @@ private int getLocalPort() {
         return self();
     }
 
-    public MqttProxyConfigImplBuilder.@NotNull Nested<B> proxyConfig() {
+    public MqttProxyConfigImplBuilder.@NotNull Nested<B> proxyConfigWith() {
         return new MqttProxyConfigImplBuilder.Nested<>(proxyConfig, this::proxyConfig);
     }
 
@@ -243,29 +244,28 @@ private int getServerPort() {
         if (serverPort != -1) {
             return serverPort;
         }
-        if (sslConfig == null) {
+        if (tlsConfig == null) {
             if (webSocketConfig == null) {
-                return DEFAULT_SERVER_PORT;
+                return MqttTransportConfigImpl.DEFAULT_SERVER_PORT;
             }
-            return DEFAULT_SERVER_PORT_WEBSOCKET;
+            return MqttTransportConfigImpl.DEFAULT_SERVER_PORT_WEBSOCKET;
         }
         if (webSocketConfig == null) {
-            return DEFAULT_SERVER_PORT_SSL;
+            return MqttTransportConfigImpl.DEFAULT_SERVER_PORT_TLS;
         }
-        return DEFAULT_SERVER_PORT_WEBSOCKET_SSL;
+        return MqttTransportConfigImpl.DEFAULT_SERVER_PORT_WEBSOCKET_TLS;
     }
 
-    @NotNull MqttClientTransportConfigImpl buildTransportConfig() {
-        return new MqttClientTransportConfigImpl(getServerAddress(), localAddress, sslConfig, webSocketConfig,
-                proxyConfig, socketConnectTimeoutMs, mqttConnectTimeoutMs);
+    @NotNull MqttTransportConfigImpl buildTransportConfig() {
+        return new MqttTransportConfigImpl(getServerAddress(), localAddress, tlsConfig, webSocketConfig, proxyConfig,
+                socketConnectTimeoutMs, mqttConnectTimeoutMs);
     }
 
-    public static class Default extends MqttClientTransportConfigImplBuilder<Default>
-            implements MqttClientTransportConfigBuilder {
+    public static class Default extends MqttTransportConfigImplBuilder<Default> implements MqttTransportConfigBuilder {
 
         public Default() {}
 
-        Default(final @NotNull MqttClientTransportConfigImpl transportConfig) {
+        Default(final @NotNull MqttTransportConfigImpl transportConfig) {
             super(transportConfig);
         }
 
@@ -275,27 +275,27 @@ public Default() {}
         }
 
         @Override
-        public @NotNull MqttClientTransportConfigImpl build() {
+        public @NotNull MqttTransportConfigImpl build() {
             return buildTransportConfig();
         }
     }
 
-    public static class Nested<P> extends MqttClientTransportConfigImplBuilder<Nested<P>>
-            implements MqttClientTransportConfigBuilder.Nested<P> {
+    public static class Nested<P> extends MqttTransportConfigImplBuilder<Nested<P>>
+            implements MqttTransportConfigBuilder.Nested<P> {
 
-        private final @NotNull Function<? super MqttClientTransportConfigImpl, P> parentConsumer;
+        private final @NotNull Function<? super MqttTransportConfigImpl, P> parentConsumer;
 
         public Nested(
-                final @NotNull MqttClientTransportConfigImpl transportConfig,
-                final @NotNull Function<? super MqttClientTransportConfigImpl, P> parentConsumer) {
+                final @NotNull MqttTransportConfigImpl transportConfig,
+                final @NotNull Function<? super MqttTransportConfigImpl, P> parentConsumer) {
 
             super(transportConfig);
             this.parentConsumer = parentConsumer;
         }
 
         Nested(
-                final @NotNull MqttClientTransportConfigImplBuilder<?> builder,
-                final @NotNull Function<? super MqttClientTransportConfigImpl, P> parentConsumer) {
+                final @NotNull MqttTransportConfigImplBuilder<?> builder,
+                final @NotNull Function<? super MqttTransportConfigImpl, P> parentConsumer) {
 
             super(builder);
             this.parentConsumer = parentConsumer;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttWebSocketConfigImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttWebSocketConfigImpl.java
similarity index 62%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttWebSocketConfigImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttWebSocketConfigImpl.java
index b2a08a16f..b14b9c93a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttWebSocketConfigImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttWebSocketConfigImpl.java
@@ -14,47 +14,49 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
-import com.hivemq.client.mqtt.MqttWebSocketConfig;
+import com.hivemq.client2.mqtt.MqttWebSocketConfig;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author David Katz
  * @author Christian Hoff
  */
+@Unmodifiable
 public class MqttWebSocketConfigImpl implements MqttWebSocketConfig {
 
     static final @NotNull MqttWebSocketConfigImpl DEFAULT =
-            new MqttWebSocketConfigImpl(DEFAULT_SERVER_PATH, DEFAULT_QUERY_STRING, DEFAULT_MQTT_SUBPROTOCOL,
-                    DEFAULT_HANDSHAKE_TIMEOUT_MS);
+            new MqttWebSocketConfigImpl(DEFAULT_PATH, DEFAULT_QUERY, DEFAULT_SUBPROTOCOL, DEFAULT_HANDSHAKE_TIMEOUT_MS);
 
-    private final @NotNull String serverPath;
-    private final @NotNull String queryString;
+    private final @NotNull String path;
+    private final @NotNull String query;
     private final @NotNull String subprotocol;
-    private final int handshakeTimeoutMs;
+    private final @Range(from = 0, to = Integer.MAX_VALUE) int handshakeTimeoutMs;
 
     MqttWebSocketConfigImpl(
-            final @NotNull String serverPath,
-            final @NotNull String queryString,
+            final @NotNull String path,
+            final @NotNull String query,
             final @NotNull String subprotocol,
-            final int handshakeTimeoutMs) {
+            final @Range(from = 0, to = Integer.MAX_VALUE) int handshakeTimeoutMs) {
 
-        this.serverPath = serverPath;
-        this.queryString = queryString;
+        this.path = path;
+        this.query = query;
         this.subprotocol = subprotocol;
         this.handshakeTimeoutMs = handshakeTimeoutMs;
     }
 
     @Override
-    public @NotNull String getServerPath() {
-        return serverPath;
+    public @NotNull String getPath() {
+        return path;
     }
 
     @Override
-    public @NotNull String getQueryString() {
-        return queryString;
+    public @NotNull String getQuery() {
+        return query;
     }
 
     @Override
@@ -63,7 +65,7 @@ public class MqttWebSocketConfigImpl implements MqttWebSocketConfig {
     }
 
     @Override
-    public int getHandshakeTimeoutMs() {
+    public @Range(from = 0, to = Integer.MAX_VALUE) int getHandshakeTimeoutMs() {
         return handshakeTimeoutMs;
     }
 
@@ -82,14 +84,14 @@ public boolean equals(final @Nullable Object o) {
         }
         final MqttWebSocketConfigImpl that = (MqttWebSocketConfigImpl) o;
 
-        return serverPath.equals(that.serverPath) && queryString.equals(that.queryString) &&
-                subprotocol.equals(that.subprotocol) && (handshakeTimeoutMs == that.handshakeTimeoutMs);
+        return path.equals(that.path) && query.equals(that.query) && subprotocol.equals(that.subprotocol) &&
+                (handshakeTimeoutMs == that.handshakeTimeoutMs);
     }
 
     @Override
     public int hashCode() {
-        int result = serverPath.hashCode();
-        result = 31 * result + queryString.hashCode();
+        int result = path.hashCode();
+        result = 31 * result + query.hashCode();
         result = 31 * result + subprotocol.hashCode();
         result = 31 * result + Integer.hashCode(handshakeTimeoutMs);
         return result;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/MqttWebSocketConfigImplBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/MqttWebSocketConfigImplBuilder.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/MqttWebSocketConfigImplBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/MqttWebSocketConfigImplBuilder.java
index 808207498..5ab43dcf8 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/MqttWebSocketConfigImplBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/MqttWebSocketConfigImplBuilder.java
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttWebSocketConfigBuilder;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttWebSocketConfigBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
@@ -29,17 +30,18 @@
  */
 public abstract class MqttWebSocketConfigImplBuilder<B extends MqttWebSocketConfigImplBuilder<B>> {
 
-    private @NotNull String serverPath = MqttWebSocketConfigImpl.DEFAULT_SERVER_PATH;
-    private @NotNull String queryString = MqttWebSocketConfigImpl.DEFAULT_QUERY_STRING;
-    private @NotNull String subprotocol = MqttWebSocketConfigImpl.DEFAULT_MQTT_SUBPROTOCOL;
-    private int handshakeTimeoutMs = MqttWebSocketConfigImpl.DEFAULT_HANDSHAKE_TIMEOUT_MS;
+    private @NotNull String path = MqttWebSocketConfigImpl.DEFAULT_PATH;
+    private @NotNull String query = MqttWebSocketConfigImpl.DEFAULT_QUERY;
+    private @NotNull String subprotocol = MqttWebSocketConfigImpl.DEFAULT_SUBPROTOCOL;
+    private @Range(from = 0, to = Integer.MAX_VALUE) int handshakeTimeoutMs =
+            MqttWebSocketConfigImpl.DEFAULT_HANDSHAKE_TIMEOUT_MS;
 
     MqttWebSocketConfigImplBuilder() {}
 
     MqttWebSocketConfigImplBuilder(final @Nullable MqttWebSocketConfigImpl webSocketConfig) {
         if (webSocketConfig != null) {
-            serverPath = webSocketConfig.getServerPath();
-            queryString = webSocketConfig.getQueryString();
+            path = webSocketConfig.getPath();
+            query = webSocketConfig.getQuery();
             subprotocol = webSocketConfig.getSubprotocol();
             handshakeTimeoutMs = webSocketConfig.getHandshakeTimeoutMs();
         }
@@ -47,14 +49,14 @@ public abstract class MqttWebSocketConfigImplBuilder<B extends MqttWebSocketConf
 
     abstract @NotNull B self();
 
-    public @NotNull B serverPath(final @Nullable String serverPath) {
+    public @NotNull B path(final @Nullable String path) {
         // remove any leading slashes
-        this.serverPath = Checks.notNull(serverPath, "Server path").replaceAll("^/+", "");
+        this.path = Checks.notNull(path, "Server path").replaceAll("^/+", "");
         return self();
     }
 
-    public @NotNull B queryString(final @Nullable String queryString) {
-        this.queryString = Checks.notNull(queryString, "Query string");
+    public @NotNull B query(final @Nullable String query) {
+        this.query = Checks.notNull(query, "Query string");
         return self();
     }
 
@@ -71,7 +73,7 @@ public abstract class MqttWebSocketConfigImplBuilder<B extends MqttWebSocketConf
     }
 
     public @NotNull MqttWebSocketConfigImpl build() {
-        return new MqttWebSocketConfigImpl(serverPath, queryString, subprotocol, handshakeTimeoutMs);
+        return new MqttWebSocketConfigImpl(path, query, subprotocol, handshakeTimeoutMs);
     }
 
     public static class Default extends MqttWebSocketConfigImplBuilder<Default> implements MqttWebSocketConfigBuilder {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/advanced/MqttClientAdvancedConfig.java b/src/main/java/com/hivemq/client2/internal/mqtt/advanced/MqttAdvancedConfig.java
similarity index 53%
rename from src/main/java/com/hivemq/client/internal/mqtt/advanced/MqttClientAdvancedConfig.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/advanced/MqttAdvancedConfig.java
index 45e6e4729..037255479 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/advanced/MqttClientAdvancedConfig.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/advanced/MqttAdvancedConfig.java
@@ -14,41 +14,32 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.advanced;
+package com.hivemq.client2.internal.mqtt.advanced;
 
-import com.hivemq.client.internal.mqtt.advanced.interceptor.MqttClientInterceptors;
-import com.hivemq.client.mqtt.mqtt5.advanced.Mqtt5ClientAdvancedConfig;
+import com.hivemq.client2.internal.mqtt.advanced.interceptor.MqttClientInterceptors;
+import com.hivemq.client2.mqtt.mqtt5.advanced.Mqtt5AdvancedConfig;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.Objects;
 
 /**
  * @author Silvio Giebl
  */
-public class MqttClientAdvancedConfig implements Mqtt5ClientAdvancedConfig {
+@Unmodifiable
+public class MqttAdvancedConfig implements Mqtt5AdvancedConfig {
 
-    public static final @NotNull MqttClientAdvancedConfig DEFAULT = new MqttClientAdvancedConfig(false, false, null);
+    public static final @NotNull MqttAdvancedConfig DEFAULT = new MqttAdvancedConfig(false, null);
 
-    private final boolean allowServerReAuth;
     private final boolean validatePayloadFormat;
     private final @Nullable MqttClientInterceptors interceptors;
 
-    MqttClientAdvancedConfig(
-            final boolean allowServerReAuth,
-            final boolean validatePayloadFormat,
-            final @Nullable MqttClientInterceptors interceptors) {
-
-        this.allowServerReAuth = allowServerReAuth;
+    MqttAdvancedConfig(final boolean validatePayloadFormat, final @Nullable MqttClientInterceptors interceptors) {
         this.validatePayloadFormat = validatePayloadFormat;
         this.interceptors = interceptors;
     }
 
-    @Override
-    public boolean isAllowServerReAuth() {
-        return allowServerReAuth;
-    }
-
     @Override
     public boolean isValidatePayloadFormat() {
         return validatePayloadFormat;
@@ -60,8 +51,8 @@ public boolean isValidatePayloadFormat() {
     }
 
     @Override
-    public MqttClientAdvancedConfigBuilder.@NotNull Default extend() {
-        return new MqttClientAdvancedConfigBuilder.Default(this);
+    public MqttAdvancedConfigBuilder.@NotNull Default extend() {
+        return new MqttAdvancedConfigBuilder.Default(this);
     }
 
     @Override
@@ -69,19 +60,17 @@ public boolean equals(final @Nullable Object o) {
         if (this == o) {
             return true;
         }
-        if (!(o instanceof MqttClientAdvancedConfig)) {
+        if (!(o instanceof MqttAdvancedConfig)) {
             return false;
         }
-        final MqttClientAdvancedConfig that = (MqttClientAdvancedConfig) o;
+        final MqttAdvancedConfig that = (MqttAdvancedConfig) o;
 
-        return (allowServerReAuth == that.allowServerReAuth) && (validatePayloadFormat == that.validatePayloadFormat) &&
-                Objects.equals(interceptors, that.interceptors);
+        return (validatePayloadFormat == that.validatePayloadFormat) && Objects.equals(interceptors, that.interceptors);
     }
 
     @Override
     public int hashCode() {
-        int result = Boolean.hashCode(allowServerReAuth);
-        result = 31 * result + Boolean.hashCode(validatePayloadFormat);
+        int result = Boolean.hashCode(validatePayloadFormat);
         result = 31 * result + Objects.hashCode(interceptors);
         return result;
     }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/advanced/MqttClientAdvancedConfigBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/advanced/MqttAdvancedConfigBuilder.java
similarity index 55%
rename from src/main/java/com/hivemq/client/internal/mqtt/advanced/MqttClientAdvancedConfigBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/advanced/MqttAdvancedConfigBuilder.java
index 0b243925d..ffdd7217d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/advanced/MqttClientAdvancedConfigBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/advanced/MqttAdvancedConfigBuilder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.advanced;
+package com.hivemq.client2.internal.mqtt.advanced;
 
-import com.hivemq.client.internal.mqtt.advanced.interceptor.MqttClientInterceptors;
-import com.hivemq.client.internal.mqtt.advanced.interceptor.MqttClientInterceptorsBuilder;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.mqtt5.advanced.Mqtt5ClientAdvancedConfigBuilder;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptors;
+import com.hivemq.client2.internal.mqtt.advanced.interceptor.MqttClientInterceptors;
+import com.hivemq.client2.internal.mqtt.advanced.interceptor.MqttClientInterceptorsBuilder;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.mqtt5.advanced.Mqtt5AdvancedConfigBuilder;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptors;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -29,27 +29,20 @@
 /**
  * @author Silvio Giebl
  */
-public abstract class MqttClientAdvancedConfigBuilder<B extends MqttClientAdvancedConfigBuilder<B>> {
+public abstract class MqttAdvancedConfigBuilder<B extends MqttAdvancedConfigBuilder<B>> {
 
-    private boolean allowServerReAuth;
     private boolean validatePayloadFormat;
     private @Nullable MqttClientInterceptors interceptors;
 
-    MqttClientAdvancedConfigBuilder() {}
+    MqttAdvancedConfigBuilder() {}
 
-    MqttClientAdvancedConfigBuilder(final @NotNull MqttClientAdvancedConfig advancedConfig) {
-        allowServerReAuth = advancedConfig.isAllowServerReAuth();
+    MqttAdvancedConfigBuilder(final @NotNull MqttAdvancedConfig advancedConfig) {
         validatePayloadFormat = advancedConfig.isValidatePayloadFormat();
         interceptors = advancedConfig.getInterceptors();
     }
 
     abstract @NotNull B self();
 
-    public @NotNull B allowServerReAuth(final boolean allowServerReAuth) {
-        this.allowServerReAuth = allowServerReAuth;
-        return self();
-    }
-
     public @NotNull B validatePayloadFormat(final boolean validatePayloadFormat) {
         this.validatePayloadFormat = validatePayloadFormat;
         return self();
@@ -60,20 +53,19 @@ public abstract class MqttClientAdvancedConfigBuilder<B extends MqttClientAdvanc
         return self();
     }
 
-    public MqttClientInterceptorsBuilder.@NotNull Nested<B> interceptors() {
+    public MqttClientInterceptorsBuilder.@NotNull Nested<B> interceptorsWith() {
         return new MqttClientInterceptorsBuilder.Nested<>(interceptors, this::interceptors);
     }
 
-    public @NotNull MqttClientAdvancedConfig build() {
-        return new MqttClientAdvancedConfig(allowServerReAuth, validatePayloadFormat, interceptors);
+    public @NotNull MqttAdvancedConfig build() {
+        return new MqttAdvancedConfig(validatePayloadFormat, interceptors);
     }
 
-    public static class Default extends MqttClientAdvancedConfigBuilder<Default>
-            implements Mqtt5ClientAdvancedConfigBuilder {
+    public static class Default extends MqttAdvancedConfigBuilder<Default> implements Mqtt5AdvancedConfigBuilder {
 
         public Default() {}
 
-        Default(final @NotNull MqttClientAdvancedConfig advancedConfig) {
+        Default(final @NotNull MqttAdvancedConfig advancedConfig) {
             super(advancedConfig);
         }
 
@@ -83,14 +75,14 @@ public Default() {}
         }
     }
 
-    public static class Nested<P> extends MqttClientAdvancedConfigBuilder<Nested<P>>
-            implements Mqtt5ClientAdvancedConfigBuilder.Nested<P> {
+    public static class Nested<P> extends MqttAdvancedConfigBuilder<Nested<P>>
+            implements Mqtt5AdvancedConfigBuilder.Nested<P> {
 
-        private final @NotNull Function<? super MqttClientAdvancedConfig, P> parentConsumer;
+        private final @NotNull Function<? super MqttAdvancedConfig, P> parentConsumer;
 
         public Nested(
-                final @NotNull MqttClientAdvancedConfig advancedConfig,
-                final @NotNull Function<? super MqttClientAdvancedConfig, P> parentConsumer) {
+                final @NotNull MqttAdvancedConfig advancedConfig,
+                final @NotNull Function<? super MqttAdvancedConfig, P> parentConsumer) {
 
             super(advancedConfig);
             this.parentConsumer = parentConsumer;
diff --git a/src/main/java/com/hivemq/client2/internal/mqtt/advanced/interceptor/MqttClientInterceptors.java b/src/main/java/com/hivemq/client2/internal/mqtt/advanced/interceptor/MqttClientInterceptors.java
new file mode 100644
index 000000000..c9efb602d
--- /dev/null
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/advanced/interceptor/MqttClientInterceptors.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2018-present HiveMQ and the HiveMQ Community
+ *
+ * Licensed 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
+ *
+ *     http://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 com.hivemq.client2.internal.mqtt.advanced.interceptor;
+
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptors;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5InboundQos1Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5OutboundQos1Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5InboundQos2Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5OutboundQos2Interceptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
+
+import java.util.Objects;
+
+/**
+ * @author Silvio Giebl
+ */
+@Unmodifiable
+public class MqttClientInterceptors implements Mqtt5ClientInterceptors {
+
+    private final @Nullable Mqtt5InboundQos1Interceptor inboundQos1Interceptor;
+    private final @Nullable Mqtt5OutboundQos1Interceptor outboundQos1Interceptor;
+    private final @Nullable Mqtt5InboundQos2Interceptor inboundQos2Interceptor;
+    private final @Nullable Mqtt5OutboundQos2Interceptor outboundQos2Interceptor;
+
+    MqttClientInterceptors(
+            final @Nullable Mqtt5InboundQos1Interceptor inboundQos1Interceptor,
+            final @Nullable Mqtt5OutboundQos1Interceptor outboundQos1Interceptor,
+            final @Nullable Mqtt5InboundQos2Interceptor inboundQos2Interceptor,
+            final @Nullable Mqtt5OutboundQos2Interceptor outboundQos2Interceptor) {
+
+        this.inboundQos1Interceptor = inboundQos1Interceptor;
+        this.outboundQos1Interceptor = outboundQos1Interceptor;
+        this.inboundQos2Interceptor = inboundQos2Interceptor;
+        this.outboundQos2Interceptor = outboundQos2Interceptor;
+    }
+
+    @Override
+    public @Nullable Mqtt5InboundQos1Interceptor getInboundQos1Interceptor() {
+        return inboundQos1Interceptor;
+    }
+
+    @Override
+    public @Nullable Mqtt5OutboundQos1Interceptor getOutboundQos1Interceptor() {
+        return outboundQos1Interceptor;
+    }
+
+    @Override
+    public @Nullable Mqtt5InboundQos2Interceptor getInboundQos2Interceptor() {
+        return inboundQos2Interceptor;
+    }
+
+    @Override
+    public @Nullable Mqtt5OutboundQos2Interceptor getOutboundQos2Interceptor() {
+        return outboundQos2Interceptor;
+    }
+
+    @Override
+    public MqttClientInterceptorsBuilder.@NotNull Default extend() {
+        return new MqttClientInterceptorsBuilder.Default(this);
+    }
+
+    @Override
+    public boolean equals(final @Nullable Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof MqttClientInterceptors)) {
+            return false;
+        }
+        final MqttClientInterceptors that = (MqttClientInterceptors) o;
+
+        return Objects.equals(inboundQos1Interceptor, that.inboundQos1Interceptor) &&
+                Objects.equals(outboundQos1Interceptor, that.outboundQos1Interceptor) &&
+                Objects.equals(inboundQos2Interceptor, that.inboundQos2Interceptor) &&
+                Objects.equals(outboundQos2Interceptor, that.outboundQos2Interceptor);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Objects.hashCode(inboundQos1Interceptor);
+        result = 31 * result + Objects.hashCode(outboundQos1Interceptor);
+        result = 31 * result + Objects.hashCode(inboundQos2Interceptor);
+        result = 31 * result + Objects.hashCode(outboundQos2Interceptor);
+        return result;
+    }
+}
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/advanced/interceptor/MqttClientInterceptorsBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/advanced/interceptor/MqttClientInterceptorsBuilder.java
similarity index 55%
rename from src/main/java/com/hivemq/client/internal/mqtt/advanced/interceptor/MqttClientInterceptorsBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/advanced/interceptor/MqttClientInterceptorsBuilder.java
index a308c02f0..316cc5be8 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/advanced/interceptor/MqttClientInterceptorsBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/advanced/interceptor/MqttClientInterceptorsBuilder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.advanced.interceptor;
+package com.hivemq.client2.internal.mqtt.advanced.interceptor;
 
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptorsBuilder;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5IncomingQos1Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5OutgoingQos1Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5IncomingQos2Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5OutgoingQos2Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptorsBuilder;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5InboundQos1Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5OutboundQos1Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5InboundQos2Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5OutboundQos2Interceptor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -31,47 +31,47 @@
  */
 public abstract class MqttClientInterceptorsBuilder<B extends MqttClientInterceptorsBuilder<B>> {
 
-    private @Nullable Mqtt5IncomingQos1Interceptor incomingQos1Interceptor;
-    private @Nullable Mqtt5OutgoingQos1Interceptor outgoingQos1Interceptor;
-    private @Nullable Mqtt5IncomingQos2Interceptor incomingQos2Interceptor;
-    private @Nullable Mqtt5OutgoingQos2Interceptor outgoingQos2Interceptor;
+    private @Nullable Mqtt5InboundQos1Interceptor inboundQos1Interceptor;
+    private @Nullable Mqtt5OutboundQos1Interceptor outboundQos1Interceptor;
+    private @Nullable Mqtt5InboundQos2Interceptor inboundQos2Interceptor;
+    private @Nullable Mqtt5OutboundQos2Interceptor outboundQos2Interceptor;
 
     MqttClientInterceptorsBuilder() {}
 
     MqttClientInterceptorsBuilder(final @Nullable MqttClientInterceptors interceptors) {
         if (interceptors != null) {
-            incomingQos1Interceptor = interceptors.getIncomingQos1Interceptor();
-            outgoingQos1Interceptor = interceptors.getOutgoingQos1Interceptor();
-            incomingQos2Interceptor = interceptors.getIncomingQos2Interceptor();
-            outgoingQos2Interceptor = interceptors.getOutgoingQos2Interceptor();
+            inboundQos1Interceptor = interceptors.getInboundQos1Interceptor();
+            outboundQos1Interceptor = interceptors.getOutboundQos1Interceptor();
+            inboundQos2Interceptor = interceptors.getInboundQos2Interceptor();
+            outboundQos2Interceptor = interceptors.getOutboundQos2Interceptor();
         }
     }
 
     abstract @NotNull B self();
 
-    public @NotNull B incomingQos1Interceptor(final @Nullable Mqtt5IncomingQos1Interceptor incomingQos1Interceptor) {
-        this.incomingQos1Interceptor = incomingQos1Interceptor;
+    public @NotNull B inboundQos1Interceptor(final @Nullable Mqtt5InboundQos1Interceptor inboundQos1Interceptor) {
+        this.inboundQos1Interceptor = inboundQos1Interceptor;
         return self();
     }
 
-    public @NotNull B outgoingQos1Interceptor(final @Nullable Mqtt5OutgoingQos1Interceptor outgoingQos1Interceptor) {
-        this.outgoingQos1Interceptor = outgoingQos1Interceptor;
+    public @NotNull B outboundQos1Interceptor(final @Nullable Mqtt5OutboundQos1Interceptor outboundQos1Interceptor) {
+        this.outboundQos1Interceptor = outboundQos1Interceptor;
         return self();
     }
 
-    public @NotNull B incomingQos2Interceptor(final @Nullable Mqtt5IncomingQos2Interceptor incomingQos2Interceptor) {
-        this.incomingQos2Interceptor = incomingQos2Interceptor;
+    public @NotNull B inboundQos2Interceptor(final @Nullable Mqtt5InboundQos2Interceptor inboundQos2Interceptor) {
+        this.inboundQos2Interceptor = inboundQos2Interceptor;
         return self();
     }
 
-    public @NotNull B outgoingQos2Interceptor(final @Nullable Mqtt5OutgoingQos2Interceptor outgoingQos2Interceptor) {
-        this.outgoingQos2Interceptor = outgoingQos2Interceptor;
+    public @NotNull B outboundQos2Interceptor(final @Nullable Mqtt5OutboundQos2Interceptor outboundQos2Interceptor) {
+        this.outboundQos2Interceptor = outboundQos2Interceptor;
         return self();
     }
 
     public @NotNull MqttClientInterceptors build() {
-        return new MqttClientInterceptors(incomingQos1Interceptor, outgoingQos1Interceptor, incomingQos2Interceptor,
-                outgoingQos2Interceptor);
+        return new MqttClientInterceptors(inboundQos1Interceptor, outboundQos1Interceptor, inboundQos2Interceptor,
+                outboundQos2Interceptor);
     }
 
     public static class Default extends MqttClientInterceptorsBuilder<Default>
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/MqttCodecModule.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/MqttCodecModule.java
similarity index 75%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/MqttCodecModule.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/MqttCodecModule.java
index 5aaff1947..f75d45d0c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/MqttCodecModule.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/MqttCodecModule.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec;
+package com.hivemq.client2.internal.mqtt.codec;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.codec.decoder.mqtt3.Mqtt3ClientMessageDecoders;
-import com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5ClientMessageDecoders;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.codec.encoder.mqtt3.Mqtt3ClientMessageEncoders;
-import com.hivemq.client.internal.mqtt.codec.encoder.mqtt5.Mqtt5ClientMessageEncoders;
-import com.hivemq.client.internal.mqtt.ioc.ConnectionScope;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3.Mqtt3ClientMessageDecoders;
+import com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5ClientMessageDecoders;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3.Mqtt3ClientMessageEncoders;
+import com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5.Mqtt5ClientMessageEncoders;
+import com.hivemq.client2.internal.mqtt.ioc.ConnectionScope;
 import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttDecoder.java
similarity index 75%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttDecoder.java
index 8abec3f1b..d97daa31f 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttDecoder.java
@@ -14,23 +14,27 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder;
-
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.internal.mqtt.ioc.ConnectionScope;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictions;
-import com.hivemq.client.mqtt.exceptions.MqttDecodeException;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder;
+
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.ioc.ConnectionScope;
+import com.hivemq.client2.internal.mqtt.message.MqttMessage;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectRestrictions;
+import com.hivemq.client2.mqtt.exceptions.MqttDecodeException;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.ByteToMessageDecoder;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
+
 import java.util.List;
 
 /**
@@ -43,6 +47,7 @@
 public class MqttDecoder extends ByteToMessageDecoder {
 
     public static final @NotNull String NAME = "decoder";
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttDecoder.class);
     private static final int MIN_FIXED_HEADER_LENGTH = 2;
 
     private final @NotNull MqttMessageDecoders decoders;
@@ -106,15 +111,18 @@ protected void decode(
             }
 
             in.writerIndex(readerIndexAfterFixedHeader + remainingLength);
-            out.add(decoder.decode(flags, in, context));
+            MqttMessage msg = decoder.decode(flags, in, context);
+            LOGGER.trace("Decoded MqttMessage {} from {}", msg, ctx.channel().remoteAddress());
+            out.add(msg);
             in.writerIndex(writerIndex);
-
         } catch (final MqttDecoderException e) {
             in.clear();
             final Mqtt5MessageType type = Mqtt5MessageType.fromCode(messageType);
             final String message =
                     "Exception while decoding " + ((type == null) ? "UNKNOWN" : type) + ": " + e.getMessage();
-            MqttDisconnectUtil.disconnect(ctx.channel(), e.getReasonCode(), new MqttDecodeException(message));
+            LOGGER.debug(message + ", Reason code: {}, remote address: {}", e.getReasonCode(), ctx.channel().remoteAddress());
+            MqttDisconnectUtil.disconnect(ctx.channel(), e.getReasonCode(),
+                    new MqttDecodeException(message.concat(", Reason code: ").concat(e.getReasonCode().toString())));
         }
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttDecoderContext.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttDecoderContext.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttDecoderContext.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttDecoderContext.java
index cce067581..005cd1daa 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttDecoderContext.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttDecoderContext.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder;
+package com.hivemq.client2.internal.mqtt.codec.decoder;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImpl;
 import org.jetbrains.annotations.Nullable;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttDecoderException.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttDecoderException.java
similarity index 93%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttDecoderException.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttDecoderException.java
index d4ac754a9..d95fd71d4 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttDecoderException.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttDecoderException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder;
+package com.hivemq.client2.internal.mqtt.codec.decoder;
 
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttMessageDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttMessageDecoder.java
similarity index 92%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttMessageDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttMessageDecoder.java
index 47560d3f6..145e32937 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttMessageDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttMessageDecoder.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder;
+package com.hivemq.client2.internal.mqtt.codec.decoder;
 
-import com.hivemq.client.internal.mqtt.message.MqttMessage;
+import com.hivemq.client2.internal.mqtt.message.MqttMessage;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttMessageDecoderUtil.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttMessageDecoderUtil.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttMessageDecoderUtil.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttMessageDecoderUtil.java
index 32c33d9d7..312594e43 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttMessageDecoderUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttMessageDecoderUtil.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder;
+package com.hivemq.client2.internal.mqtt.codec.decoder;
 
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
-import static com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish.NO_PACKET_IDENTIFIER_QOS_0;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish.NO_PACKET_IDENTIFIER_QOS_0;
 
 /**
  * Util for decoders for MQTT messages of different versions.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttMessageDecoders.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttMessageDecoders.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttMessageDecoders.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttMessageDecoders.java
index 0403bbe1e..a92d4ec5a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttMessageDecoders.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttMessageDecoders.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder;
+package com.hivemq.client2.internal.mqtt.codec.decoder;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttPingRespDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttPingRespDecoder.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttPingRespDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttPingRespDecoder.java
index 3660628a8..13fddfdc0 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/MqttPingRespDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/MqttPingRespDecoder.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder;
+package com.hivemq.client2.internal.mqtt.codec.decoder;
 
-import com.hivemq.client.internal.mqtt.message.ping.MqttPingResp;
+import com.hivemq.client2.internal.mqtt.message.ping.MqttPingResp;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
-import static com.hivemq.client.internal.mqtt.message.ping.MqttPingResp.INSTANCE;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
+import static com.hivemq.client2.internal.mqtt.message.ping.MqttPingResp.INSTANCE;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecoders.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecoders.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecoders.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecoders.java
index b70a8df4c..65e852323 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecoders.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecoders.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttPingRespDecoder;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttPingRespDecoder;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoder.java
similarity index 70%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoder.java
index beeb576f1..d5ed22f16 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoder.java
@@ -14,23 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.internal.mqtt.message.connect.connack.mqtt3.Mqtt3ConnAckView;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAckReturnCode;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnAckView;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAckReturnCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt3.Mqtt3MessageDecoderUtil.wrongReturnCode;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3.Mqtt3MessageDecoderUtil.wrongReturnCode;
 
 /**
  * @author Daniel Krüger
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3MessageDecoderUtil.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3MessageDecoderUtil.java
similarity index 87%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3MessageDecoderUtil.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3MessageDecoderUtil.java
index 89313143f..637a04992 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3MessageDecoderUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3MessageDecoderUtil.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoder.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoder.java
index b27396df7..2716774db 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoder.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.internal.mqtt.message.publish.puback.mqtt3.Mqtt3PubAckView;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubAckView;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
 
 /**
  * @author Daniel Krüger
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoder.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoder.java
index 15cb121e4..874f193e7 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoder.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.mqtt3.Mqtt3PubCompView;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubCompView;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
 
 /**
  * @author Daniel Krüger
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoder.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoder.java
index da8be5614..fdda8fb14 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoder.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.mqtt3.Mqtt3PubRecView;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubRecView;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
 
 /**
  * @author Daniel Krüger
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoder.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoder.java
index 2d57d6db3..0ee455a23 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoder.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.mqtt3.Mqtt3PubRelView;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubRelView;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
 
 /**
  * @author Daniel Krüger
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoder.java
similarity index 74%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoder.java
index 612a14be8..d1cf26f46 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoder.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImpl;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
-import com.hivemq.client.internal.util.ByteBufferUtil;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
+import com.hivemq.client2.internal.util.ByteBufferUtil;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
@@ -32,7 +32,7 @@
 import javax.inject.Singleton;
 import java.nio.ByteBuffer;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.*;
 
 /**
  * @author Daniel Krüger
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoder.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoder.java
index a1a067d2f..99f6a2abb 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoder.java
@@ -14,24 +14,24 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAck;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.mqtt3.Mqtt3SubAckView;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAckReturnCode;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAck;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubAckView;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAckReturnCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt3.Mqtt3MessageDecoderUtil.wrongReturnCode;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3.Mqtt3MessageDecoderUtil.wrongReturnCode;
 
 /**
  * @author Daniel Krüger
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoder.java
similarity index 69%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoder.java
index fe4ee306e..7bf19f7c0 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoder.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.MqttUnsubAck;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.mqtt3.Mqtt3UnsubAckView;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubAck;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubAckView;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkRemainingLength;
 
 /**
  * @author Daniel Krüger
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoder.java
similarity index 72%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoder.java
index a6109c0f6..1d70e4888 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoder.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.auth.MqttAuth;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttAuth;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
@@ -33,10 +33,10 @@
 import javax.inject.Singleton;
 import java.nio.ByteBuffer;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.auth.MqttAuthProperty.*;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.auth.MqttAuthProperty.*;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecoders.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecoders.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecoders.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecoders.java
index 00c7af4be..52aed2207 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecoders.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecoders.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttPingRespDecoder;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttPingRespDecoder;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoder.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoder.java
index 2949a5b6c..6b90fb735 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoder.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.*;
-import com.hivemq.client.internal.mqtt.message.auth.MqttEnhancedAuth;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAckRestrictions;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAckReturnCode;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.*;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttEnhancedAuth;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAckRestrictions;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAckReturnCode;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
@@ -35,12 +35,12 @@
 import javax.inject.Singleton;
 import java.nio.ByteBuffer;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck.KEEP_ALIVE_FROM_CONNECT;
-import static com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
-import static com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAckProperty.*;
-import static com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions.*;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck.KEEP_ALIVE_FROM_CONNECT;
+import static com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
+import static com.hivemq.client2.internal.mqtt.message.connect.MqttConnAckProperty.*;
+import static com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions.*;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoder.java
similarity index 71%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoder.java
index 35b8319b0..a8d3bf814 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoder.java
@@ -14,28 +14,28 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect.DEFAULT_REASON_CODE;
-import static com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
-import static com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnectProperty.*;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect.DEFAULT_REASON_CODE;
+import static com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
+import static com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnectProperty.*;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtil.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtil.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtil.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtil.java
index 7beccb86b..26f4f3e1d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtil.java
@@ -14,25 +14,25 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.datatypes.MqttBinaryData;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttBinaryData;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.nio.ByteBuffer;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.malformedUTF8String;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
-import static com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.malformedUTF8String;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
+import static com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
 
 /**
  * Util for decoders for MQTT 5 messages.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoder.java
similarity index 68%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoder.java
index 307f81edb..47a284a52 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoder.java
@@ -14,29 +14,29 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAckReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck.DEFAULT_REASON_CODE;
-import static com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAckProperty.REASON_STRING;
-import static com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAckProperty.USER_PROPERTY;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck.DEFAULT_REASON_CODE;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubAckProperty.REASON_STRING;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubAckProperty.USER_PROPERTY;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoder.java
similarity index 67%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoder.java
index 552fe31e7..6f1ce2acc 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoder.java
@@ -14,29 +14,29 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp.DEFAULT_REASON_CODE;
-import static com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubCompProperty.REASON_STRING;
-import static com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubCompProperty.USER_PROPERTY;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp.DEFAULT_REASON_CODE;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubCompProperty.REASON_STRING;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubCompProperty.USER_PROPERTY;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoder.java
similarity index 68%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoder.java
index 735b7f649..6397257d0 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoder.java
@@ -14,29 +14,29 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec.DEFAULT_REASON_CODE;
-import static com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRecProperty.REASON_STRING;
-import static com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRecProperty.USER_PROPERTY;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec.DEFAULT_REASON_CODE;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubRecProperty.REASON_STRING;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubRecProperty.USER_PROPERTY;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoder.java
similarity index 68%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoder.java
index 34b98248b..aa28d08a8 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoder.java
@@ -14,29 +14,29 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRelReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel.DEFAULT_REASON_CODE;
-import static com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRelProperty.REASON_STRING;
-import static com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRelProperty.USER_PROPERTY;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel.DEFAULT_REASON_CODE;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubRelProperty.REASON_STRING;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubRelProperty.USER_PROPERTY;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoder.java
similarity index 86%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoder.java
index 8d31a2785..441a76f2f 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoder.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.*;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.util.ByteBufferUtil;
-import com.hivemq.client.internal.util.Utf8Util;
-import com.hivemq.client.internal.util.collections.ImmutableIntList;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.*;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish;
+import com.hivemq.client2.internal.util.ByteBufferUtil;
+import com.hivemq.client2.internal.util.Utf8Util;
+import com.hivemq.client2.internal.util.collections.ImmutableIntList;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
@@ -36,11 +36,11 @@
 import javax.inject.Singleton;
 import java.nio.ByteBuffer;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.publish.MqttPublish.NO_MESSAGE_EXPIRY;
-import static com.hivemq.client.internal.mqtt.message.publish.MqttPublishProperty.*;
-import static com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish.*;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPublish.NO_MESSAGE_EXPIRY;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPublishProperty.*;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish.*;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoder.java
similarity index 73%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoder.java
index e4b0d4cda..f7df5c0b2 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoder.java
@@ -14,28 +14,28 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAck;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAck;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAckReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAckProperty.REASON_STRING;
-import static com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAckProperty.USER_PROPERTY;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAckProperty.REASON_STRING;
+import static com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAckProperty.USER_PROPERTY;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoder.java
similarity index 72%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoder.java
index 3144b0cbf..bf128d50e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoder.java
@@ -14,28 +14,28 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderContext;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.MqttUnsubAck;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderContext;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubAck;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAckReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
-import static com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
-import static com.hivemq.client.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.MqttUnsubAckProperty.REASON_STRING;
-import static com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.MqttUnsubAckProperty.USER_PROPERTY;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.checkFixedHeaderFlags;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoderUtil.remainingLengthTooShort;
+import static com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5.Mqtt5MessageDecoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubAckProperty.REASON_STRING;
+import static com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubAckProperty.USER_PROPERTY;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttEncoder.java
similarity index 78%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttEncoder.java
index 3b99bb907..c8a57f23e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttEncoder.java
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder;
+package com.hivemq.client2.internal.mqtt.codec.encoder;
 
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.ioc.ConnectionScope;
-import com.hivemq.client.internal.mqtt.message.MqttMessage;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.ioc.ConnectionScope;
+import com.hivemq.client2.internal.mqtt.message.MqttMessage;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.channel.ChannelDuplexHandler;
@@ -37,6 +39,7 @@
 public class MqttEncoder extends ChannelDuplexHandler {
 
     public static final @NotNull String NAME = "encoder";
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttEncoder.class);
 
     private final @NotNull MqttMessageEncoders encoders;
     private final @NotNull MqttEncoderContext context;
@@ -67,8 +70,10 @@ public void write(
                 throw new UnsupportedOperationException();
             }
             final ByteBuf out = messageEncoder.castAndEncode(message, context);
+            LOGGER.trace("Write MqttMessage {} to {}", message, ctx.channel().remoteAddress());
             ctx.write(out, promise);
         } else {
+            LOGGER.trace("Write message {} to {}", msg, ctx.channel().remoteAddress());
             ctx.write(msg, promise);
         }
     }
@@ -78,22 +83,26 @@ public void flush(final @NotNull ChannelHandlerContext ctx) {
         if (inRead) {
             pendingFlush = true;
         } else {
+            LOGGER.trace("flush");
             ctx.flush();
         }
     }
 
     @Override
     public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull Object msg) {
+        LOGGER.trace("channelRead: {} from {}", msg, ctx.channel().remoteAddress());
         inRead = true;
         ctx.fireChannelRead(msg);
     }
 
     @Override
     public void channelReadComplete(final @NotNull ChannelHandlerContext ctx) {
+        LOGGER.trace("channelRead complete");
         ctx.fireChannelReadComplete();
         inRead = false;
         if (pendingFlush) {
             pendingFlush = false;
+            LOGGER.trace("flush pendingFlush");
             ctx.flush();
         }
     }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttEncoderContext.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttEncoderContext.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttEncoderContext.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttEncoderContext.java
index ce903a0d5..b6fad855d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttEncoderContext.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttEncoderContext.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder;
+package com.hivemq.client2.internal.mqtt.codec.encoder;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
 import io.netty.buffer.ByteBufAllocator;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttMessageEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttMessageEncoder.java
similarity index 93%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttMessageEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttMessageEncoder.java
index 1131417f7..88a16e030 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttMessageEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttMessageEncoder.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder;
+package com.hivemq.client2.internal.mqtt.codec.encoder;
 
-import com.hivemq.client.internal.mqtt.message.MqttMessage;
+import com.hivemq.client2.internal.mqtt.message.MqttMessage;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttMessageEncoderUtil.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttMessageEncoderUtil.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttMessageEncoderUtil.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttMessageEncoderUtil.java
index c6102b65a..aae4d7d7f 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttMessageEncoderUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttMessageEncoderUtil.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder;
+package com.hivemq.client2.internal.mqtt.codec.encoder;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttBinaryData;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.MqttMessage;
-import com.hivemq.client.mqtt.exceptions.MqttEncodeException;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttBinaryData;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.MqttMessage;
+import com.hivemq.client2.mqtt.exceptions.MqttEncodeException;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttMessageEncoders.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttMessageEncoders.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttMessageEncoders.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttMessageEncoders.java
index b0592ed8c..e54a29373 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttMessageEncoders.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttMessageEncoders.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder;
+package com.hivemq.client2.internal.mqtt.codec.encoder;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttPingReqEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttPingReqEncoder.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttPingReqEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttPingReqEncoder.java
index 411711187..18662388c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/MqttPingReqEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/MqttPingReqEncoder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder;
+package com.hivemq.client2.internal.mqtt.codec.encoder;
 
-import com.hivemq.client.internal.mqtt.message.ping.MqttPingReq;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.message.ping.MqttPingReq;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.UnpooledByteBufAllocator;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3ClientMessageEncoders.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3ClientMessageEncoders.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3ClientMessageEncoders.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3ClientMessageEncoders.java
index 3e978f027..57a77d012 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3ClientMessageEncoders.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3ClientMessageEncoders.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttPingReqEncoder;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttPingReqEncoder;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoder.java
similarity index 87%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoder.java
index 4358591a4..4419f6bc3 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoder.java
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttStatefulConnect;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttStatefulConnect;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoderUtil.*;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3DisconnectEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3DisconnectEncoder.java
similarity index 80%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3DisconnectEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3DisconnectEncoder.java
index 0f473f019..c7f224508 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3DisconnectEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3DisconnectEncoder.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttEncoderContext;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoder;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttEncoderContext;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoder;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.UnpooledByteBufAllocator;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3MessageEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3MessageEncoder.java
similarity index 87%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3MessageEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3MessageEncoder.java
index c0c2c5b93..94bf7c688 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3MessageEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3MessageEncoder.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttEncoderContext;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoder;
-import com.hivemq.client.internal.mqtt.message.MqttMessage;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttEncoderContext;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoder;
+import com.hivemq.client2.internal.mqtt.message.MqttMessage;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
-import static com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoderUtil.encodedPacketLength;
-import static com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoderUtil.maximumPacketSizeExceeded;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoderUtil.encodedPacketLength;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoderUtil.maximumPacketSizeExceeded;
 
 /**
  * Base class of encoders for MQTT 3 messages.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoder.java
similarity index 77%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoder.java
index 4143c90cd..a515c478c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoder.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.mqtt3.Mqtt3MessageEncoder.Mqtt3MessageWithIdEncoder;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3.Mqtt3MessageEncoder.Mqtt3MessageWithIdEncoder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoder.java
similarity index 77%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoder.java
index 5a537146c..44e202ac1 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoder.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.mqtt3.Mqtt3MessageEncoder.Mqtt3MessageWithIdEncoder;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3.Mqtt3MessageEncoder.Mqtt3MessageWithIdEncoder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoder.java
similarity index 77%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoder.java
index ab678e32c..69e078a94 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoder.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.mqtt3.Mqtt3MessageEncoder.Mqtt3MessageWithIdEncoder;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3.Mqtt3MessageEncoder.Mqtt3MessageWithIdEncoder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoder.java
similarity index 77%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoder.java
index 01ef046a4..3b53ac831 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoder.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.mqtt3.Mqtt3MessageEncoder.Mqtt3MessageWithIdEncoder;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3.Mqtt3MessageEncoder.Mqtt3MessageWithIdEncoder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PublishEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PublishEncoder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PublishEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PublishEncoder.java
index 1deec43a0..d299d8d73 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PublishEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PublishEncoder.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttEncoderContext;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttEncoderContext;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3SubscribeEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3SubscribeEncoder.java
similarity index 84%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3SubscribeEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3SubscribeEncoder.java
index 9d8030b9c..0322eea85 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3SubscribeEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3SubscribeEncoder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttStatefulSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttStatefulSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
@@ -74,7 +74,7 @@ private void encodePayload(final @NotNull MqttStatefulSubscribe message, final @
         for (int i = 0; i < subscriptions.size(); i++) {
             final MqttSubscription subscription = subscriptions.get(i);
             subscription.getTopicFilter().encode(out);
-            out.writeByte(subscription.getQos().getCode());
+            out.writeByte(subscription.getMaxQos().getCode());
         }
     }
 }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3UnsubscribeEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3UnsubscribeEncoder.java
similarity index 86%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3UnsubscribeEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3UnsubscribeEncoder.java
index 9e5c70de1..6f99c0c05 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3UnsubscribeEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3UnsubscribeEncoder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttStatefulUnsubscribe;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttStatefulUnsubscribe;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoder.java
similarity index 84%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoder.java
index 19c8c13e9..263e10303 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoder.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.auth.MqttAuth;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.auth.MqttAuthProperty.AUTHENTICATION_DATA;
-import static com.hivemq.client.internal.mqtt.message.auth.MqttAuthProperty.AUTHENTICATION_METHOD;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.auth.MqttAuthProperty.AUTHENTICATION_DATA;
+import static com.hivemq.client2.internal.mqtt.message.auth.MqttAuthProperty.AUTHENTICATION_METHOD;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5ClientMessageEncoders.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5ClientMessageEncoders.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5ClientMessageEncoders.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5ClientMessageEncoders.java
index ef3cf01ad..afecd53aa 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5ClientMessageEncoders.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5ClientMessageEncoders.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttPingReqEncoder;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttPingReqEncoder;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoder.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoder.java
index d2917c25a..8fb819854 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoder.java
@@ -14,31 +14,31 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttEncoderContext;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.auth.MqttEnhancedAuth;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictions;
-import com.hivemq.client.internal.mqtt.message.connect.MqttStatefulConnect;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublishProperty;
-import com.hivemq.client.mqtt.exceptions.MqttEncodeException;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttEncoderContext;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttEnhancedAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectRestrictions;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttStatefulConnect;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublishProperty;
+import com.hivemq.client2.mqtt.exceptions.MqttEncodeException;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoderUtil.*;
-import static com.hivemq.client.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.connect.MqttConnect.DEFAULT_SESSION_EXPIRY_INTERVAL;
-import static com.hivemq.client.internal.mqtt.message.connect.MqttConnectProperty.*;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.connect.MqttConnect.DEFAULT_SESSION_EXPIRY_INTERVAL;
+import static com.hivemq.client2.internal.mqtt.message.connect.MqttConnectProperty.*;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoder.java
similarity index 70%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoder.java
index 83d25be1e..991c2c180 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoder.java
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect.DEFAULT_REASON_CODE;
-import static com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
-import static com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnectProperty.SERVER_REFERENCE;
-import static com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnectProperty.SESSION_EXPIRY_INTERVAL;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect.DEFAULT_REASON_CODE;
+import static com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
+import static com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnectProperty.SERVER_REFERENCE;
+import static com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnectProperty.SESSION_EXPIRY_INTERVAL;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageEncoderUtil.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageEncoderUtil.java
similarity index 93%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageEncoderUtil.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageEncoderUtil.java
index 95f928939..9aac4db3e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageEncoderUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageEncoderUtil.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttBinaryData;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttBinaryData;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageWithUserPropertiesEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageWithUserPropertiesEncoder.java
similarity index 93%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageWithUserPropertiesEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageWithUserPropertiesEncoder.java
index 565cf88a9..f4e104e96 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageWithUserPropertiesEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5MessageWithUserPropertiesEncoder.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttEncoderContext;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.MqttMessage;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttEncoderContext;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.MqttMessage;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
-import static com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoderUtil.*;
-import static com.hivemq.client.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.encodeNullableProperty;
-import static com.hivemq.client.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.nullablePropertyEncodedLength;
-import static com.hivemq.client.internal.mqtt.message.MqttProperty.REASON_STRING;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.encodeNullableProperty;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.nullablePropertyEncodedLength;
+import static com.hivemq.client2.internal.mqtt.message.MqttProperty.REASON_STRING;
 
 /**
  * Base class of encoders for MQTT messages with omissible User Properties.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoder.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoder.java
index e4ad274b5..03a694ea5 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoder.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAckReasonCode;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAckReasonCode;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck.DEFAULT_REASON_CODE;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck.DEFAULT_REASON_CODE;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoder.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoder.java
index f1cac1fd6..cacde6f90 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoder.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompReasonCode;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompReasonCode;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp.DEFAULT_REASON_CODE;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp.DEFAULT_REASON_CODE;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoder.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoder.java
index 42fb61b0a..f936c39c7 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoder.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecReasonCode;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecReasonCode;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec.DEFAULT_REASON_CODE;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec.DEFAULT_REASON_CODE;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoder.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoder.java
index cba0adab5..d21d1688a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoder.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelReasonCode;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRelReasonCode;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel.DEFAULT_REASON_CODE;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel.DEFAULT_REASON_CODE;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoder.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoder.java
index 0ee94dcda..a50c7ae5d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoder.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttEncoderContext;
-import com.hivemq.client.internal.mqtt.datatypes.MqttBinaryData;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.util.collections.ImmutableIntList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttEncoderContext;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttBinaryData;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish;
+import com.hivemq.client2.internal.util.collections.ImmutableIntList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
@@ -32,10 +32,10 @@
 import javax.inject.Singleton;
 import java.nio.ByteBuffer;
 
-import static com.hivemq.client.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.*;
-import static com.hivemq.client.internal.mqtt.message.publish.MqttPublish.NO_MESSAGE_EXPIRY;
-import static com.hivemq.client.internal.mqtt.message.publish.MqttPublishProperty.*;
-import static com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish.DEFAULT_NO_TOPIC_ALIAS;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.*;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPublish.NO_MESSAGE_EXPIRY;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttPublishProperty.*;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish.DEFAULT_NO_TOPIC_ALIAS;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoder.java
similarity index 81%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoder.java
index 5060fe17c..54a5ab106 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoder.java
@@ -14,23 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttStatefulSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttStatefulSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import static com.hivemq.client.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.encodeVariableByteIntegerProperty;
-import static com.hivemq.client.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.variableByteIntegerPropertyEncodedLength;
-import static com.hivemq.client.internal.mqtt.message.subscribe.MqttStatefulSubscribe.DEFAULT_NO_SUBSCRIPTION_IDENTIFIER;
-import static com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribeProperty.SUBSCRIPTION_IDENTIFIER;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.encodeVariableByteIntegerProperty;
+import static com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5.Mqtt5MessageEncoderUtil.variableByteIntegerPropertyEncodedLength;
+import static com.hivemq.client2.internal.mqtt.message.subscribe.MqttStatefulSubscribe.DEFAULT_NO_SUBSCRIPTION_IDENTIFIER;
+import static com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribeProperty.SUBSCRIPTION_IDENTIFIER;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoder.java b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoder.java
index f5b1fd2cd..a2157c20b 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttStatefulUnsubscribe;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttStatefulUnsubscribe;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttBinaryData.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttBinaryData.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttBinaryData.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttBinaryData.java
index 367909753..c4416e624 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttBinaryData.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttBinaryData.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.util.ByteBufferUtil;
+import com.hivemq.client2.internal.util.ByteBufferUtil;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttClientIdentifierImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttClientIdentifierImpl.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttClientIdentifierImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttClientIdentifierImpl.java
index 96524b3dd..9dbe3d12b 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttClientIdentifierImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttClientIdentifierImpl.java
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttClientIdentifier;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttClientIdentifier;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  * @see MqttClientIdentifier
  * @see MqttUtf8StringImpl
  */
-@Immutable
+@Unmodifiable
 public class MqttClientIdentifierImpl extends MqttUtf8StringImpl implements MqttClientIdentifier {
 
     /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttSharedTopicFilterImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttSharedTopicFilterImpl.java
similarity index 97%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttSharedTopicFilterImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttSharedTopicFilterImpl.java
index ac1daba1f..eb647b781 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttSharedTopicFilterImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttSharedTopicFilterImpl.java
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.ByteArrayUtil;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttSharedTopicFilter;
+import com.hivemq.client2.internal.util.ByteArrayUtil;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttSharedTopicFilter;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  * @see MqttSharedTopicFilter
  * @see MqttUtf8StringImpl
  */
-@Immutable
+@Unmodifiable
 public class MqttSharedTopicFilterImpl extends MqttTopicFilterImpl implements MqttSharedTopicFilter {
 
     private static final int SHARE_PREFIX_LENGTH = SHARE_PREFIX.length();
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicFilterImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicFilterImpl.java
similarity index 97%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicFilterImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicFilterImpl.java
index 1a37b0429..a4cc3e85b 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicFilterImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicFilterImpl.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
+package com.hivemq.client2.internal.mqtt.datatypes;
+
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.Arrays;
 
@@ -34,7 +34,7 @@
  * @see MqttTopicFilter
  * @see MqttUtf8StringImpl
  */
-@Immutable
+@Unmodifiable
 public class MqttTopicFilterImpl extends MqttUtf8StringImpl implements MqttTopicFilter {
 
     static final int WILDCARD_CHECK_FAILURE = -1;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicFilterImplBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicFilterImplBuilder.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicFilterImplBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicFilterImplBuilder.java
index c28b618c4..2048e7af3 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicFilterImplBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicFilterImplBuilder.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttSharedTopicFilterBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilterBuilder;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttSharedTopicFilterBuilder;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilterBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicImpl.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicImpl.java
index 18f11e3f6..e30b2c4f5 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicImpl.java
@@ -14,23 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  * @see MqttTopic
  * @see MqttUtf8StringImpl
  */
-@Immutable
+@Unmodifiable
 public class MqttTopicImpl extends MqttUtf8StringImpl implements MqttTopic {
 
     /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicImplBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicImplBuilder.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicImplBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicImplBuilder.java
index 2a1c3238d..f2a0eec58 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicImplBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicImplBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttTopicBuilder;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicIterator.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicIterator.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicIterator.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicIterator.java
index 9635d226e..de037b86d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicIterator.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicIterator.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.util.ByteArrayUtil;
+import com.hivemq.client2.internal.util.ByteArrayUtil;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Arrays;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevel.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevel.java
similarity index 97%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevel.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevel.java
index 90b89ef3e..9cf179f5b 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevel.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevel.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.util.ByteArray;
+import com.hivemq.client2.internal.util.ByteArray;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevels.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevels.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevels.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevels.java
index 325ce7100..ae5c530a6 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevels.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevels.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.util.ByteArrayUtil;
+import com.hivemq.client2.internal.util.ByteArrayUtil;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Arrays;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImpl.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImpl.java
index e3c11e19a..8e996f51f 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImpl.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  * @see Mqtt5UserProperties
  */
-@Immutable
+@Unmodifiable
 public class MqttUserPropertiesImpl implements Mqtt5UserProperties {
 
     /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImplBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImplBuilder.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImplBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImplBuilder.java
index 2c5cb44cc..9841b8b9a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImplBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImplBuilder.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
-
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty;
+package com.hivemq.client2.internal.mqtt.datatypes;
+
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperty;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertyImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertyImpl.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertyImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertyImpl.java
index 9e48a7d17..65fff4324 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertyImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertyImpl.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperty;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  * @see Mqtt5UserProperty
  */
-@Immutable
+@Unmodifiable
 public class MqttUserPropertyImpl implements Mqtt5UserProperty {
 
     /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUtf8StringImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUtf8StringImpl.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUtf8StringImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUtf8StringImpl.java
index ba3a92d08..7ef029762 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttUtf8StringImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUtf8StringImpl.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.Utf8Util;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.Utf8Util;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
@@ -35,7 +35,7 @@
  * @author Silvio Giebl
  * @see MqttUtf8String
  */
-@Immutable
+@Unmodifiable
 public class MqttUtf8StringImpl implements MqttUtf8String {
 
     /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttVariableByteInteger.java b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttVariableByteInteger.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttVariableByteInteger.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttVariableByteInteger.java
index 3ca9da933..055bd0056 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/datatypes/MqttVariableByteInteger.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/datatypes/MqttVariableByteInteger.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/exceptions/MqttClientStateExceptions.java b/src/main/java/com/hivemq/client2/internal/mqtt/exceptions/MqttClientStateExceptions.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/mqtt/exceptions/MqttClientStateExceptions.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/exceptions/MqttClientStateExceptions.java
index a09585696..56e61f496 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/exceptions/MqttClientStateExceptions.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/exceptions/MqttClientStateExceptions.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.exceptions;
+package com.hivemq.client2.internal.mqtt.exceptions;
 
-import com.hivemq.client.mqtt.exceptions.MqttClientStateException;
+import com.hivemq.client2.mqtt.exceptions.MqttClientStateException;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/exceptions/mqtt3/Mqtt3ExceptionFactory.java b/src/main/java/com/hivemq/client2/internal/mqtt/exceptions/mqtt3/Mqtt3ExceptionFactory.java
similarity index 68%
rename from src/main/java/com/hivemq/client/internal/mqtt/exceptions/mqtt3/Mqtt3ExceptionFactory.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/exceptions/mqtt3/Mqtt3ExceptionFactory.java
index 6c3083380..4e5a77596 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/exceptions/mqtt3/Mqtt3ExceptionFactory.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/exceptions/mqtt3/Mqtt3ExceptionFactory.java
@@ -14,17 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.exceptions.mqtt3;
+package com.hivemq.client2.internal.mqtt.exceptions.mqtt3;
 
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.internal.mqtt.message.connect.connack.mqtt3.Mqtt3ConnAckView;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAck;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.mqtt3.Mqtt3SubAckView;
-import com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException;
-import com.hivemq.client.mqtt.mqtt3.exceptions.*;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5MessageException;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import io.reactivex.functions.Function;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnAckView;
+import com.hivemq.client2.internal.mqtt.message.disconnect.mqtt3.Mqtt3DisconnectView;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubAckView;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubRecView;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAck;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubAckView;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubAckView;
+import com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException;
+import com.hivemq.client2.mqtt.mqtt3.exceptions.*;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5MessageException;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import io.reactivex.rxjava3.functions.Function;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -73,15 +77,15 @@ public final class Mqtt3ExceptionFactory {
             case CONNACK:
                 return new Mqtt3ConnAckException(Mqtt3ConnAckView.of((MqttConnAck) mqttMessage), message, cause);
             case DISCONNECT:
-                return new Mqtt3DisconnectException(message, cause);
+                return new Mqtt3DisconnectException(Mqtt3DisconnectView.INSTANCE, message, cause);
             case PUBACK:
-                return new Mqtt3PubAckException(message, cause);
+                return new Mqtt3PubAckException(Mqtt3PubAckView.INSTANCE, message, cause);
             case PUBREC:
-                return new Mqtt3PubRecException(message, cause);
+                return new Mqtt3PubRecException(Mqtt3PubRecView.INSTANCE, message, cause);
             case SUBACK:
                 return new Mqtt3SubAckException(Mqtt3SubAckView.of((MqttSubAck) mqttMessage), message, cause);
             case UNSUBACK:
-                return new Mqtt3UnsubAckException(message, cause);
+                return new Mqtt3UnsubAckException(Mqtt3UnsubAckView.INSTANCE, message, cause);
             default:
                 throw new IllegalStateException();
         }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/MqttChannelInitializer.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttChannelInitializer.java
similarity index 68%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/MqttChannelInitializer.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttChannelInitializer.java
index 8c39895cb..3cee57c03 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/MqttChannelInitializer.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttChannelInitializer.java
@@ -14,25 +14,27 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler;
-
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientSslConfigImpl;
-import com.hivemq.client.internal.mqtt.MqttProxyConfigImpl;
-import com.hivemq.client.internal.mqtt.MqttWebSocketConfigImpl;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttEncoder;
-import com.hivemq.client.internal.mqtt.handler.auth.MqttAuthHandler;
-import com.hivemq.client.internal.mqtt.handler.connect.MqttConnAckFlow;
-import com.hivemq.client.internal.mqtt.handler.connect.MqttConnAckSingle;
-import com.hivemq.client.internal.mqtt.handler.connect.MqttConnectHandler;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectHandler;
-import com.hivemq.client.internal.mqtt.handler.proxy.MqttProxyInitializer;
-import com.hivemq.client.internal.mqtt.handler.ssl.MqttSslInitializer;
-import com.hivemq.client.internal.mqtt.handler.websocket.MqttWebSocketInitializer;
-import com.hivemq.client.internal.mqtt.ioc.ConnectionScope;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.mqtt.exceptions.ConnectionFailedException;
-import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource;
+package com.hivemq.client2.internal.mqtt.handler;
+
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttProxyConfigImpl;
+import com.hivemq.client2.internal.mqtt.MqttTlsConfigImpl;
+import com.hivemq.client2.internal.mqtt.MqttWebSocketConfigImpl;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttEncoder;
+import com.hivemq.client2.internal.mqtt.handler.auth.MqttAuthHandler;
+import com.hivemq.client2.internal.mqtt.handler.connect.MqttConnAckFlow;
+import com.hivemq.client2.internal.mqtt.handler.connect.MqttConnAckSingle;
+import com.hivemq.client2.internal.mqtt.handler.connect.MqttConnectHandler;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectHandler;
+import com.hivemq.client2.internal.mqtt.handler.proxy.MqttProxyInitializer;
+import com.hivemq.client2.internal.mqtt.handler.tls.MqttTlsInitializer;
+import com.hivemq.client2.internal.mqtt.handler.websocket.MqttWebSocketInitializer;
+import com.hivemq.client2.internal.mqtt.ioc.ConnectionScope;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.mqtt.exceptions.ConnectionFailedException;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectSource;
 import dagger.Lazy;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandlerContext;
@@ -46,7 +48,7 @@
  * Initializes:
  * <ul>
  *   <li>the proxy handlers (optional)
- *   <li>the SSL/TLS handlers (optional)
+ *   <li>the TLS handlers (optional)
  *   <li>the WebSocket handlers (optional)
  *   <li>the basic MQTT handlers: Encoder, AuthHandler, ConnectHandler, DisconnectHandler
  * </ul>
@@ -57,6 +59,7 @@
 @ConnectionScope
 public class MqttChannelInitializer extends ChannelInboundHandlerAdapter {
 
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttChannelInitializer.class);
     private final @NotNull MqttClientConfig clientConfig;
     private final @NotNull MqttConnect connect;
     private final @NotNull MqttConnAckFlow connAckFlow;
@@ -91,6 +94,7 @@ public class MqttChannelInitializer extends ChannelInboundHandlerAdapter {
 
     @Override
     public void handlerAdded(final @NotNull ChannelHandlerContext ctx) {
+        LOGGER.debug("Initialize channel");
         ctx.pipeline().remove(this);
 
         ((SocketChannel) ctx.channel()).config()
@@ -107,18 +111,20 @@ public void handlerAdded(final @NotNull ChannelHandlerContext ctx) {
     private void initProxy(final @NotNull Channel channel) {
         final MqttProxyConfigImpl proxyConfig = clientConfig.getCurrentTransportConfig().getRawProxyConfig();
         if (proxyConfig == null) {
-            initSsl(channel);
+            initTls(channel);
         } else {
-            MqttProxyInitializer.initChannel(channel, clientConfig, proxyConfig, this::initSsl, this::onError);
+            LOGGER.trace("initProxy");
+            MqttProxyInitializer.initChannel(channel, clientConfig, proxyConfig, this::initTls, this::onError);
         }
     }
 
-    private void initSsl(final @NotNull Channel channel) {
-        final MqttClientSslConfigImpl sslConfig = clientConfig.getCurrentTransportConfig().getRawSslConfig();
-        if (sslConfig == null) {
+    private void initTls(final @NotNull Channel channel) {
+        final MqttTlsConfigImpl tlsConfig = clientConfig.getCurrentTransportConfig().getRawTlsConfig();
+        if (tlsConfig == null) {
             initWebsocket(channel);
         } else {
-            MqttSslInitializer.initChannel(channel, clientConfig, sslConfig, this::initWebsocket, this::onError);
+            LOGGER.trace("initTls");
+            MqttTlsInitializer.initChannel(channel, clientConfig, tlsConfig, this::initWebsocket, this::onError);
         }
     }
 
@@ -128,20 +134,24 @@ private void initWebsocket(final @NotNull Channel channel) {
         if (webSocketConfig == null) {
             initMqtt(channel);
         } else {
+            LOGGER.trace("initWebsocket");
             webSocketInitializer.get()
                     .initChannel(channel, clientConfig, webSocketConfig, this::initMqtt, this::onError);
         }
     }
 
     private void initMqtt(final @NotNull Channel channel) {
+        LOGGER.trace("initMqtt");
         channel.pipeline()
                 .addLast(MqttEncoder.NAME, encoder)
                 .addLast(MqttAuthHandler.NAME, authHandler)
                 .addLast(MqttConnectHandler.NAME, connectHandler)
                 .addLast(MqttDisconnectHandler.NAME, disconnectHandler);
+        LOGGER.debug("Channel initialization succeeded");
     }
 
     private void onError(final @NotNull Channel channel, final @NotNull Throwable cause) {
+        LOGGER.debug("Channel initialization failed: {}", cause);
         channel.close();
         MqttConnAckSingle.reconnect(clientConfig, MqttDisconnectSource.CLIENT, new ConnectionFailedException(cause),
                 connect, connAckFlow, channel.eventLoop());
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/MqttConnectionAwareHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttConnectionAwareHandler.java
similarity index 92%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/MqttConnectionAwareHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttConnectionAwareHandler.java
index 76d21539c..c800054fe 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/MqttConnectionAwareHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttConnectionAwareHandler.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler;
+package com.hivemq.client2.internal.mqtt.handler;
 
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/MqttSession.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttSession.java
similarity index 71%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/MqttSession.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttSession.java
index b2319d966..0fd18dd6d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/MqttSession.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttSession.java
@@ -14,19 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler;
+package com.hivemq.client2.internal.mqtt.handler;
 
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoder;
-import com.hivemq.client.internal.mqtt.handler.publish.incoming.MqttIncomingQosHandler;
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttOutgoingQosHandler;
-import com.hivemq.client.internal.mqtt.handler.subscribe.MqttSubscriptionHandler;
-import com.hivemq.client.internal.mqtt.ioc.ClientScope;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoder;
+import com.hivemq.client2.internal.mqtt.handler.publish.incoming.MqttIncomingQosHandler;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttOutgoingQosHandler;
+import com.hivemq.client2.internal.mqtt.handler.subscribe.MqttSubscriptionHandler;
+import com.hivemq.client2.internal.mqtt.ioc.ClientScope;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
 import io.netty.channel.ChannelPipeline;
 import io.netty.channel.EventLoop;
 import io.netty.util.concurrent.ScheduledFuture;
@@ -34,6 +36,7 @@
 import org.jetbrains.annotations.Nullable;
 
 import javax.inject.Inject;
+
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -42,6 +45,7 @@
 @ClientScope
 public class MqttSession {
 
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttSession.class);
     private final @NotNull MqttSubscriptionHandler subscriptionHandler;
     private final @NotNull MqttIncomingQosHandler incomingQosHandler;
     private final @NotNull MqttOutgoingQosHandler outgoingQosHandler;
@@ -65,10 +69,16 @@ public void startOrResume(
             final @NotNull MqttClientConnectionConfig connectionConfig,
             final @NotNull ChannelPipeline pipeline,
             final @NotNull EventLoop eventLoop) {
-
-        if (hasSession && !connAck.isSessionPresent()) {
-            final String message = "Session expired as CONNACK did not contain the session present flag.";
-            end(new MqttSessionExpiredException(message, new Mqtt5ConnAckException(connAck, message)));
+        if (hasSession) {
+            if (!connAck.isSessionPresent()) {
+                final String message = "Session expired as CONNACK did not contain the session present flag.";
+                end(new MqttSessionExpiredException(message, new Mqtt5ConnAckException(connAck, message)));
+                LOGGER.trace("Session START");
+            } else {
+                LOGGER.trace("Session RESUME");
+            }
+        } else {
+            LOGGER.trace("Session START");
         }
         hasSession = true;
 
@@ -109,6 +119,7 @@ public void expire(
 
     @CallByThread("Netty EventLoop")
     private void end(final @NotNull Throwable cause) {
+        LOGGER.debug("Session END, cause {}", cause);
         if (hasSession) {
             hasSession = false;
             outgoingQosHandler.onSessionEnd(cause);
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/MqttSessionAwareHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttSessionAwareHandler.java
similarity index 87%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/MqttSessionAwareHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttSessionAwareHandler.java
index 4da38e553..caa68ae65 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/MqttSessionAwareHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/MqttSessionAwareHandler.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler;
+package com.hivemq.client2.internal.mqtt.handler;
 
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.EventLoop;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/AbstractMqttAuthHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/AbstractMqttAuthHandler.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/auth/AbstractMqttAuthHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/AbstractMqttAuthHandler.java
index b7155f92a..a6516ed77 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/AbstractMqttAuthHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/AbstractMqttAuthHandler.java
@@ -14,23 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.auth;
-
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.internal.mqtt.handler.util.MqttTimeoutInboundHandler;
-import com.hivemq.client.internal.mqtt.message.auth.MqttAuth;
-import com.hivemq.client.internal.mqtt.message.auth.MqttAuthBuilder;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5AuthException;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5Auth;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.handler.auth;
+
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.handler.util.MqttTimeoutInboundHandler;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttAuthBuilder;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5AuthException;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5Auth;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.channel.ChannelHandlerContext;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -41,7 +41,7 @@
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
-import static com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode.CONTINUE_AUTHENTICATION;
+import static com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode.CONTINUE_AUTHENTICATION;
 
 /**
  * Base for enhanced auth handling according to the MQTT 5 specification.
@@ -50,7 +50,7 @@
  */
 abstract class AbstractMqttAuthHandler extends MqttTimeoutInboundHandler implements MqttAuthHandler {
 
-    static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(AbstractMqttAuthHandler.class);
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(AbstractMqttAuthHandler.class);
 
     enum MqttAuthState {
         NONE,
@@ -72,7 +72,9 @@ enum MqttAuthState {
     }
 
     /**
-     * Handles an incoming AUTH message. Sends a DISCONNECT message if the AUTH message is not valid.
+     * Handles an incoming AUTH message.
+     * <p>
+     * Sends a DISCONNECT message if the AUTH message is not valid.
      *
      * @param ctx  the channel handler context.
      * @param auth the incoming AUTH message.
@@ -114,17 +116,21 @@ private boolean validateAuth(final @NotNull ChannelHandlerContext ctx, final @No
     }
 
     /**
-     * Handles an incoming AUTH message with the Reason Code CONTINUE AUTHENTICATION.
+     * Handles an incoming AUTH message with the reason code CONTINUE AUTHENTICATION.
      * <ul>
-     * <li>Calls {@link Mqtt5EnhancedAuthMechanism#onContinue(Mqtt5ClientConfig, Mqtt5Auth, Mqtt5AuthBuilder)}.</li>
-     * <li>Sends a new AUTH message if the enhanced auth mechanism accepted the incoming AUTH message.</li>
-     * <li>Otherwise sends a DISCONNECT message.</li>
+     *   <li>Sends a DISCONNECT message if client side authentication is pending, or
+     *   <li>Calls {@link Mqtt5EnhancedAuthMechanism#onContinue(Mqtt5ClientConfig, Mqtt5Auth, Mqtt5AuthBuilder)} which
+     *     can add enhanced auth data to the outgoing AUTH message, then
+     *   <li>Sends the AUTH message with the reason code CONTINUE AUTHENTICATION, or
+     *   <li>Sends a DISCONNECT message if the enhanced auth mechanism rejected the incoming AUTH message, which leads
+     *     to {@link #onDisconnectEvent} being called.
      * </ul>
      *
      * @param ctx  the channel handler context.
-     * @param auth the received AUTH message.
+     * @param auth the incoming AUTH message.
      */
     private void readAuthContinue(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttAuth auth) {
+        LOGGER.debug("Read AUTH continue {}", auth);
         if (state != MqttAuthState.WAIT_FOR_SERVER) {
             MqttDisconnectUtil.disconnect(ctx.channel(), Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
                     new Mqtt5AuthException(auth, "Must not receive AUTH with reason code CONTINUE_AUTHENTICATION " +
@@ -136,14 +142,16 @@ private void readAuthContinue(final @NotNull ChannelHandlerContext ctx, final @N
         state = MqttAuthState.IN_PROGRESS_RESPONSE;
         callMechanismFutureResult(() -> authMechanism.onContinue(clientConfig, auth, authBuilder), ctx2 -> {
             state = MqttAuthState.WAIT_FOR_SERVER;
-            ctx2.writeAndFlush(authBuilder.build()).addListener(this);
+            MqttAuth auth2 = authBuilder.build();
+            LOGGER.debug("Write AUTH {}", auth2);
+            ctx2.writeAndFlush(auth2).addListener(this);
 
         }, (ctx2, throwable) -> MqttDisconnectUtil.disconnect(ctx2.channel(), Mqtt5DisconnectReasonCode.NOT_AUTHORIZED,
                 new Mqtt5AuthException(auth, "Server auth not accepted.")));
     }
 
     /**
-     * Disconnects on an incoming AUTH message with the Reason Code SUCCESS.
+     * Handles an incoming AUTH message with the reason code SUCCESS.
      *
      * @param ctx  the channel handler context.
      * @param auth the incoming AUTH message.
@@ -151,7 +159,7 @@ private void readAuthContinue(final @NotNull ChannelHandlerContext ctx, final @N
     abstract void readAuthSuccess(@NotNull ChannelHandlerContext ctx, @NotNull MqttAuth auth);
 
     /**
-     * Disconnects on an incoming AUTH message with the Reason Code REAUTHENTICATE.
+     * Handles an incoming AUTH message with the reason code REAUTHENTICATE.
      *
      * @param ctx  the channel handler context.
      * @param auth the incoming AUTH message.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttAuthHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttAuthHandler.java
similarity index 93%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttAuthHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttAuthHandler.java
index db2038ebb..6805568d8 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttAuthHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttAuthHandler.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.auth;
+package com.hivemq.client2.internal.mqtt.handler.auth;
 
 import io.netty.channel.ChannelHandler;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttConnectAuthHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttConnectAuthHandler.java
similarity index 66%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttConnectAuthHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttConnectAuthHandler.java
index c8ad5076b..7a6a48c30 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttConnectAuthHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttConnectAuthHandler.java
@@ -14,30 +14,32 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.auth;
-
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.internal.mqtt.ioc.ConnectionScope;
-import com.hivemq.client.internal.mqtt.message.auth.MqttAuth;
-import com.hivemq.client.internal.mqtt.message.auth.MqttEnhancedAuthBuilder;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttStatefulConnect;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.internal.netty.DefaultChannelOutboundHandler;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.exceptions.ConnectionFailedException;
-import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5AuthException;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuth;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuthBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.handler.auth;
+
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.ioc.ConnectionScope;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttEnhancedAuthBuilder;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttStatefulConnect;
+import com.hivemq.client2.internal.netty.DefaultChannelOutboundHandler;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.exceptions.ConnectionFailedException;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectSource;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5AuthException;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuthBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelPromise;
 import org.jetbrains.annotations.NotNull;
@@ -54,6 +56,8 @@
 @ConnectionScope
 public class MqttConnectAuthHandler extends AbstractMqttAuthHandler implements DefaultChannelOutboundHandler {
 
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttConnectAuthHandler.class);
+
     @Inject
     MqttConnectAuthHandler(final @NotNull MqttClientConfig clientConfig, final @NotNull MqttConnect connect) {
         super(clientConfig, Checks.stateNotNull(connect.getRawEnhancedAuthMechanism(), "Auth mechanism"));
@@ -75,9 +79,11 @@ public void write(
     /**
      * Handles the outgoing CONNECT message.
      * <ul>
-     * <li>Calls {@link Mqtt5EnhancedAuthMechanism#onAuth(Mqtt5ClientConfig, Mqtt5Connect, Mqtt5EnhancedAuthBuilder)}
-     * which adds enhanced auth data to the CONNECT message.</li>
-     * <li>Sends the CONNECT message with the enhanced auth data.</li>
+     *   <li>Calls {@link Mqtt5EnhancedAuthMechanism#onAuth(Mqtt5ClientConfig, Mqtt5Connect, Mqtt5EnhancedAuthBuilder)}
+     *     which can add enhanced auth data to the outgoing CONNECT message, then
+     *   <li>Sends the CONNECT message with the enhanced auth data, or
+     *   <li>Closes the connection with a {@link ConnectionFailedException} if the enhanced auth mechanism rejected the
+     *     CONNECT message, which leads to {@link #onDisconnectEvent} being called.
      * </ul>
      *
      * @param connect the CONNECT message.
@@ -90,6 +96,7 @@ private void writeConnect(final @NotNull MqttConnect connect, final @NotNull Cha
             state = MqttAuthState.WAIT_FOR_SERVER;
             final MqttStatefulConnect statefulConnect =
                     connect.createStateful(clientConfig.getRawClientIdentifier(), enhancedAuthBuilder.build());
+            LOGGER.debug("Write CONNECT {}", statefulConnect);
             ctx.writeAndFlush(statefulConnect, promise).addListener(this);
 
         }, (ctx, throwable) -> MqttDisconnectUtil.close(ctx.channel(), new ConnectionFailedException(throwable)));
@@ -108,18 +115,14 @@ public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull
 
     /**
      * Handles the incoming CONNACK message.
-     * <ul>
-     * <li>Calls {@link Mqtt5EnhancedAuthMechanism#onAuthRejected(Mqtt5ClientConfig, Mqtt5ConnAck)} and closes the
-     * channel if the CONNACK message contains an Error Code.</li>
-     * <li>Sends a DISCONNECT message if the enhanced auth data of the CONNACK message is not valid.</li>
-     * <li>Otherwise calls {@link Mqtt5EnhancedAuthMechanism#onAuthSuccess(Mqtt5ClientConfig, Mqtt5ConnAck)}.</li>
-     * <li>Sends a DISCONNECT message if the enhanced auth mechanism did not accept the enhanced auth data.</li>
-     * </ul>
+     * <p>
+     * Sends a DISCONNECT message if the CONNACK message has a successful reason code but is not valid.
      *
      * @param ctx     the channel handler context.
      * @param connAck the received CONNACK message.
      */
     private void readConnAck(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttConnAck connAck) {
+        LOGGER.debug("Read CONNACK {}", connAck);
         cancelTimeout();
 
         if (connAck.getReasonCode().isError()) {
@@ -129,6 +132,16 @@ private void readConnAck(final @NotNull ChannelHandlerContext ctx, final @NotNul
         }
     }
 
+    /**
+     * Handles the incoming CONNACK message with an error reason code.
+     * <ul>
+     *   <li>Calls {@link Mqtt5EnhancedAuthMechanism#onAuthRejected(Mqtt5ClientConfig, Mqtt5ConnAck)} and
+     *   <li>Fires a disconnect event with a {@link Mqtt5ConnAckException} which leads to closing the connection.
+     * </ul>
+     *
+     * @param ctx     the channel handler context.
+     * @param connAck the received CONNACK message.
+     */
     private void readConnAckError(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttConnAck connAck) {
         callMechanism(() -> authMechanism.onAuthRejected(clientConfig, connAck));
         state = MqttAuthState.NONE;
@@ -138,6 +151,18 @@ private void readConnAckError(final @NotNull ChannelHandlerContext ctx, final @N
                 MqttDisconnectSource.SERVER);
     }
 
+    /**
+     * Handles the incoming CONNACK message with a successful reason code.
+     * <ul>
+     *   <li>Sends a DISCONNECT message if client side authentication is pending, or
+     *   <li>Calls {@link Mqtt5EnhancedAuthMechanism#onAuthSuccess(Mqtt5ClientConfig, Mqtt5ConnAck)}, then
+     *   <li>Fires the CONNACK message to the next handler, or
+     *   <li>Sends a DISCONNECT message if the enhanced auth mechanism rejected the CONNACK message.
+     * </ul>
+     *
+     * @param ctx     the channel handler context.
+     * @param connAck the received CONNACK message.
+     */
     private void readConnAckSuccess(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttConnAck connAck) {
         if (state != MqttAuthState.WAIT_FOR_SERVER) {
             MqttDisconnectUtil.disconnect(ctx.channel(), Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
@@ -157,7 +182,7 @@ private void readConnAckSuccess(final @NotNull ChannelHandlerContext ctx, final
     }
 
     /**
-     * Validates the enhanced auth data of an incoming CONNACK message.
+     * Validates the enhanced auth data of the incoming CONNACK message.
      * <p>
      * If validation fails, disconnection and closing of the channel is already handled.
      *
@@ -181,35 +206,37 @@ private boolean validateConnAck(final @NotNull ChannelHandlerContext ctx, final
     }
 
     /**
-     * Disconnects on an incoming AUTH message with the Reason Code SUCCESS.
+     * Disconnects on an incoming AUTH message with the reason code SUCCESS.
      *
      * @param ctx  the channel handler context.
      * @param auth the incoming AUTH message.
      */
     @Override
     void readAuthSuccess(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttAuth auth) {
+        LOGGER.debug("Read AUTH success {}", auth);
         MqttDisconnectUtil.disconnect(ctx.channel(), Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
                 new Mqtt5AuthException(auth, "Must not receive AUTH with reason code SUCCESS during connect auth."));
     }
 
     /**
-     * Disconnects on an incoming AUTH message with the Reason Code REAUTHENTICATE.
+     * Disconnects on an incoming AUTH message with the reason code REAUTHENTICATE.
      *
      * @param ctx  the channel handler context.
      * @param auth the incoming AUTH message.
      */
     @Override
     void readReAuth(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttAuth auth) {
+        LOGGER.debug("Read re-AUTH {}", auth);
         MqttDisconnectUtil.disconnect(ctx.channel(), Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
                 new Mqtt5AuthException(auth,
                         "Must not receive AUTH with reason code REAUTHENTICATE during connect auth."));
     }
 
     /**
-     * Calls {@link Mqtt5EnhancedAuthMechanism#onAuthError(Mqtt5ClientConfig, Throwable)} with the cause why the channel
-     * was closed if auth is still in progress.
+     * Calls {@link Mqtt5EnhancedAuthMechanism#onAuthError(Mqtt5ClientConfig, Throwable)} with the cause why the
+     * connection was disconnected if auth is still in progress.
      *
-     * @param disconnectEvent the channel close event.
+     * @param disconnectEvent the disconnect event.
      */
     @Override
     protected void onDisconnectEvent(
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttDisconnectOnAuthHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttDisconnectOnAuthHandler.java
similarity index 74%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttDisconnectOnAuthHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttDisconnectOnAuthHandler.java
index 8ffa3adb0..672f7f3ae 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttDisconnectOnAuthHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttDisconnectOnAuthHandler.java
@@ -14,14 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.auth;
+package com.hivemq.client2.internal.mqtt.handler.auth;
 
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.internal.mqtt.message.auth.MqttAuth;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5AuthException;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttAuth;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5AuthException;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
@@ -40,6 +42,8 @@
 @Singleton
 public class MqttDisconnectOnAuthHandler extends ChannelInboundHandlerAdapter implements MqttAuthHandler {
 
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttDisconnectOnAuthHandler.class);
+
     @Inject
     MqttDisconnectOnAuthHandler() {}
 
@@ -55,12 +59,14 @@ public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull
     }
 
     private void readAuth(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttAuth auth) {
+        LOGGER.debug("Read AUTH {}", auth);
         MqttDisconnectUtil.disconnect(ctx.channel(), Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
                 new Mqtt5AuthException(auth, "Server must not send AUTH"));
     }
 
     private void readConnAck(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttConnAck connAck) {
         if (connAck.getRawEnhancedAuth() != null) {
+            LOGGER.debug("Read CONNACK with auth {}", connAck);
             MqttDisconnectUtil.disconnect(ctx.channel(), Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
                     new Mqtt5ConnAckException(connAck, "Server must not include auth in CONNACK"));
         } else {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttReAuthCompletable.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttReAuthCompletable.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttReAuthCompletable.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttReAuthCompletable.java
index f8335c314..ee84aec60 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttReAuthCompletable.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttReAuthCompletable.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.auth;
+package com.hivemq.client2.internal.mqtt.handler.auth;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.exceptions.MqttClientStateExceptions;
-import com.hivemq.client.internal.rx.CompletableFlow;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.exceptions.MqttClientStateExceptions;
+import com.hivemq.client2.internal.rx.CompletableFlow;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandler;
-import io.reactivex.Completable;
-import io.reactivex.CompletableObserver;
-import io.reactivex.internal.disposables.EmptyDisposable;
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.CompletableObserver;
+import io.reactivex.rxjava3.internal.disposables.EmptyDisposable;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttReAuthHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttReAuthHandler.java
similarity index 65%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttReAuthHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttReAuthHandler.java
index 3bd0ebcb0..5f5bafec1 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/auth/MqttReAuthHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/auth/MqttReAuthHandler.java
@@ -14,29 +14,31 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.auth;
-
-import com.hivemq.client.internal.mqtt.exceptions.MqttClientStateExceptions;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.internal.mqtt.ioc.ConnectionScope;
-import com.hivemq.client.internal.mqtt.message.auth.MqttAuth;
-import com.hivemq.client.internal.mqtt.message.auth.MqttAuthBuilder;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.rx.CompletableFlow;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5AuthException;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5Auth;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.handler.auth;
+
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.exceptions.MqttClientStateExceptions;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.ioc.ConnectionScope;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttAuthBuilder;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.rx.CompletableFlow;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5AuthException;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5Auth;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.channel.ChannelHandlerContext;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import static com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode.CONTINUE_AUTHENTICATION;
-import static com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode.REAUTHENTICATE;
+import static com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode.CONTINUE_AUTHENTICATION;
+import static com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode.REAUTHENTICATE;
 
 /**
  * Enhanced reauth handling according to the MQTT 5 specification.
@@ -46,6 +48,8 @@
 @ConnectionScope
 public class MqttReAuthHandler extends AbstractMqttAuthHandler {
 
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttReAuthHandler.class);
+
     private @Nullable CompletableFlow flow;
 
     MqttReAuthHandler(final @NotNull MqttConnectAuthHandler connectAuthHandler) {
@@ -59,9 +63,15 @@ void reauth(final @NotNull CompletableFlow flow) {
     }
 
     /**
-     * Sends a AUTH message with the Reason Code REAUTHENTICATE.
-     * <p>
-     * Calls {@link Mqtt5EnhancedAuthMechanism#onReAuth(Mqtt5ClientConfig, Mqtt5AuthBuilder)}.
+     * <ul>
+     *   <li>Errors the flow if the client is not connected, or
+     *   <li>Errors the flow if reauthentication is pending, or
+     *   <li>Calls {@link Mqtt5EnhancedAuthMechanism#onReAuth(Mqtt5ClientConfig, Mqtt5AuthBuilder)} which can add
+     *     enhanced auth data to the outgoing AUTH message, then
+     *   <li>Sends the AUTH message with the reason code REAUTHENTICATE, or
+     *   <li>Calls {@link Mqtt5EnhancedAuthMechanism#onReAuthError(Mqtt5ClientConfig, Throwable)} if the enhanced auth
+     *     mechanism rejected the reauthentication (it does not disconnect).
+     * </ul>
      *
      * @param flow the flow for the reauth result.
      */
@@ -81,7 +91,9 @@ private void writeReAuth(final @NotNull CompletableFlow flow) {
         state = MqttAuthState.IN_PROGRESS_INIT;
         callMechanismFuture(() -> authMechanism.onReAuth(clientConfig, authBuilder), ctx -> {
             state = MqttAuthState.WAIT_FOR_SERVER;
-            ctx.writeAndFlush(authBuilder.build()).addListener(this);
+            MqttAuth auth = authBuilder.build();
+            LOGGER.debug("Write re-AUTH {}", auth);
+            ctx.writeAndFlush(auth).addListener(this);
         }, (ctx, throwable) -> {
             callMechanism(() -> authMechanism.onReAuthError(clientConfig, throwable));
             state = MqttAuthState.NONE;
@@ -102,10 +114,13 @@ public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull
     }
 
     /**
-     * Handles an incoming AUTH message with the Reason Code SUCCESS.
+     * Handles an incoming AUTH message with the reason code SUCCESS.
      * <ul>
-     * <li>Calls {@link Mqtt5EnhancedAuthMechanism#onReAuthSuccess(Mqtt5ClientConfig, Mqtt5Auth)}.</li>
-     * <li>Sends a DISCONNECT message if the enhanced auth mechanism did not accept the AUTH message.</li>
+     *   <li>Sends a DISCONNECT message if client side authentication is pending, or
+     *   <li>Calls {@link Mqtt5EnhancedAuthMechanism#onReAuthSuccess(Mqtt5ClientConfig, Mqtt5Auth)}, then
+     *   <li>Completes the flow, or
+     *   <li>Sends a DISCONNECT message if the enhanced auth mechanism rejected the incoming AUTH message, which leads
+     *     to {@link #onDisconnectEvent} being called.
      * </ul>
      *
      * @param ctx  the channel handler context.
@@ -113,6 +128,7 @@ public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull
      */
     @Override
     void readAuthSuccess(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttAuth auth) {
+        LOGGER.debug("Read AUTH success {}", auth);
         if (state != MqttAuthState.WAIT_FOR_SERVER) {
             MqttDisconnectUtil.disconnect(ctx.channel(), Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
                     new Mqtt5AuthException(auth,
@@ -138,11 +154,12 @@ void readAuthSuccess(final @NotNull ChannelHandlerContext ctx, final @NotNull Mq
     /**
      * Handles an incoming AUTH message with the Reason Code REAUTHENTICATE.
      * <ul>
-     * <li>Sends a DISCONNECT message if server reauth is not allowed.</li>
-     * <li>Otherwise calls
-     * {@link Mqtt5EnhancedAuthMechanism#onServerReAuth(Mqtt5ClientConfig, Mqtt5Auth, Mqtt5AuthBuilder)}.</li>
-     * <li>Sends a new AUTH message if the enhanced auth mechanism accepted the incoming AUTH message.</li>
-     * <li>Otherwise sends a DISCONNECT message.</li>
+     *   <li>Sends a DISCONNECT message if reauthentication is already pending, or
+     *   <li>Calls {@link Mqtt5EnhancedAuthMechanism#onServerReAuth(Mqtt5ClientConfig, Mqtt5Auth, Mqtt5AuthBuilder)}
+     *     which can add enhanced auth data to the outgoing AUTH message, then
+     *   <li>Sends the AUTH message with the reason code CONTINUE AUTHENTICATION, or
+     *   <li>Sends a DISCONNECT message if the enhanced auth mechanism rejected the incoming AUTH message, which leads
+     *     to {@link #onDisconnectEvent} being called.
      * </ul>
      *
      * @param ctx  the channel handler context.
@@ -150,11 +167,7 @@ void readAuthSuccess(final @NotNull ChannelHandlerContext ctx, final @NotNull Mq
      */
     @Override
     void readReAuth(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttAuth auth) {
-        if (!clientConfig.getAdvancedConfig().isAllowServerReAuth()) {
-            MqttDisconnectUtil.disconnect(ctx.channel(), Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
-                    new Mqtt5AuthException(auth, "Must not receive AUTH with reason code REAUTHENTICATE."));
-            return;
-        }
+        LOGGER.debug("Read re-AUTH {}", auth);
         if (state != MqttAuthState.NONE) {
             MqttDisconnectUtil.disconnect(ctx.channel(), Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
                     new Mqtt5AuthException(auth,
@@ -166,7 +179,9 @@ void readReAuth(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttAut
         state = MqttAuthState.IN_PROGRESS_INIT;
         callMechanismFutureResult(() -> authMechanism.onServerReAuth(clientConfig, auth, authBuilder), ctx2 -> {
             state = MqttAuthState.WAIT_FOR_SERVER;
-            ctx2.writeAndFlush(authBuilder.build()).addListener(this);
+            MqttAuth auth2 = authBuilder.build();
+            LOGGER.debug("Write AUTH {}", auth2);
+            ctx2.writeAndFlush(auth2).addListener(this);
 
         }, (ctx2, throwable) -> MqttDisconnectUtil.disconnect(ctx2.channel(), Mqtt5DisconnectReasonCode.NOT_AUTHORIZED,
                 new Mqtt5AuthException(auth, "Server AUTH with reason code REAUTHENTICATE not accepted.")));
@@ -181,6 +196,7 @@ void readReAuth(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttAut
      * @param disconnect the incoming DISCONNECT message.
      */
     private void readDisconnect(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttDisconnect disconnect) {
+        LOGGER.trace("Read DISCONNECT {}", disconnect);
         cancelTimeout();
 
         if (state != MqttAuthState.NONE) {
@@ -193,7 +209,7 @@ private void readDisconnect(final @NotNull ChannelHandlerContext ctx, final @Not
 
     /**
      * Calls {@link Mqtt5EnhancedAuthMechanism#onReAuthError(Mqtt5ClientConfig, Throwable)} with the cause why the
-     * channel was closed if reauth is still in progress.
+     * connection was disconnected if reauth is still in progress.
      *
      * @param disconnectEvent the channel close event.
      */
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/connect/MqttConnAckFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/connect/MqttConnAckFlow.java
similarity index 91%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/connect/MqttConnAckFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/connect/MqttConnAckFlow.java
index b6d2215ca..11b736260 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/connect/MqttConnAckFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/connect/MqttConnAckFlow.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.connect;
+package com.hivemq.client2.internal.mqtt.handler.connect;
 
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import io.reactivex.SingleObserver;
-import io.reactivex.disposables.Disposable;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import io.reactivex.rxjava3.core.SingleObserver;
+import io.reactivex.rxjava3.disposables.Disposable;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/connect/MqttConnAckSingle.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/connect/MqttConnAckSingle.java
similarity index 77%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/connect/MqttConnAckSingle.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/connect/MqttConnAckSingle.java
index 31e8f13c0..51e4c15d3 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/connect/MqttConnAckSingle.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/connect/MqttConnAckSingle.java
@@ -14,32 +14,32 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.connect;
-
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientTransportConfigImpl;
-import com.hivemq.client.internal.mqtt.exceptions.MqttClientStateExceptions;
-import com.hivemq.client.internal.mqtt.lifecycle.MqttClientDisconnectedContextImpl;
-import com.hivemq.client.internal.mqtt.lifecycle.MqttClientReconnector;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.mqtt.exceptions.ConnectionFailedException;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedContext;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener;
-import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
+package com.hivemq.client2.internal.mqtt.handler.connect;
+
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttTransportConfigImpl;
+import com.hivemq.client2.internal.mqtt.exceptions.MqttClientStateExceptions;
+import com.hivemq.client2.internal.mqtt.lifecycle.MqttDisconnectedContextImpl;
+import com.hivemq.client2.internal.mqtt.lifecycle.MqttReconnector;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.mqtt.exceptions.ConnectionFailedException;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectSource;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedContext;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedListener;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.EventLoop;
-import io.reactivex.Single;
-import io.reactivex.SingleObserver;
-import io.reactivex.internal.disposables.EmptyDisposable;
+import io.reactivex.rxjava3.core.Single;
+import io.reactivex.rxjava3.core.SingleObserver;
+import io.reactivex.rxjava3.internal.disposables.EmptyDisposable;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.concurrent.TimeUnit;
 
-import static com.hivemq.client.mqtt.MqttClientState.*;
+import static com.hivemq.client2.mqtt.MqttClientState.*;
 
 /**
  * @author Silvio Giebl
@@ -85,14 +85,16 @@ private static void connect(
                     .build()
                     .bootstrap();
 
-            final MqttClientTransportConfigImpl transportConfig = clientConfig.getCurrentTransportConfig();
+            final MqttTransportConfigImpl transportConfig = clientConfig.getCurrentTransportConfig();
 
+            LOGGER.trace("connect: schedule CONNECT {} to {}", connect, transportConfig.getRemoteAddress());
             bootstrap.group(eventLoop)
                     .connect(transportConfig.getRemoteAddress(), transportConfig.getRawLocalAddress())
                     .addListener(future -> {
                         final Throwable cause = future.cause();
                         if (cause != null) {
                             final ConnectionFailedException e = new ConnectionFailedException(cause);
+                            LOGGER.debug("connect failed: {}, remote address {}", e, transportConfig.getRemoteAddress());
                             if (eventLoop.inEventLoop()) {
                                 reconnect(clientConfig, MqttDisconnectSource.CLIENT, e, connect, flow, eventLoop);
                             } else {
@@ -137,12 +139,12 @@ private static void reconnect(
             final @Nullable MqttConnAckFlow flow,
             final @NotNull EventLoop eventLoop) {
 
-        final MqttClientReconnector reconnector =
-                new MqttClientReconnector(eventLoop, attempts, connect, clientConfig.getCurrentTransportConfig());
-        final MqttClientDisconnectedContext context =
-                MqttClientDisconnectedContextImpl.of(clientConfig, source, cause, reconnector);
+        final MqttReconnector reconnector =
+                new MqttReconnector(eventLoop, attempts, connect, clientConfig.getCurrentTransportConfig());
+        final MqttDisconnectedContext context =
+                MqttDisconnectedContextImpl.of(clientConfig, source, cause, reconnector);
 
-        for (final MqttClientDisconnectedListener disconnectedListener : clientConfig.getDisconnectedListeners()) {
+        for (final MqttDisconnectedListener disconnectedListener : clientConfig.getDisconnectedListeners()) {
             try {
                 disconnectedListener.onDisconnected(context);
             } catch (final Throwable t) {
@@ -151,6 +153,7 @@ private static void reconnect(
         }
 
         if (reconnector.isReconnect()) {
+            LOGGER.debug("Schedule reconnect.");
             clientConfig.getRawState().set(DISCONNECTED_RECONNECT);
             eventLoop.schedule(() -> {
                 reconnector.getFuture().whenComplete((ignored, throwable) -> {
@@ -177,6 +180,7 @@ private static void reconnect(
             clientConfig.setRepublishIfSessionExpired(reconnector.isRepublishIfSessionExpired());
             reconnector.afterOnDisconnected();
         } else {
+            LOGGER.debug("Do not schedule reconnect.");
             clientConfig.getRawState().set(DISCONNECTED);
             clientConfig.releaseEventLoop();
             if (flow != null) {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/connect/MqttConnectHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/connect/MqttConnectHandler.java
similarity index 80%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/connect/MqttConnectHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/connect/MqttConnectHandler.java
index ff5d470a3..b06c5f086 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/connect/MqttConnectHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/connect/MqttConnectHandler.java
@@ -14,35 +14,35 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.connect;
-
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoder;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttEncoder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttClientIdentifierImpl;
-import com.hivemq.client.internal.mqtt.handler.MqttSession;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.internal.mqtt.handler.ping.MqttPingHandler;
-import com.hivemq.client.internal.mqtt.handler.util.MqttTimeoutInboundHandler;
-import com.hivemq.client.internal.mqtt.ioc.ConnectionScope;
-import com.hivemq.client.internal.mqtt.lifecycle.MqttClientConnectedContextImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessage;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictions;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAckRestrictions;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.MqttClientState;
-import com.hivemq.client.mqtt.MqttVersion;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedContext;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedListener;
-import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.handler.connect;
+
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoder;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttEncoder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttClientIdentifierImpl;
+import com.hivemq.client2.internal.mqtt.handler.MqttSession;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.handler.ping.MqttPingHandler;
+import com.hivemq.client2.internal.mqtt.handler.util.MqttTimeoutInboundHandler;
+import com.hivemq.client2.internal.mqtt.ioc.ConnectionScope;
+import com.hivemq.client2.internal.mqtt.lifecycle.MqttConnectedContextImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessage;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAckRestrictions;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectRestrictions;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.MqttClientState;
+import com.hivemq.client2.mqtt.MqttVersion;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedContext;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedListener;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectSource;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandlerContext;
 import org.jetbrains.annotations.NotNull;
@@ -118,13 +118,16 @@ private void writeConnect(final @NotNull ChannelHandlerContext ctx) {
         if (!connectWritten) {
             connectWritten = true;
             connectFlushTime = System.nanoTime();
-            ctx.writeAndFlush((connect.getRawEnhancedAuthMechanism() == null) ?
-                    connect.createStateful(clientConfig.getRawClientIdentifier(), null) : connect).addListener(this);
+            Object connectObj = connect.getRawEnhancedAuthMechanism() == null ?
+                connect.createStateful(clientConfig.getRawClientIdentifier(), null) :  connect;
+            LOGGER.debug("Write CONNECT {} to {}", connectObj, ctx.channel().remoteAddress());
+            ctx.writeAndFlush(connectObj).addListener(this);
         }
     }
 
     @Override
     protected void operationSuccessful(final @NotNull ChannelHandlerContext ctx) {
+        LOGGER.trace("operationSuccessful");
         if (connect.getRawEnhancedAuthMechanism() == null) {
             scheduleTimeout(ctx.channel());
         }
@@ -154,6 +157,7 @@ public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull
      * @param channel the channel.
      */
     private void readConnAck(final @NotNull MqttConnAck connAck, final @NotNull Channel channel) {
+        LOGGER.debug("Read CONNACK {} from {}", connAck, ctx.channel().remoteAddress());
         if (connAck.getReasonCode().isError()) {
             MqttDisconnectUtil.fireDisconnectEvent(channel, new Mqtt5ConnAckException(connAck,
                             "CONNECT failed as CONNACK contained an Error Code: " + connAck.getReasonCode() + "."),
@@ -176,11 +180,10 @@ private void readConnAck(final @NotNull MqttConnAck connAck, final @NotNull Chan
 
             clientConfig.getRawState().set(MqttClientState.CONNECTED);
 
-            final ImmutableList<MqttClientConnectedListener> connectedListeners = clientConfig.getConnectedListeners();
+            final ImmutableList<MqttConnectedListener> connectedListeners = clientConfig.getConnectedListeners();
             if (!connectedListeners.isEmpty()) {
-                final MqttClientConnectedContext context =
-                        MqttClientConnectedContextImpl.of(clientConfig, connect, connAck);
-                for (final MqttClientConnectedListener connectedListener : connectedListeners) {
+                final MqttConnectedContext context = MqttConnectedContextImpl.of(clientConfig, connect, connAck);
+                for (final MqttConnectedListener connectedListener : connectedListeners) {
                     try {
                         connectedListener.onConnected(context);
                     } catch (final Throwable t) {
@@ -205,6 +208,7 @@ private void readConnAck(final @NotNull MqttConnAck connAck, final @NotNull Chan
      * @param channel the channel.
      */
     private void readOtherThanConnAck(final @NotNull Object msg, final @NotNull Channel channel) {
+        LOGGER.error("Read NON CONNACK {} from {}", msg, ctx.channel().remoteAddress());
         if (msg instanceof MqttMessage) {
             MqttDisconnectUtil.disconnect(channel, Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
                     ((MqttMessage) msg).getType() + " message must not be received before CONNACK");
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectCompletable.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectCompletable.java
similarity index 78%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectCompletable.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectCompletable.java
index 6b70bac2e..14cb7e09a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectCompletable.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectCompletable.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.disconnect;
+package com.hivemq.client2.internal.mqtt.handler.disconnect;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.exceptions.MqttClientStateExceptions;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.rx.CompletableFlow;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.exceptions.MqttClientStateExceptions;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.rx.CompletableFlow;
 import io.netty.channel.Channel;
-import io.reactivex.Completable;
-import io.reactivex.CompletableObserver;
-import io.reactivex.internal.disposables.EmptyDisposable;
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.CompletableObserver;
+import io.reactivex.rxjava3.internal.disposables.EmptyDisposable;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectEvent.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectEvent.java
similarity index 86%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectEvent.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectEvent.java
index 69a31479b..829dad17e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectEvent.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectEvent.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.disconnect;
+package com.hivemq.client2.internal.mqtt.handler.disconnect;
 
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.rx.CompletableFlow;
-import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5DisconnectException;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.rx.CompletableFlow;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectSource;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5DisconnectException;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectHandler.java
similarity index 74%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectHandler.java
index 145c8afe0..2def0398b 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectHandler.java
@@ -14,30 +14,31 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.disconnect;
-
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.exceptions.MqttClientStateExceptions;
-import com.hivemq.client.internal.mqtt.handler.MqttConnectionAwareHandler;
-import com.hivemq.client.internal.mqtt.handler.MqttSession;
-import com.hivemq.client.internal.mqtt.handler.connect.MqttConnAckSingle;
-import com.hivemq.client.internal.mqtt.ioc.ConnectionScope;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictions;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.rx.CompletableFlow;
-import com.hivemq.client.mqtt.MqttVersion;
-import com.hivemq.client.mqtt.exceptions.ConnectionClosedException;
-import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5DisconnectException;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.handler.disconnect;
+
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.exceptions.MqttClientStateExceptions;
+import com.hivemq.client2.internal.mqtt.handler.MqttConnectionAwareHandler;
+import com.hivemq.client2.internal.mqtt.handler.MqttSession;
+import com.hivemq.client2.internal.mqtt.handler.connect.MqttConnAckSingle;
+import com.hivemq.client2.internal.mqtt.ioc.ConnectionScope;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectRestrictions;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.rx.CompletableFlow;
+import com.hivemq.client2.mqtt.MqttVersion;
+import com.hivemq.client2.mqtt.exceptions.ConnectionClosedException;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectSource;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5DisconnectException;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.EventLoop;
@@ -50,7 +51,7 @@
 import java.io.IOException;
 import java.util.concurrent.TimeUnit;
 
-import static com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil.fireDisconnectEvent;
+import static com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil.fireDisconnectEvent;
 
 /**
  * If the server initiated the closing of the channel (a Disconnect message is received or the channel is closed without
@@ -91,6 +92,7 @@ public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull
     }
 
     private void readDisconnect(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttDisconnect disconnect) {
+        LOGGER.debug("Read DISCONNECT {} from {}", disconnect, ctx.channel().remoteAddress());
         if (state == null) {
             state = STATE_CLOSED;
             fireDisconnectEvent(ctx.channel(), new Mqtt5DisconnectException(disconnect, "Server sent DISCONNECT."),
@@ -99,6 +101,7 @@ private void readDisconnect(final @NotNull ChannelHandlerContext ctx, final @Not
     }
 
     private void readConnAck(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttConnAck connAck) {
+        LOGGER.debug("Read CONNACK {} from {}", connAck, ctx.channel().remoteAddress());
         if (state == null) {
             state = STATE_CLOSED;
             MqttDisconnectUtil.disconnect(ctx.channel(), Mqtt5DisconnectReasonCode.PROTOCOL_ERROR,
@@ -127,13 +130,15 @@ public void channelInactive(final @NotNull ChannelHandlerContext ctx) {
     public void exceptionCaught(final @NotNull ChannelHandlerContext ctx, final @NotNull Throwable cause) {
         if (state == null) {
             state = STATE_CLOSED;
+            // will be logged in MqttDisconnectUtil
             fireDisconnectEvent(ctx.channel(), new ConnectionClosedException(cause), MqttDisconnectSource.CLIENT);
         } else if (!(cause instanceof IOException)) {
-            LOGGER.warn("Exception while disconnecting: {}", cause);
+            LOGGER.warn("Exception while disconnecting: {}, remote address: {}", cause, ctx.channel().remoteAddress());
         }
     }
 
     public void disconnect(final @NotNull MqttDisconnect disconnect, final @NotNull CompletableFlow flow) {
+        LOGGER.trace("disconnect: schedule DISCONNECT {}", disconnect);
         if (!clientConfig.executeInEventLoop(() -> writeDisconnect(disconnect, flow))) {
             flow.onError(MqttClientStateExceptions.notConnected());
         }
@@ -143,6 +148,7 @@ private void writeDisconnect(final @NotNull MqttDisconnect disconnect, final @No
         final ChannelHandlerContext ctx = this.ctx;
         if ((ctx != null) && (state == null)) {
             state = STATE_CLOSED;
+            LOGGER.trace("Fire DISCONNECT event {}", disconnect);
             fireDisconnectEvent(ctx.channel(), new MqttDisconnectEvent.ByUser(disconnect, flow));
         } else {
             flow.onError(MqttClientStateExceptions.notConnected());
@@ -158,10 +164,14 @@ protected void onDisconnectEvent(
         final Channel channel = ctx.channel();
 
         if (disconnectEvent.getSource() == MqttDisconnectSource.SERVER) {
+            LOGGER.debug("OnDisconnectedEvent: server closed connection: source: {}, cause: {}, remote address: {}",
+                    disconnectEvent.getSource(), disconnectEvent.getCause(), ctx.channel().remoteAddress());
             disconnected(channel, disconnectEvent);
             channel.close();
             return;
         }
+        LOGGER.debug("OnDisconnectedEvent: source: {}, cause: {}", disconnectEvent.getSource(),
+                disconnectEvent.getCause());
 
         MqttDisconnect disconnect = disconnectEvent.getDisconnect();
         if (disconnect != null) {
@@ -182,31 +192,44 @@ protected void onDisconnectEvent(
 
             if (disconnectEvent instanceof MqttDisconnectEvent.ByUser) {
                 final MqttDisconnectEvent.ByUser disconnectEventByUser = (MqttDisconnectEvent.ByUser) disconnectEvent;
+                LOGGER.debug("Write DISCONNECT (by user) {} to {}", disconnect, ctx.channel().remoteAddress());
                 ctx.writeAndFlush(disconnect).addListener(f -> {
                     if (f.isSuccess()) {
                         ((DuplexChannel) channel).shutdownOutput().addListener(cf -> {
                             if (cf.isSuccess()) {
+                                LOGGER.trace("DISCONNECT successful");
                                 state = new DisconnectingState(channel, disconnectEventByUser);
                             } else {
+                                LOGGER.debug("DISCONNECT failed: {}, remote address {}", cf.cause(), ctx.channel().remoteAddress());
                                 disconnected(channel, disconnectEvent);
                                 disconnectEventByUser.getFlow().onError(new ConnectionClosedException(cf.cause()));
                             }
                         });
                     } else {
+                        LOGGER.debug("DISCONNECT failed: {}, remote address {}", f.cause(), ctx.channel().remoteAddress());
                         disconnected(channel, disconnectEvent);
                         disconnectEventByUser.getFlow().onError(new ConnectionClosedException(f.cause()));
                     }
                 });
 
             } else if (clientConfig.getMqttVersion() == MqttVersion.MQTT_5_0) {
+                LOGGER.debug("Write DISCONNECT {} to {}", disconnect, ctx.channel().remoteAddress());
                 ctx.writeAndFlush(disconnect)
-                        .addListener(f -> channel.close().addListener(cf -> disconnected(channel, disconnectEvent)));
+                        .addListener(f -> channel.close().addListener(cf -> {
+                            LOGGER.trace("DISCONNECT done");
+                            disconnected(channel, disconnectEvent);}));
 
             } else {
-                channel.close().addListener(cf -> disconnected(channel, disconnectEvent));
+                LOGGER.debug("Close channel (DISCONNECT) {} to {}", disconnect, ctx.channel().remoteAddress());
+                channel.close().addListener(cf -> {
+                    LOGGER.trace("DISCONNECT done");
+                    disconnected(channel, disconnectEvent);});
             }
         } else {
-            channel.close().addListener(cf -> disconnected(channel, disconnectEvent));
+            LOGGER.debug("Close channel (DISCONNECT) to {}", ctx.channel().remoteAddress());
+            channel.close().addListener(cf -> {
+                LOGGER.trace("DISCONNECT done");
+                disconnected(channel, disconnectEvent);});
         }
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectUtil.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectUtil.java
similarity index 81%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectUtil.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectUtil.java
index ebacaab11..44d599911 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/disconnect/MqttDisconnectUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/disconnect/MqttDisconnectUtil.java
@@ -14,15 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.disconnect;
+package com.hivemq.client2.internal.mqtt.handler.disconnect;
 
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
-import com.hivemq.client.mqtt.exceptions.ConnectionClosedException;
-import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5DisconnectException;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
+import com.hivemq.client2.mqtt.exceptions.ConnectionClosedException;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectSource;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5DisconnectException;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.channel.Channel;
+
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -33,6 +36,7 @@
  */
 public final class MqttDisconnectUtil {
 
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttDisconnectUtil.class);
     /**
      * Closes the channel from the client side without sending a DISCONNECT message.
      *
@@ -98,7 +102,8 @@ public static void fireDisconnectEvent(
 
     static void fireDisconnectEvent(
             final @NotNull Channel channel, final @NotNull MqttDisconnectEvent disconnectEvent) {
-
+        LOGGER.trace("Fire DISCONNECT event: source: {}, cause: {}", disconnectEvent.getSource(),
+                disconnectEvent.getCause());
         channel.pipeline().fireUserEventTriggered(disconnectEvent);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/ping/MqttPingHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/ping/MqttPingHandler.java
similarity index 77%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/ping/MqttPingHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/ping/MqttPingHandler.java
index 3f11d6f72..fd979fa0f 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/ping/MqttPingHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/ping/MqttPingHandler.java
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.ping;
-
-import com.hivemq.client.internal.mqtt.handler.MqttConnectionAwareHandler;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.internal.mqtt.ioc.ConnectionScope;
-import com.hivemq.client.internal.mqtt.message.ping.MqttPingReq;
-import com.hivemq.client.internal.mqtt.message.ping.MqttPingResp;
-import com.hivemq.client.internal.netty.DefaultChannelOutboundHandler;
+package com.hivemq.client2.internal.mqtt.handler.ping;
+
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.handler.MqttConnectionAwareHandler;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.ioc.ConnectionScope;
+import com.hivemq.client2.internal.mqtt.message.ping.MqttPingReq;
+import com.hivemq.client2.internal.mqtt.message.ping.MqttPingResp;
+import com.hivemq.client2.internal.netty.DefaultChannelOutboundHandler;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
 import io.netty.channel.ChannelHandlerContext;
@@ -46,6 +48,7 @@ public class MqttPingHandler extends MqttConnectionAwareHandler
         implements DefaultChannelOutboundHandler, Runnable, ChannelFutureListener {
 
     public static final @NotNull String NAME = "ping";
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttPingHandler.class);
     private static final boolean PINGRESP_REQUIRED = false; // TODO configurable
 
     private final long keepAliveNanos;
@@ -78,6 +81,7 @@ public void flush(final @NotNull ChannelHandlerContext ctx) {
     public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull Object msg) {
         lastReadTimeNanos = System.nanoTime();
         if (msg instanceof MqttPingResp) {
+            LOGGER.debug("Read PINGRESP from {}", ctx.channel().remoteAddress());
             messageRead = true;
         } else {
             messageRead = !PINGRESP_REQUIRED;
@@ -100,10 +104,12 @@ public void run() {
         }
         if (pingReqWritten) {
             if (!pingReqFlushed) {
+                LOGGER.warn("Timeout while writing PINGREQ to {}", ctx.channel().remoteAddress());
                 MqttDisconnectUtil.close(ctx.channel(), "Timeout while writing PINGREQ");
                 return;
             }
             if (!messageRead) {
+                LOGGER.warn("Timeout while waiting for PINGRESP from {}", ctx.channel().remoteAddress());
                 MqttDisconnectUtil.close(ctx.channel(), "Timeout while waiting for PINGRESP");
                 return;
             }
@@ -116,6 +122,7 @@ public void run() {
             pingReqWritten = false;
             schedule(ctx, nextDelayNanos);
         } else {
+            LOGGER.debug("Write PINGREQ to {}", ctx.channel().remoteAddress());
             pingReqWritten = true;
             schedule(ctx, keepAliveNanos);
             lastFlushTimeNanos = timeNanos;
@@ -126,7 +133,10 @@ public void run() {
     @Override
     public void operationComplete(final @NotNull ChannelFuture future) {
         if (future.isSuccess()) {
+            LOGGER.trace("PINGREQ sent");
             pingReqFlushed = true;
+        } else {
+            LOGGER.debug("PINGREQ failed: cancelled: {}, cause: {}", future.isCancelled(), future.cause());
         }
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/proxy/MqttProxyAdapterHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/proxy/MqttProxyAdapterHandler.java
similarity index 97%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/proxy/MqttProxyAdapterHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/proxy/MqttProxyAdapterHandler.java
index b58b0ccd1..00163e4da 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/proxy/MqttProxyAdapterHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/proxy/MqttProxyAdapterHandler.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.proxy;
+package com.hivemq.client2.internal.mqtt.handler.proxy;
 
-import com.hivemq.client.internal.mqtt.MqttProxyConfigImpl;
+import com.hivemq.client2.internal.mqtt.MqttProxyConfigImpl;
 import io.netty.channel.*;
 import io.netty.handler.proxy.HttpProxyHandler;
 import io.netty.handler.proxy.ProxyHandler;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/proxy/MqttProxyInitializer.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/proxy/MqttProxyInitializer.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/proxy/MqttProxyInitializer.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/proxy/MqttProxyInitializer.java
index 83be60cfc..8f4866d79 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/proxy/MqttProxyInitializer.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/proxy/MqttProxyInitializer.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.proxy;
+package com.hivemq.client2.internal.mqtt.handler.proxy;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttProxyConfigImpl;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttProxyConfigImpl;
 import io.netty.channel.Channel;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlow.java
similarity index 85%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlow.java
index a534b615e..7b5d7ea6a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlow.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.util.collections.HandleList.Handle;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.util.collections.HandleList.Handle;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlowable.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlowable.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlowable.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlowable.java
index 05a71dc17..4164fcff8 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlowable.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttGlobalIncomingPublishFlowable.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
-
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.handler.subscribe.MqttSubscriptionHandler;
-import com.hivemq.client.internal.mqtt.ioc.ClientComponent;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import io.reactivex.Flowable;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
+
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.handler.subscribe.MqttSubscriptionHandler;
+import com.hivemq.client2.internal.mqtt.ioc.ClientComponent;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import io.reactivex.rxjava3.core.Flowable;
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Subscriber;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishConfirmable.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishConfirmable.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishConfirmable.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishConfirmable.java
index de5b296b1..b41d24146 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishConfirmable.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishConfirmable.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
 
-import com.hivemq.client.internal.checkpoint.Confirmable;
+import com.hivemq.client2.internal.checkpoint.Confirmable;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.concurrent.atomic.AtomicBoolean;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlow.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlow.java
index a1ed75d3a..58d923ebd 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlow.java
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
-
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.handler.util.FlowWithEventLoop;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import io.reactivex.Emitter;
-import io.reactivex.internal.util.BackpressureHelper;
-import io.reactivex.plugins.RxJavaPlugins;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
+
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.handler.util.FlowWithEventLoop;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import io.reactivex.rxjava3.core.Emitter;
+import io.reactivex.rxjava3.internal.util.BackpressureHelper;
+import io.reactivex.rxjava3.plugins.RxJavaPlugins;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
@@ -36,6 +38,7 @@
  */
 abstract class MqttIncomingPublishFlow extends FlowWithEventLoop
         implements Emitter<Mqtt5Publish>, Subscription, Runnable {
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttIncomingPublishFlow.class);
 
     private static final int STATE_NO_NEW_REQUESTS = 0;
     private static final int STATE_NEW_REQUESTS = 1;
@@ -72,6 +75,7 @@ abstract class MqttIncomingPublishFlow extends FlowWithEventLoop
     @CallByThread("Netty EventLoop")
     @Override
     public void onNext(final @NotNull Mqtt5Publish result) {
+        LOGGER.trace("onNext: {}, {}", result, subscriber);
         subscriber.onNext(result);
         if (requested != Long.MAX_VALUE) {
             requested--;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlows.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlows.java
similarity index 85%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlows.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlows.java
index 75465668f..749012830 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlows.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishFlows.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
-
-import com.hivemq.client.internal.annotations.NotThreadSafe;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.ioc.ClientScope;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.mqtt3.Mqtt3UnsubAckView;
-import com.hivemq.client.internal.util.collections.HandleList;
-import com.hivemq.client.internal.util.collections.HandleList.Handle;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAckReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
+
+import com.hivemq.client2.internal.annotations.NotThreadSafe;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.ioc.ClientScope;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubAckView;
+import com.hivemq.client2.internal.util.collections.HandleList;
+import com.hivemq.client2.internal.util.collections.HandleList.Handle;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAckReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAckReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishService.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishService.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishService.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishService.java
index 7dd36fca5..8df58ae00 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingPublishService.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingPublishService.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
-
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.checkpoint.Confirmable;
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.ioc.ClientScope;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.util.collections.ChunkedArrayQueue;
-import com.hivemq.client.internal.util.collections.HandleList.Handle;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
+
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.checkpoint.Confirmable;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.ioc.ClientScope;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.util.collections.ChunkedArrayQueue;
+import com.hivemq.client2.internal.util.collections.HandleList.Handle;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -109,6 +109,7 @@ private void onPublish(final @NotNull MqttStatefulPublishWithFlows publishWithFl
                 referencedFlowCount++;
             }
         }
+        LOGGER.trace("emit {}", publishWithFlows.publish);
         emit(publishWithFlows);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingQosHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingQosHandler.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingQosHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingQosHandler.java
index ad1e2f7d4..d21dc9530 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttIncomingQosHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttIncomingQosHandler.java
@@ -14,32 +14,25 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
-
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.advanced.interceptor.MqttClientInterceptors;
-import com.hivemq.client.internal.mqtt.handler.MqttSessionAwareHandler;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.internal.mqtt.ioc.ClientScope;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAckBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubCompBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRecBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.internal.util.collections.IntIndex;
-import com.hivemq.client.mqtt.MqttVersion;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5IncomingQos1Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5IncomingQos2Interceptor;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompReasonCode;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
+
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.advanced.interceptor.MqttClientInterceptors;
+import com.hivemq.client2.internal.mqtt.handler.MqttSessionAwareHandler;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.ioc.ClientScope;
+import com.hivemq.client2.internal.mqtt.message.publish.*;
+import com.hivemq.client2.internal.util.collections.IntIndex;
+import com.hivemq.client2.mqtt.MqttVersion;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5InboundQos1Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5InboundQos2Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompReasonCode;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.EventLoop;
 import org.jetbrains.annotations.NotNull;
@@ -104,6 +97,7 @@ public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull
     }
 
     private void readPublish(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttStatefulPublish publish) {
+        LOGGER.debug("Read PUBLISH {} from {}", publish, ctx.channel().remoteAddress());
         switch (publish.stateless().getQos()) {
             case AT_MOST_ONCE:
                 readPublishQos0(publish);
@@ -271,14 +265,17 @@ private boolean ack(
     }
 
     private void writePubAck(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttPubAck pubAck) {
+        LOGGER.debug("Write PUBACK {} to {}", pubAck, ctx.channel().remoteAddress());
         ctx.writeAndFlush(pubAck, ctx.voidPromise());
     }
 
     private void writePubRec(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttPubRec pubRec) {
+        LOGGER.debug("Write PUBREC {} to {}", pubRec, ctx.channel().remoteAddress());
         ctx.writeAndFlush(pubRec, ctx.voidPromise());
     }
 
     private void readPubRel(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttPubRel pubRel) {
+        LOGGER.debug("Read PUBREL {} from {}", pubRel, ctx.channel().remoteAddress());
         final Object prevMessage = messages.remove(pubRel.getPacketIdentifier());
         if (prevMessage instanceof MqttPubRec) { // normal case
             writePubComp(ctx, buildPubComp(new MqttPubCompBuilder(pubRel)));
@@ -305,6 +302,7 @@ ctx, buildPubComp(new MqttPubCompBuilder(pubRel).reasonCode(
     }
 
     private void writePubComp(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttPubComp pubComp) {
+        LOGGER.debug("Write PUBCOMP {} to {}", pubComp, ctx.channel().remoteAddress());
         ctx.writeAndFlush(pubComp, ctx.voidPromise());
     }
 
@@ -317,7 +315,7 @@ public void onSessionEnd(final @NotNull Throwable cause) {
     private @NotNull MqttPubAck buildPubAck(final @NotNull MqttPubAckBuilder pubAckBuilder) {
         final MqttClientInterceptors interceptors = clientConfig.getAdvancedConfig().getInterceptors();
         if (interceptors != null) {
-            final Mqtt5IncomingQos1Interceptor interceptor = interceptors.getIncomingQos1Interceptor();
+            final Mqtt5InboundQos1Interceptor interceptor = interceptors.getInboundQos1Interceptor();
             if (interceptor != null) {
                 interceptor.onPublish(clientConfig, pubAckBuilder.getPublish().stateless(), pubAckBuilder);
             }
@@ -328,7 +326,7 @@ public void onSessionEnd(final @NotNull Throwable cause) {
     private @NotNull MqttPubRec buildPubRec(final @NotNull MqttPubRecBuilder pubRecBuilder) {
         final MqttClientInterceptors interceptors = clientConfig.getAdvancedConfig().getInterceptors();
         if (interceptors != null) {
-            final Mqtt5IncomingQos2Interceptor interceptor = interceptors.getIncomingQos2Interceptor();
+            final Mqtt5InboundQos2Interceptor interceptor = interceptors.getInboundQos2Interceptor();
             if (interceptor != null) {
                 interceptor.onPublish(clientConfig, pubRecBuilder.getPublish().stateless(), pubRecBuilder);
             }
@@ -339,7 +337,7 @@ public void onSessionEnd(final @NotNull Throwable cause) {
     private @NotNull MqttPubComp buildPubComp(final @NotNull MqttPubCompBuilder pubCompBuilder) {
         final MqttClientInterceptors interceptors = clientConfig.getAdvancedConfig().getInterceptors();
         if (interceptors != null) {
-            final Mqtt5IncomingQos2Interceptor interceptor = interceptors.getIncomingQos2Interceptor();
+            final Mqtt5InboundQos2Interceptor interceptor = interceptors.getInboundQos2Interceptor();
             if (interceptor != null) {
                 interceptor.onPubRel(clientConfig, pubCompBuilder.getPubRel(), pubCompBuilder);
             }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttStatefulPublishWithFlows.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttStatefulPublishWithFlows.java
similarity index 83%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttStatefulPublishWithFlows.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttStatefulPublishWithFlows.java
index ec8e4c216..3a39a9570 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttStatefulPublishWithFlows.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttStatefulPublishWithFlows.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
 
-import com.hivemq.client.internal.annotations.NotThreadSafe;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.util.collections.HandleList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.internal.annotations.NotThreadSafe;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish;
+import com.hivemq.client2.internal.util.collections.HandleList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlow.java
similarity index 75%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlow.java
index 6559528ac..33b8c453d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlow.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.handler.subscribe.MqttSubscriptionFlow;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAck;
-import com.hivemq.client.internal.util.collections.HandleList;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.rx.FlowableWithSingleSubscriber;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.handler.subscribe.MqttSubscriptionFlow;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAck;
+import com.hivemq.client2.internal.util.collections.HandleList;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.rx.FlowableWithSingleSubscriber;
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Subscriber;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTree.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTree.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTree.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTree.java
index 8309955da..724760aee 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTree.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTree.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
-
-import com.hivemq.client.internal.annotations.NotThreadSafe;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicIterator;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicLevel;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicLevels;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.util.collections.HandleList.Handle;
-import com.hivemq.client.internal.util.collections.Index;
-import com.hivemq.client.internal.util.collections.NodeList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
+
+import com.hivemq.client2.internal.annotations.NotThreadSafe;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicIterator;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicLevel;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicLevels;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.util.collections.HandleList.Handle;
+import com.hivemq.client2.internal.util.collections.Index;
+import com.hivemq.client2.internal.util.collections.NodeList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -569,8 +569,8 @@ private static void getSubscriptions(
                     final MqttTopicFilterImpl topicFilter =
                             MqttTopicLevel.toFilter(entry.topicFilterPrefix, topicLevels, multiLevelWildcard);
                     assert topicFilter != null : "reconstructed topic filter must be valid";
-                    final MqttQos qos = MqttSubscription.decodeQos(entry.subscriptionOptions);
-                    assert qos != null : "reconstructed qos must be valid";
+                    final MqttQos maxQos = MqttSubscription.decodeMaxQos(entry.subscriptionOptions);
+                    assert maxQos != null : "reconstructed maxQos must be valid";
                     final boolean noLocal = MqttSubscription.decodeNoLocal(entry.subscriptionOptions);
                     final Mqtt5RetainHandling retainHandling =
                             MqttSubscription.decodeRetainHandling(entry.subscriptionOptions);
@@ -578,7 +578,7 @@ private static void getSubscriptions(
                     final boolean retainAsPublished =
                             MqttSubscription.decodeRetainAsPublished(entry.subscriptionOptions);
                     final MqttSubscription subscription =
-                            new MqttSubscription(topicFilter, qos, noLocal, retainHandling, retainAsPublished);
+                            new MqttSubscription(topicFilter, maxQos, noLocal, retainHandling, retainAsPublished);
                     map.computeIfAbsent(entry.subscriptionIdentifier, k -> new LinkedList<>()).add(subscription);
                 }
             }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowable.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowable.java
similarity index 78%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowable.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowable.java
index 8cc939d9e..f430a99e7 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowable.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowable.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.handler.subscribe.MqttSubscriptionHandler;
-import com.hivemq.client.internal.mqtt.ioc.ClientComponent;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.rx.FlowableWithSingle;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.handler.subscribe.MqttSubscriptionHandler;
+import com.hivemq.client2.internal.mqtt.ioc.ClientComponent;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.rx.FlowableWithSingle;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Subscriber;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlows.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlows.java
similarity index 84%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlows.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlows.java
index d4f3ad00f..d286c5659 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlows.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlows.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
 
-import com.hivemq.client.internal.annotations.NotThreadSafe;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.annotations.NotThreadSafe;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckFlow.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckFlow.java
index 85b875bed..5ac0c538e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckFlow.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
 
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.handler.util.FlowWithEventLoop;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishResult;
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.handler.util.FlowWithEventLoop;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishResult;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckFlowable.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckFlowable.java
similarity index 79%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckFlowable.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckFlowable.java
index 6c0f4a274..cfa6890f4 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckFlowable.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckFlowable.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
-
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.exceptions.MqttClientStateExceptions;
-import com.hivemq.client.internal.mqtt.ioc.ClientComponent;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import io.reactivex.Flowable;
-import io.reactivex.internal.subscriptions.EmptySubscription;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
+
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.exceptions.MqttClientStateExceptions;
+import com.hivemq.client2.internal.mqtt.ioc.ClientComponent;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.internal.subscriptions.EmptySubscription;
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Subscriber;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckFlowableFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckFlowableFlow.java
similarity index 92%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckFlowableFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckFlowableFlow.java
index 44d3ef4fe..8d34192d7 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckFlowableFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckFlowableFlow.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
-
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttPublishFlowableAckLink.LinkedFlow;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishResult;
-import com.hivemq.client.internal.util.collections.ChunkedArrayQueue;
-import io.reactivex.internal.util.BackpressureHelper;
-import io.reactivex.plugins.RxJavaPlugins;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
+
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttPublishFlowableAckLink.LinkedFlow;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishResult;
+import com.hivemq.client2.internal.util.collections.ChunkedArrayQueue;
+import io.reactivex.rxjava3.internal.util.BackpressureHelper;
+import io.reactivex.rxjava3.plugins.RxJavaPlugins;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckSingle.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckSingle.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckSingle.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckSingle.java
index 160d34afa..a80cf6854 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckSingle.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckSingle.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
 
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.exceptions.MqttClientStateExceptions;
-import com.hivemq.client.internal.mqtt.ioc.ClientComponent;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import io.reactivex.Flowable;
-import io.reactivex.Single;
-import io.reactivex.SingleObserver;
-import io.reactivex.disposables.Disposable;
-import io.reactivex.internal.disposables.EmptyDisposable;
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.exceptions.MqttClientStateExceptions;
+import com.hivemq.client2.internal.mqtt.ioc.ClientComponent;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.Single;
+import io.reactivex.rxjava3.core.SingleObserver;
+import io.reactivex.rxjava3.disposables.Disposable;
+import io.reactivex.rxjava3.internal.disposables.EmptyDisposable;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckSingleFlowable.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckSingleFlowable.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckSingleFlowable.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckSingleFlowable.java
index 0592e148e..00bcec441 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttAckSingleFlowable.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttAckSingleFlowable.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
-
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.exceptions.MqttClientStateExceptions;
-import com.hivemq.client.internal.mqtt.ioc.ClientComponent;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import io.reactivex.Flowable;
-import io.reactivex.internal.subscriptions.EmptySubscription;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
+
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.exceptions.MqttClientStateExceptions;
+import com.hivemq.client2.internal.mqtt.ioc.ClientComponent;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.internal.subscriptions.EmptySubscription;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttOutgoingQosHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttOutgoingQosHandler.java
similarity index 83%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttOutgoingQosHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttOutgoingQosHandler.java
index 7eb3e534e..d19bab965 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttOutgoingQosHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttOutgoingQosHandler.java
@@ -14,52 +14,45 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
-
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.advanced.interceptor.MqttClientInterceptors;
-import com.hivemq.client.internal.mqtt.exceptions.MqttClientStateExceptions;
-import com.hivemq.client.internal.mqtt.handler.MqttSessionAwareHandler;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttPubRelWithFlow.MqttQos2CompleteWithFlow;
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttPubRelWithFlow.MqttQos2IntermediateWithFlow;
-import com.hivemq.client.internal.mqtt.handler.subscribe.MqttSubscriptionHandler;
-import com.hivemq.client.internal.mqtt.ioc.ClientScope;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishResult;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishResult.MqttQos1Result;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishResult.MqttQos2CompleteResult;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishResult.MqttQos2IntermediateResult;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishResult.MqttQos2Result;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRelBuilder;
-import com.hivemq.client.internal.netty.ContextFuture;
-import com.hivemq.client.internal.netty.DefaultContextPromise;
-import com.hivemq.client.internal.util.Ranges;
-import com.hivemq.client.internal.util.UnsignedDataTypes;
-import com.hivemq.client.internal.util.collections.IntIndex;
-import com.hivemq.client.internal.util.collections.NodeList;
-import com.hivemq.client.mqtt.MqttClientState;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.exceptions.ConnectionClosedException;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5OutgoingQos1Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5OutgoingQos2Interceptor;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5PubAckException;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5PubRecException;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
+
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.advanced.interceptor.MqttClientInterceptors;
+import com.hivemq.client2.internal.mqtt.exceptions.MqttClientStateExceptions;
+import com.hivemq.client2.internal.mqtt.handler.MqttSessionAwareHandler;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttPubRelWithFlow.MqttQos2CompleteWithFlow;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttPubRelWithFlow.MqttQos2IntermediateWithFlow;
+import com.hivemq.client2.internal.mqtt.handler.subscribe.MqttSubscriptionHandler;
+import com.hivemq.client2.internal.mqtt.ioc.ClientScope;
+import com.hivemq.client2.internal.mqtt.message.publish.*;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishResult.MqttQos1Result;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishResult.MqttQos2CompleteResult;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishResult.MqttQos2IntermediateResult;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishResult.MqttQos2Result;
+import com.hivemq.client2.internal.netty.ContextFuture;
+import com.hivemq.client2.internal.netty.DefaultContextPromise;
+import com.hivemq.client2.internal.util.Ranges;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.internal.util.collections.IntIndex;
+import com.hivemq.client2.internal.util.collections.NodeList;
+import com.hivemq.client2.mqtt.MqttClientState;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.exceptions.ConnectionClosedException;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5OutboundQos1Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5OutboundQos2Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5PubAckException;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5PubRecException;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.EventLoop;
-import io.reactivex.Flowable;
-import io.reactivex.FlowableSubscriber;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.FlowableSubscriber;
 import org.jctools.queues.SpscUnboundedArrayQueue;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -69,7 +62,7 @@
 import java.io.IOException;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import static com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish.NO_PACKET_IDENTIFIER_QOS_0;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish.NO_PACKET_IDENTIFIER_QOS_0;
 
 /**
  * @author Silvio Giebl
@@ -153,8 +146,11 @@ public void onSubscribe(final @NotNull Subscription subscription) {
 
     @Override
     public void onNext(final @NotNull MqttPublishWithFlow publishWithFlow) {
+        LOGGER.trace("onNext: queuing/scheduling outgoing {}", publishWithFlow.getPublish());
+
         queue.offer(publishWithFlow);
         if (queuedCounter.getAndIncrement() == 0) {
+            LOGGER.trace("Trigger actual publish (runnable)");
             publishWithFlow.getAckFlow().getEventLoop().execute(this);
         }
     }
@@ -187,14 +183,17 @@ void request(final long n) {
     @CallByThread("Netty EventLoop")
     @Override
     public void run() {
+        LOGGER.trace("run BEGIN");
         if (!hasSession) {
             if (!isRepublishIfSessionExpired()) {
                 clearQueued(MqttClientStateExceptions.notConnected());
             }
+            LOGGER.trace("run: !hasSession");
             return;
         }
         final ChannelHandlerContext ctx = this.ctx;
         if (ctx == null) {
+            LOGGER.trace("run: ctx == null");
             return;
         }
         final Channel channel = ctx.channel();
@@ -220,9 +219,11 @@ public void run() {
             final boolean wasWritable = channel.isWritable();
             ctx.flush();
             if ((dequeued > 0) && (queuedCounter.addAndGet(-dequeued) > 0) && wasWritable) {
+                LOGGER.trace("Retrigger actual publish (runnable)");
                 channel.eventLoop().execute(this);
             }
         }
+        LOGGER.trace("run END");
     }
 
     @Override
@@ -261,7 +262,7 @@ private void writePublish(
 
     private void writeQos0Publish(
             final @NotNull ChannelHandlerContext ctx, final @NotNull MqttPublishWithFlow publishWithFlow) {
-
+        LOGGER.debug("Write PUBLISH {} to {}", publishWithFlow.getPublish(), ctx.channel().remoteAddress());
         ctx.write(publishWithFlow.getPublish().createStateful(NO_PACKET_IDENTIFIER_QOS_0, false, topicAliasMapping),
                 new DefaultContextPromise<>(ctx.channel(), publishWithFlow)).addListener(this);
     }
@@ -301,7 +302,7 @@ private void writeQos1Or2Publish(
             final @NotNull ChannelHandlerContext ctx,
             final @NotNull MqttStatefulPublish publish,
             final @NotNull MqttPublishWithFlow publishWithFlow) {
-
+        LOGGER.debug("Write PUBLISH {} to {}", publish, ctx.channel().remoteAddress());
         currentPending = publishWithFlow;
         ctx.write(publish, ctx.voidPromise());
         currentPending = null;
@@ -321,6 +322,7 @@ public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull
     }
 
     private void readPubAck(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttPubAck pubAck) {
+        LOGGER.debug("Read PUBACK {} from {}", pubAck, ctx.channel().remoteAddress());
         final int packetIdentifier = pubAck.getPacketIdentifier();
         final MqttPubOrRelWithFlow removed = pendingIndex.remove(packetIdentifier);
 
@@ -351,6 +353,7 @@ private void readPubAck(final @NotNull ChannelHandlerContext ctx, final @NotNull
     }
 
     private void readPubRec(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttPubRec pubRec) {
+        LOGGER.debug("Read PUBREC {} from {}", pubRec, ctx.channel().remoteAddress());
         final int packetIdentifier = pubRec.getPacketIdentifier();
         final MqttPubOrRelWithFlow got = pendingIndex.get(packetIdentifier);
 
@@ -397,6 +400,7 @@ private void readPubRec(final @NotNull ChannelHandlerContext ctx, final @NotNull
     }
 
     private void writePubRel(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttPubRel pubRel) {
+        LOGGER.debug("Write PUBREL {} to {}", pubRel, ctx.channel().remoteAddress());
         ctx.write(pubRel, ctx.voidPromise());
     }
 
@@ -409,6 +413,7 @@ private void replacePending(
     }
 
     private void readPubComp(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttPubComp pubComp) {
+        LOGGER.debug("Read PUBCOMP {} from {}", pubComp, ctx.channel().remoteAddress());
         final int packetIdentifier = pubComp.getPacketIdentifier();
         final MqttPubOrRelWithFlow removed = pendingIndex.remove(packetIdentifier);
 
@@ -464,6 +469,7 @@ private void completePending(
     @Override
     public void exceptionCaught(final @NotNull ChannelHandlerContext ctx, final @NotNull Throwable cause) {
         if (!(cause instanceof IOException) && (currentPending != null)) {
+            LOGGER.debug("Exception caught: {}, remote address: {}", cause, ctx.channel().remoteAddress());
             pendingIndex.remove(currentPending.packetIdentifier);
             currentPending.getAckFlow().onNext(new MqttPublishResult(currentPending.getPublish(), cause));
             completePending(ctx, currentPending);
@@ -509,6 +515,7 @@ private boolean isRepublishIfSessionExpired() {
     }
 
     private void clearQueued(final @NotNull Throwable cause) {
+        LOGGER.trace("clear queued, cause: {}", cause);
         int polled = 0;
         while (true) {
             final MqttPublishWithFlow publishWithFlow = queue.poll();
@@ -532,7 +539,7 @@ private static void error(final @NotNull ChannelHandlerContext ctx, final @NotNu
     private void onPubAck(final @NotNull MqttPublish publish, final @NotNull MqttPubAck pubAck) {
         final MqttClientInterceptors interceptors = clientConfig.getAdvancedConfig().getInterceptors();
         if (interceptors != null) {
-            final Mqtt5OutgoingQos1Interceptor interceptor = interceptors.getOutgoingQos1Interceptor();
+            final Mqtt5OutboundQos1Interceptor interceptor = interceptors.getOutboundQos1Interceptor();
             if (interceptor != null) {
                 interceptor.onPubAck(clientConfig, publish, pubAck);
             }
@@ -542,7 +549,7 @@ private void onPubAck(final @NotNull MqttPublish publish, final @NotNull MqttPub
     private void onPubRecError(final @NotNull MqttPublish publish, final @NotNull MqttPubRec pubRec) {
         final MqttClientInterceptors interceptors = clientConfig.getAdvancedConfig().getInterceptors();
         if (interceptors != null) {
-            final Mqtt5OutgoingQos2Interceptor interceptor = interceptors.getOutgoingQos2Interceptor();
+            final Mqtt5OutboundQos2Interceptor interceptor = interceptors.getOutboundQos2Interceptor();
             if (interceptor != null) {
                 interceptor.onPubRecError(clientConfig, publish, pubRec);
             }
@@ -553,7 +560,7 @@ private void onPubRecError(final @NotNull MqttPublish publish, final @NotNull Mq
         final MqttPubRelBuilder pubRelBuilder = new MqttPubRelBuilder(pubRec);
         final MqttClientInterceptors interceptors = clientConfig.getAdvancedConfig().getInterceptors();
         if (interceptors != null) {
-            final Mqtt5OutgoingQos2Interceptor interceptor = interceptors.getOutgoingQos2Interceptor();
+            final Mqtt5OutboundQos2Interceptor interceptor = interceptors.getOutboundQos2Interceptor();
             if (interceptor != null) {
                 interceptor.onPubRec(clientConfig, publish, pubRec, pubRelBuilder);
             }
@@ -564,7 +571,7 @@ private void onPubRecError(final @NotNull MqttPublish publish, final @NotNull Mq
     private void onPubComp(final @NotNull MqttPubRel pubRel, final @NotNull MqttPubComp pubComp) {
         final MqttClientInterceptors interceptors = clientConfig.getAdvancedConfig().getInterceptors();
         if (interceptors != null) {
-            final Mqtt5OutgoingQos2Interceptor interceptor = interceptors.getOutgoingQos2Interceptor();
+            final Mqtt5OutboundQos2Interceptor interceptor = interceptors.getOutboundQos2Interceptor();
             if (interceptor != null) {
                 interceptor.onPubComp(clientConfig, pubRel, pubComp);
             }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPubOrRelWithFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPubOrRelWithFlow.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPubOrRelWithFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPubOrRelWithFlow.java
index edff5b74a..f43c1638a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPubOrRelWithFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPubOrRelWithFlow.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
 
-import com.hivemq.client.internal.util.collections.NodeList;
+import com.hivemq.client2.internal.util.collections.NodeList;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPubRelWithFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPubRelWithFlow.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPubRelWithFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPubRelWithFlow.java
index b3c8c6504..c7465139a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPubRelWithFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPubRelWithFlow.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
 
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.function.BooleanSupplier;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPublishFlowableAckLink.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPublishFlowableAckLink.java
similarity index 92%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPublishFlowableAckLink.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPublishFlowableAckLink.java
index b72298d2c..ce3e5dd69 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPublishFlowableAckLink.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPublishFlowableAckLink.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
-
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import io.reactivex.Flowable;
-import io.reactivex.FlowableSubscriber;
-import io.reactivex.plugins.RxJavaPlugins;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
+
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.FlowableSubscriber;
+import io.reactivex.rxjava3.plugins.RxJavaPlugins;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPublishFlowables.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPublishFlowables.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPublishFlowables.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPublishFlowables.java
index f7586fdc3..4de60e075 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPublishFlowables.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPublishFlowables.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
 
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.ioc.ClientScope;
-import io.reactivex.Flowable;
-import io.reactivex.internal.util.BackpressureHelper;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.ioc.ClientScope;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.internal.util.BackpressureHelper;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
@@ -50,7 +50,9 @@ public void add(final @NotNull Flowable<MqttPublishWithFlow> publishFlowable) {
         synchronized (this) {
             while (requested == 0) {
                 try {
+                    LOGGER.debug("Publish blocked (requested == 0)");
                     this.wait();
+                    LOGGER.debug("Publish unblocked");
                 } catch (final InterruptedException e) {
                     LOGGER.error("thread interrupted while waiting to publish.", e);
                     return;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPublishWithFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPublishWithFlow.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPublishWithFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPublishWithFlow.java
index d5f573327..ad361d3a2 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttPublishWithFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttPublishWithFlow.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
 
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttTopicAliasAutoMapping.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttTopicAliasAutoMapping.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttTopicAliasAutoMapping.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttTopicAliasAutoMapping.java
index e3f22c4d3..c080f5653 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttTopicAliasAutoMapping.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttTopicAliasAutoMapping.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImpl;
-import com.hivemq.client.internal.util.collections.Index;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImpl;
+import com.hivemq.client2.internal.util.collections.Index;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import static com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish.*;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish.*;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttTopicAliasMapping.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttTopicAliasMapping.java
similarity index 86%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttTopicAliasMapping.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttTopicAliasMapping.java
index 75b42e79f..8a4e57151 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/publish/outgoing/MqttTopicAliasMapping.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/publish/outgoing/MqttTopicAliasMapping.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.outgoing;
+package com.hivemq.client2.internal.mqtt.handler.publish.outgoing;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImpl;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubAckSingle.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubAckSingle.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubAckSingle.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubAckSingle.java
index ab914a897..fc4dda01b 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubAckSingle.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubAckSingle.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.subscribe;
+package com.hivemq.client2.internal.mqtt.handler.subscribe;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.ioc.ClientComponent;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAck;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import io.reactivex.Single;
-import io.reactivex.SingleObserver;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.ioc.ClientComponent;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAck;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import io.reactivex.rxjava3.core.Single;
+import io.reactivex.rxjava3.core.SingleObserver;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubOrUnsubAckFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubOrUnsubAckFlow.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubOrUnsubAckFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubOrUnsubAckFlow.java
index 0dad079a3..a4e95c693 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubOrUnsubAckFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubOrUnsubAckFlow.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.subscribe;
+package com.hivemq.client2.internal.mqtt.handler.subscribe;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.handler.util.FlowWithEventLoop;
-import io.reactivex.SingleObserver;
-import io.reactivex.disposables.Disposable;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.handler.util.FlowWithEventLoop;
+import io.reactivex.rxjava3.core.SingleObserver;
+import io.reactivex.rxjava3.disposables.Disposable;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubOrUnsubWithFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubOrUnsubWithFlow.java
similarity index 87%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubOrUnsubWithFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubOrUnsubWithFlow.java
index a8ae37a8e..1be0be063 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubOrUnsubWithFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubOrUnsubWithFlow.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.subscribe;
+package com.hivemq.client2.internal.mqtt.handler.subscribe;
 
-import com.hivemq.client.internal.util.collections.NodeList;
+import com.hivemq.client2.internal.util.collections.NodeList;
 import org.jetbrains.annotations.Nullable;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubscribeWithFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubscribeWithFlow.java
similarity index 86%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubscribeWithFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubscribeWithFlow.java
index a2f388682..524a32dbd 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubscribeWithFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubscribeWithFlow.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.subscribe;
+package com.hivemq.client2.internal.mqtt.handler.subscribe;
 
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAck;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAck;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubscriptionFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubscriptionFlow.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubscriptionFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubscriptionFlow.java
index 0b1be90dd..62e4b5f5e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubscriptionFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubscriptionFlow.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.subscribe;
+package com.hivemq.client2.internal.mqtt.handler.subscribe;
 
 import io.netty.channel.EventLoop;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubscriptionHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubscriptionHandler.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubscriptionHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubscriptionHandler.java
index 3e2ca8cad..067edd62f 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttSubscriptionHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttSubscriptionHandler.java
@@ -14,39 +14,39 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.subscribe;
-
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.handler.MqttSessionAwareHandler;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.internal.mqtt.handler.publish.incoming.MqttGlobalIncomingPublishFlow;
-import com.hivemq.client.internal.mqtt.handler.publish.incoming.MqttIncomingPublishFlows;
-import com.hivemq.client.internal.mqtt.handler.publish.incoming.MqttSubscribedPublishFlow;
-import com.hivemq.client.internal.mqtt.ioc.ClientScope;
-import com.hivemq.client.internal.mqtt.message.MqttCommonReasonCode;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttStatefulSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAck;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttStatefulUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.MqttUnsubAck;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.mqtt3.Mqtt3UnsubAckView;
-import com.hivemq.client.internal.util.Ranges;
-import com.hivemq.client.internal.util.UnsignedDataTypes;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.internal.util.collections.IntIndex;
-import com.hivemq.client.internal.util.collections.NodeList;
-import com.hivemq.client.mqtt.MqttClientState;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAckReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.handler.subscribe;
+
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.handler.MqttSessionAwareHandler;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.handler.publish.incoming.MqttGlobalIncomingPublishFlow;
+import com.hivemq.client2.internal.mqtt.handler.publish.incoming.MqttIncomingPublishFlows;
+import com.hivemq.client2.internal.mqtt.handler.publish.incoming.MqttSubscribedPublishFlow;
+import com.hivemq.client2.internal.mqtt.ioc.ClientScope;
+import com.hivemq.client2.internal.mqtt.message.MqttReasonCodes;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttStatefulSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAck;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttStatefulUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubAck;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubAckView;
+import com.hivemq.client2.internal.util.Ranges;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.util.collections.IntIndex;
+import com.hivemq.client2.internal.util.collections.NodeList;
+import com.hivemq.client2.mqtt.MqttClientState;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5SubAckException;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAckReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAckReasonCode;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.EventLoop;
 import org.jetbrains.annotations.NotNull;
@@ -119,6 +119,7 @@ public void onSessionStartOrResume(
 
     public void subscribe(
             final @NotNull MqttSubscribe subscribe, final @NotNull MqttSubscriptionFlow<MqttSubAck> flow) {
+        LOGGER.trace("subscribe: schedule SUBSCRIBE {}", subscribe);
 
         flow.getEventLoop().execute(() -> {
             if (flow.init()) {
@@ -132,6 +133,7 @@ public void subscribe(
 
     public void unsubscribe(
             final @NotNull MqttUnsubscribe unsubscribe, final @NotNull MqttSubOrUnsubAckFlow<MqttUnsubAck> flow) {
+        LOGGER.trace("unsubscribe: schedule UNSUBSCRIBE {}", unsubscribe);
 
         flow.getEventLoop().execute(() -> {
             if (flow.init()) {
@@ -199,6 +201,7 @@ private void writeSubscribe(
                 subscribeWithFlow.subscribe.createStateful(subscribeWithFlow.packetIdentifier, subscriptionIdentifier);
 
         currentPending = subscribeWithFlow;
+        LOGGER.debug("Write SUBSCRIBE {} to {}", statefulSubscribe, ctx.channel().remoteAddress());
         ctx.write(statefulSubscribe, ctx.voidPromise());
         currentPending = null;
     }
@@ -210,6 +213,7 @@ private void writeUnsubscribe(
                 unsubscribeWithFlow.unsubscribe.createStateful(unsubscribeWithFlow.packetIdentifier);
 
         currentPending = unsubscribeWithFlow;
+        LOGGER.debug("Write UNSUBSCRIBE {} to {}", statefulUnsubscribe, ctx.channel().remoteAddress());
         ctx.write(statefulUnsubscribe, ctx.voidPromise());
         currentPending = null;
     }
@@ -226,6 +230,7 @@ public void channelRead(final @NotNull ChannelHandlerContext ctx, final @NotNull
     }
 
     private void readSubAck(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttSubAck subAck) {
+        LOGGER.debug("Read SUBACK {} from {}", subAck, ctx.channel().remoteAddress());
         final MqttSubOrUnsubWithFlow subOrUnsubWithFlow = pendingIndex.remove(subAck.getPacketIdentifier());
 
         if (subOrUnsubWithFlow == null) {
@@ -243,7 +248,7 @@ private void readSubAck(final @NotNull ChannelHandlerContext ctx, final @NotNull
 
         final ImmutableList<Mqtt5SubAckReasonCode> reasonCodes = subAck.getReasonCodes();
         final boolean countNotMatching = subscribeWithFlow.subscribe.getSubscriptions().size() != reasonCodes.size();
-        final boolean allErrors = MqttCommonReasonCode.allErrors(subAck.getReasonCodes());
+        final boolean allErrors = MqttReasonCodes.allErrors(subAck.getReasonCodes());
 
         incomingPublishFlows.subAck(subscribeWithFlow.subscribe, subscribeWithFlow.subscriptionIdentifier, reasonCodes);
 
@@ -273,6 +278,7 @@ private void readSubAck(final @NotNull ChannelHandlerContext ctx, final @NotNull
     }
 
     private void readUnsubAck(final @NotNull ChannelHandlerContext ctx, final @NotNull MqttUnsubAck unsubAck) {
+        LOGGER.debug("Read UNSUBACK {} from {}", unsubAck, ctx.channel().remoteAddress());
         final MqttSubOrUnsubWithFlow subOrUnsubWithFlow = pendingIndex.remove(unsubAck.getPacketIdentifier());
 
         if (subOrUnsubWithFlow == null) {
@@ -290,7 +296,7 @@ private void readUnsubAck(final @NotNull ChannelHandlerContext ctx, final @NotNu
 
         final ImmutableList<Mqtt5UnsubAckReasonCode> reasonCodes = unsubAck.getReasonCodes();
         final boolean countNotMatching = unsubscribeWithFlow.unsubscribe.getTopicFilters().size() != reasonCodes.size();
-        final boolean allErrors = MqttCommonReasonCode.allErrors(unsubAck.getReasonCodes());
+        final boolean allErrors = MqttReasonCodes.allErrors(unsubAck.getReasonCodes());
 
         if ((reasonCodes == Mqtt3UnsubAckView.REASON_CODES_ALL_SUCCESS) || !(countNotMatching || allErrors)) {
 
@@ -326,6 +332,7 @@ private void completePending(final @NotNull MqttSubOrUnsubWithFlow oldPending) {
 
     @Override
     public void exceptionCaught(final @NotNull ChannelHandlerContext ctx, final @NotNull Throwable cause) {
+        LOGGER.debug("Exception caught: {}, remote address: {}", cause, ctx.channel().remoteAddress());
         if (!(cause instanceof IOException) && (currentPending != null)) {
             pending.remove(currentPending);
             packetIdentifiers.returnId(currentPending.packetIdentifier);
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttUnsubAckSingle.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttUnsubAckSingle.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttUnsubAckSingle.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttUnsubAckSingle.java
index 197a87716..06004222c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttUnsubAckSingle.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttUnsubAckSingle.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.subscribe;
-
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.ioc.ClientComponent;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.MqttUnsubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
-import io.reactivex.Single;
-import io.reactivex.SingleObserver;
+package com.hivemq.client2.internal.mqtt.handler.subscribe;
+
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.ioc.ClientComponent;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubAck;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import io.reactivex.rxjava3.core.Single;
+import io.reactivex.rxjava3.core.SingleObserver;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttUnsubscribeWithFlow.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttUnsubscribeWithFlow.java
similarity index 85%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttUnsubscribeWithFlow.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttUnsubscribeWithFlow.java
index e0f9a180c..dedf217da 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/subscribe/MqttUnsubscribeWithFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/subscribe/MqttUnsubscribeWithFlow.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.subscribe;
+package com.hivemq.client2.internal.mqtt.handler.subscribe;
 
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.MqttUnsubAck;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubAck;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/ssl/MqttSslAdapterHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/tls/MqttTlsAdapterHandler.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/ssl/MqttSslAdapterHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/tls/MqttTlsAdapterHandler.java
index 143e8b95f..05efe4e2a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/ssl/MqttSslAdapterHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/tls/MqttTlsAdapterHandler.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.ssl;
+package com.hivemq.client2.internal.mqtt.handler.tls;
 
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandlerContext;
@@ -32,7 +32,7 @@
 /**
  * @author Silvio Giebl
  */
-class MqttSslAdapterHandler extends ChannelInboundHandlerAdapter {
+class MqttTlsAdapterHandler extends ChannelInboundHandlerAdapter {
 
     public static final @NotNull String NAME = "ssl.adapter";
 
@@ -43,7 +43,7 @@ class MqttSslAdapterHandler extends ChannelInboundHandlerAdapter {
     private final @NotNull BiConsumer<Channel, Throwable> onError;
     private boolean handshakeDone = false;
 
-    public MqttSslAdapterHandler(
+    public MqttTlsAdapterHandler(
             final @NotNull SslHandler sslHandler,
             final @NotNull String host,
             final @Nullable HostnameVerifier hostnameVerifier,
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/ssl/MqttSslInitializer.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/tls/MqttTlsInitializer.java
similarity index 71%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/ssl/MqttSslInitializer.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/tls/MqttTlsInitializer.java
index dfdd808b6..61590bc21 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/ssl/MqttSslInitializer.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/tls/MqttTlsInitializer.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.ssl;
+package com.hivemq.client2.internal.mqtt.handler.tls;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientSslConfigImpl;
-import com.hivemq.client.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttTlsConfigImpl;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
 import io.netty.channel.Channel;
 import io.netty.handler.ssl.SslContext;
 import io.netty.handler.ssl.SslContextBuilder;
@@ -37,14 +37,14 @@
  * @author Christoph Schäbel
  * @author Silvio Giebl
  */
-public final class MqttSslInitializer {
+public final class MqttTlsInitializer {
 
-    private static final @NotNull String SSL_HANDLER_NAME = "ssl";
+    private static final @NotNull String SSL_HANDLER_NAME = "tls";
 
     public static void initChannel(
             final @NotNull Channel channel,
             final @NotNull MqttClientConfig clientConfig,
-            final @NotNull MqttClientSslConfigImpl sslConfig,
+            final @NotNull MqttTlsConfigImpl tlsConfig,
             final @NotNull Consumer<Channel> onSuccess,
             final @NotNull BiConsumer<Channel, Throwable> onError) {
 
@@ -54,7 +54,7 @@ public static void initChannel(
         try {
             SslContext sslContext = clientConfig.getCurrentSslContext();
             if (sslContext == null) {
-                sslContext = createSslContext(sslConfig);
+                sslContext = createSslContext(tlsConfig);
                 clientConfig.setCurrentSslContext(sslContext);
             }
             sslHandler = sslContext.newHandler(channel.alloc(), serverAddress.getHostString(), serverAddress.getPort());
@@ -63,32 +63,32 @@ public static void initChannel(
             return;
         }
 
-        sslHandler.setHandshakeTimeoutMillis(sslConfig.getHandshakeTimeoutMs());
+        sslHandler.setHandshakeTimeoutMillis(tlsConfig.getHandshakeTimeoutMs());
 
-        final HostnameVerifier hostnameVerifier = sslConfig.getRawHostnameVerifier();
+        final HostnameVerifier hostnameVerifier = tlsConfig.getRawHostnameVerifier();
         if (hostnameVerifier == null) {
             final SSLParameters sslParameters = sslHandler.engine().getSSLParameters();
             sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
             sslHandler.engine().setSSLParameters(sslParameters);
         }
 
-        final MqttSslAdapterHandler sslAdapterHandler =
-                new MqttSslAdapterHandler(sslHandler, serverAddress.getHostString(), hostnameVerifier, onSuccess,
+        final MqttTlsAdapterHandler tlsAdapterHandler =
+                new MqttTlsAdapterHandler(sslHandler, serverAddress.getHostString(), hostnameVerifier, onSuccess,
                         onError);
 
-        channel.pipeline().addLast(SSL_HANDLER_NAME, sslHandler).addLast(MqttSslAdapterHandler.NAME, sslAdapterHandler);
+        channel.pipeline().addLast(SSL_HANDLER_NAME, sslHandler).addLast(MqttTlsAdapterHandler.NAME, tlsAdapterHandler);
     }
 
-    static @NotNull SslContext createSslContext(final @NotNull MqttClientSslConfigImpl sslConfig) throws SSLException {
-        final ImmutableList<String> protocols = sslConfig.getRawProtocols();
+    static @NotNull SslContext createSslContext(final @NotNull MqttTlsConfigImpl tlsConfig) throws SSLException {
+        final ImmutableList<String> protocols = tlsConfig.getRawProtocols();
 
         return SslContextBuilder.forClient()
-                .trustManager(sslConfig.getRawTrustManagerFactory())
-                .keyManager(sslConfig.getRawKeyManagerFactory())
+                .trustManager(tlsConfig.getRawTrustManagerFactory())
+                .keyManager(tlsConfig.getRawKeyManagerFactory())
                 .protocols((protocols == null) ? null : protocols.toArray(new String[0]))
-                .ciphers(sslConfig.getRawCipherSuites(), SupportedCipherSuiteFilter.INSTANCE)
+                .ciphers(tlsConfig.getRawCipherSuites(), SupportedCipherSuiteFilter.INSTANCE)
                 .build();
     }
 
-    private MqttSslInitializer() {}
+    private MqttTlsInitializer() {}
 }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/util/FlowWithEventLoop.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/util/FlowWithEventLoop.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/util/FlowWithEventLoop.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/util/FlowWithEventLoop.java
index 4c116c9e4..75ac38584 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/util/FlowWithEventLoop.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/util/FlowWithEventLoop.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.util;
+package com.hivemq.client2.internal.mqtt.handler.util;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
 import io.netty.channel.EventLoop;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/util/MqttTimeoutInboundHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/util/MqttTimeoutInboundHandler.java
similarity index 83%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/util/MqttTimeoutInboundHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/util/MqttTimeoutInboundHandler.java
index 06857674f..166479edc 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/util/MqttTimeoutInboundHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/util/MqttTimeoutInboundHandler.java
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.util;
+package com.hivemq.client2.internal.mqtt.handler.util;
 
-import com.hivemq.client.internal.annotations.CallByThread;
-import com.hivemq.client.internal.mqtt.handler.MqttConnectionAwareHandler;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.internal.annotations.CallByThread;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.handler.MqttConnectionAwareHandler;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
@@ -40,6 +42,7 @@
 public abstract class MqttTimeoutInboundHandler extends MqttConnectionAwareHandler
         implements Runnable, ChannelFutureListener {
 
+    private static final @NotNull InternalLogger LOGGER = InternalLoggerFactory.getLogger(MqttTimeoutInboundHandler.class);
     private @Nullable ScheduledFuture<?> timeoutFuture;
 
     /**
@@ -109,6 +112,7 @@ protected void cancelTimeout() {
     @Override
     protected void onDisconnectEvent(
             final @NotNull ChannelHandlerContext ctx, final @NotNull MqttDisconnectEvent disconnectEvent) {
+        LOGGER.debug("OnDisconnectedEvent: source: {}, cause: {}", disconnectEvent.getSource(), disconnectEvent.getCause());
 
         cancelTimeout();
     }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/websocket/MqttWebSocketCodec.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/websocket/MqttWebSocketCodec.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/websocket/MqttWebSocketCodec.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/websocket/MqttWebSocketCodec.java
index ede95cc2b..c0653a182 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/websocket/MqttWebSocketCodec.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/websocket/MqttWebSocketCodec.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.websocket;
+package com.hivemq.client2.internal.mqtt.handler.websocket;
 
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectUtil;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelDuplexHandler;
 import io.netty.channel.ChannelHandler;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/websocket/MqttWebSocketInitializer.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/websocket/MqttWebSocketInitializer.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/websocket/MqttWebSocketInitializer.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/websocket/MqttWebSocketInitializer.java
index ed1c4c3f4..f0a12f1b9 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/websocket/MqttWebSocketInitializer.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/websocket/MqttWebSocketInitializer.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.websocket;
+package com.hivemq.client2.internal.mqtt.handler.websocket;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientTransportConfigImpl;
-import com.hivemq.client.internal.mqtt.MqttWebSocketConfigImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.ioc.ConnectionScope;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttTransportConfigImpl;
+import com.hivemq.client2.internal.mqtt.MqttWebSocketConfigImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.ioc.ConnectionScope;
 import io.netty.channel.Channel;
 import io.netty.handler.codec.http.HttpClientCodec;
 import io.netty.handler.codec.http.HttpObjectAggregator;
@@ -61,11 +61,11 @@ public void initChannel(
 
         final URI uri;
         try {
-            final MqttClientTransportConfigImpl transportConfig = clientConfig.getCurrentTransportConfig();
+            final MqttTransportConfigImpl transportConfig = clientConfig.getCurrentTransportConfig();
             final InetSocketAddress serverAddress = transportConfig.getServerAddress();
-            uri = new URI((transportConfig.getRawSslConfig() == null) ? "ws" : "wss", null,
-                    serverAddress.getHostString(), serverAddress.getPort(), "/" + webSocketConfig.getServerPath(),
-                    webSocketConfig.getQueryString(), null);
+            uri = new URI((transportConfig.getRawTlsConfig() == null) ? "ws" : "wss", null,
+                    serverAddress.getHostString(), serverAddress.getPort(), "/" + webSocketConfig.getPath(),
+                    webSocketConfig.getQuery(), null);
         } catch (final URISyntaxException e) {
             onError.accept(channel, e);
             return;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/handler/websocket/MqttWebsocketHandshakeHandler.java b/src/main/java/com/hivemq/client2/internal/mqtt/handler/websocket/MqttWebsocketHandshakeHandler.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/mqtt/handler/websocket/MqttWebsocketHandshakeHandler.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/handler/websocket/MqttWebsocketHandshakeHandler.java
index dcde3a0ad..4572acbb0 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/handler/websocket/MqttWebsocketHandshakeHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/handler/websocket/MqttWebsocketHandshakeHandler.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.websocket;
+package com.hivemq.client2.internal.mqtt.handler.websocket;
 
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandlerContext;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ClientComponent.java b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/ClientComponent.java
similarity index 77%
rename from src/main/java/com/hivemq/client/internal/mqtt/ioc/ClientComponent.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/ioc/ClientComponent.java
index b79446b0c..6ccd41f6d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ClientComponent.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/ClientComponent.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.ioc;
+package com.hivemq.client2.internal.mqtt.ioc;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.handler.publish.incoming.MqttIncomingQosHandler;
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttOutgoingQosHandler;
-import com.hivemq.client.internal.mqtt.handler.subscribe.MqttSubscriptionHandler;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.handler.publish.incoming.MqttIncomingQosHandler;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttOutgoingQosHandler;
+import com.hivemq.client2.internal.mqtt.handler.subscribe.MqttSubscriptionHandler;
 import dagger.BindsInstance;
 import dagger.Subcomponent;
 import org.jetbrains.annotations.NotNull;
@@ -29,7 +29,7 @@
  *
  * @author Silvio Giebl
  */
-@Subcomponent(modules = {ClientModule.class})
+@Subcomponent
 @ClientScope
 public interface ClientComponent {
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ClientScope.java b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/ClientScope.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/mqtt/ioc/ClientScope.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/ioc/ClientScope.java
index 34ede4af2..e9449a4f5 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ClientScope.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/ClientScope.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.ioc;
+package com.hivemq.client2.internal.mqtt.ioc;
 
 import javax.inject.Scope;
 import java.lang.annotation.Documented;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ConnectionComponent.java b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/ConnectionComponent.java
similarity index 84%
rename from src/main/java/com/hivemq/client/internal/mqtt/ioc/ConnectionComponent.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/ioc/ConnectionComponent.java
index 60fbb2e66..dd469dc9e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ConnectionComponent.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/ConnectionComponent.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.ioc;
+package com.hivemq.client2.internal.mqtt.ioc;
 
-import com.hivemq.client.internal.mqtt.codec.MqttCodecModule;
-import com.hivemq.client.internal.mqtt.handler.connect.MqttConnAckFlow;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.codec.MqttCodecModule;
+import com.hivemq.client2.internal.mqtt.handler.connect.MqttConnAckFlow;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
 import dagger.BindsInstance;
 import dagger.Subcomponent;
 import io.netty.bootstrap.Bootstrap;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ConnectionModule.java b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/ConnectionModule.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/ioc/ConnectionModule.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/ioc/ConnectionModule.java
index 34d516c4c..8be9ee528 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ConnectionModule.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/ConnectionModule.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.ioc;
+package com.hivemq.client2.internal.mqtt.ioc;
 
-import com.hivemq.client.internal.mqtt.handler.MqttChannelInitializer;
-import com.hivemq.client.internal.mqtt.handler.auth.MqttAuthHandler;
-import com.hivemq.client.internal.mqtt.handler.auth.MqttConnectAuthHandler;
-import com.hivemq.client.internal.mqtt.handler.auth.MqttDisconnectOnAuthHandler;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.netty.NettyEventLoopProvider;
+import com.hivemq.client2.internal.mqtt.handler.MqttChannelInitializer;
+import com.hivemq.client2.internal.mqtt.handler.auth.MqttAuthHandler;
+import com.hivemq.client2.internal.mqtt.handler.auth.MqttConnectAuthHandler;
+import com.hivemq.client2.internal.mqtt.handler.auth.MqttDisconnectOnAuthHandler;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.netty.NettyEventLoopProvider;
 import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ConnectionScope.java b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/ConnectionScope.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/mqtt/ioc/ConnectionScope.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/ioc/ConnectionScope.java
index 56363f8fe..89b17371c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/ioc/ConnectionScope.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/ConnectionScope.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.ioc;
+package com.hivemq.client2.internal.mqtt.ioc;
 
 import javax.inject.Scope;
 import java.lang.annotation.Documented;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/ioc/SingletonComponent.java b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/SingletonComponent.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/mqtt/ioc/SingletonComponent.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/ioc/SingletonComponent.java
index 7129a5407..3534076b6 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/ioc/SingletonComponent.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/ioc/SingletonComponent.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.ioc;
+package com.hivemq.client2.internal.mqtt.ioc;
 
 import dagger.Component;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientAutoReconnectImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttAutoReconnectImpl.java
similarity index 50%
rename from src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientAutoReconnectImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttAutoReconnectImpl.java
index 28be4ecdd..906bd3880 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientAutoReconnectImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttAutoReconnectImpl.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.lifecycle;
+package com.hivemq.client2.internal.mqtt.lifecycle;
 
-import com.hivemq.client.mqtt.lifecycle.MqttClientAutoReconnect;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedContext;
-import com.hivemq.client.mqtt.lifecycle.MqttClientReconnector;
-import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource;
+import com.hivemq.client2.mqtt.lifecycle.MqttAutoReconnect;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectSource;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedContext;
+import com.hivemq.client2.mqtt.lifecycle.MqttReconnector;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
@@ -28,26 +29,28 @@
 /**
  * @author Silvio Giebl
  */
-public class MqttClientAutoReconnectImpl implements MqttClientAutoReconnect {
+public class MqttAutoReconnectImpl implements MqttAutoReconnect {
 
-    static final long DEFAULT_START_DELAY_NANOS =
-            TimeUnit.SECONDS.toNanos(MqttClientAutoReconnect.DEFAULT_START_DELAY_S);
-    static final long DEFAULT_MAX_DELAY_NANOS = TimeUnit.SECONDS.toNanos(MqttClientAutoReconnect.DEFAULT_MAX_DELAY_S);
-    public static final @NotNull MqttClientAutoReconnectImpl DEFAULT =
-            new MqttClientAutoReconnectImpl(DEFAULT_START_DELAY_NANOS, DEFAULT_MAX_DELAY_NANOS);
+    static final long DEFAULT_START_DELAY_NANOS = TimeUnit.SECONDS.toNanos(MqttAutoReconnect.DEFAULT_START_DELAY_S);
+    static final long DEFAULT_MAX_DELAY_NANOS = TimeUnit.SECONDS.toNanos(MqttAutoReconnect.DEFAULT_MAX_DELAY_S);
+    public static final @NotNull MqttAutoReconnectImpl DEFAULT =
+            new MqttAutoReconnectImpl(DEFAULT_START_DELAY_NANOS, DEFAULT_MAX_DELAY_NANOS);
 
-    private final long initialDelayNanos;
-    private final long maxDelayNanos;
+    private final @Range(from = 1, to = Long.MAX_VALUE) long initialDelayNanos;
+    private final @Range(from = 0, to = Long.MAX_VALUE) long maxDelayNanos;
+
+    MqttAutoReconnectImpl(
+            final @Range(from = 1, to = Long.MAX_VALUE) long initialDelayNanos,
+            final @Range(from = 0, to = Long.MAX_VALUE) long maxDelayNanos) {
 
-    MqttClientAutoReconnectImpl(final long initialDelayNanos, final long maxDelayNanos) {
         this.initialDelayNanos = initialDelayNanos;
         this.maxDelayNanos = maxDelayNanos;
     }
 
     @Override
-    public void onDisconnected(final @NotNull MqttClientDisconnectedContext context) {
+    public void onDisconnected(final @NotNull MqttDisconnectedContext context) {
         if (context.getSource() != MqttDisconnectSource.USER) {
-            final MqttClientReconnector reconnector = context.getReconnector();
+            final MqttReconnector reconnector = context.getReconnector();
             final long delay =
                     (long) Math.min(initialDelayNanos * Math.pow(2, reconnector.getAttempts()), maxDelayNanos);
             final long randomDelay = (long) (delay / 4d / Integer.MAX_VALUE * ThreadLocalRandom.current().nextInt());
@@ -56,17 +59,17 @@ public void onDisconnected(final @NotNull MqttClientDisconnectedContext context)
     }
 
     @Override
-    public long getInitialDelay(final @NotNull TimeUnit timeUnit) {
+    public @Range(from = 1, to = Long.MAX_VALUE) long getInitialDelay(final @NotNull TimeUnit timeUnit) {
         return timeUnit.convert(initialDelayNanos, TimeUnit.NANOSECONDS);
     }
 
     @Override
-    public long getMaxDelay(final @NotNull TimeUnit timeUnit) {
+    public @Range(from = 0, to = Long.MAX_VALUE) long getMaxDelay(final @NotNull TimeUnit timeUnit) {
         return timeUnit.convert(maxDelayNanos, TimeUnit.NANOSECONDS);
     }
 
     @Override
-    public MqttClientAutoReconnectImplBuilder.@NotNull Default extend() {
-        return new MqttClientAutoReconnectImplBuilder.Default(this);
+    public MqttAutoReconnectImplBuilder.@NotNull Default extend() {
+        return new MqttAutoReconnectImplBuilder.Default(this);
     }
 }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientAutoReconnectImplBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttAutoReconnectImplBuilder.java
similarity index 62%
rename from src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientAutoReconnectImplBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttAutoReconnectImplBuilder.java
index dc7e866b6..1fbcf76be 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientAutoReconnectImplBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttAutoReconnectImplBuilder.java
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.lifecycle;
+package com.hivemq.client2.internal.mqtt.lifecycle;
 
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.lifecycle.MqttClientAutoReconnectBuilder;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.lifecycle.MqttAutoReconnectBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
@@ -27,14 +28,15 @@
 /**
  * @author Silvio Giebl
  */
-public abstract class MqttClientAutoReconnectImplBuilder<B extends MqttClientAutoReconnectImplBuilder<B>> {
+public abstract class MqttAutoReconnectImplBuilder<B extends MqttAutoReconnectImplBuilder<B>> {
 
-    private long initialDelayNanos = MqttClientAutoReconnectImpl.DEFAULT_START_DELAY_NANOS;
-    private long maxDelayNanos = MqttClientAutoReconnectImpl.DEFAULT_MAX_DELAY_NANOS;
+    private @Range(from = 1, to = Long.MAX_VALUE) long initialDelayNanos =
+            MqttAutoReconnectImpl.DEFAULT_START_DELAY_NANOS;
+    private @Range(from = 0, to = Long.MAX_VALUE) long maxDelayNanos = MqttAutoReconnectImpl.DEFAULT_MAX_DELAY_NANOS;
 
-    MqttClientAutoReconnectImplBuilder() {}
+    MqttAutoReconnectImplBuilder() {}
 
-    MqttClientAutoReconnectImplBuilder(final @Nullable MqttClientAutoReconnectImpl autoReconnect) {
+    MqttAutoReconnectImplBuilder(final @Nullable MqttAutoReconnectImpl autoReconnect) {
         if (autoReconnect != null) {
             initialDelayNanos = autoReconnect.getInitialDelay(TimeUnit.NANOSECONDS);
             maxDelayNanos = autoReconnect.getMaxDelay(TimeUnit.NANOSECONDS);
@@ -61,16 +63,15 @@ public abstract class MqttClientAutoReconnectImplBuilder<B extends MqttClientAut
         return self();
     }
 
-    public @NotNull MqttClientAutoReconnectImpl build() {
-        return new MqttClientAutoReconnectImpl(initialDelayNanos, maxDelayNanos);
+    public @NotNull MqttAutoReconnectImpl build() {
+        return new MqttAutoReconnectImpl(initialDelayNanos, maxDelayNanos);
     }
 
-    public static class Default extends MqttClientAutoReconnectImplBuilder<Default>
-            implements MqttClientAutoReconnectBuilder {
+    public static class Default extends MqttAutoReconnectImplBuilder<Default> implements MqttAutoReconnectBuilder {
 
         public Default() {}
 
-        Default(final @Nullable MqttClientAutoReconnectImpl autoReconnect) {
+        Default(final @Nullable MqttAutoReconnectImpl autoReconnect) {
             super(autoReconnect);
         }
 
@@ -80,14 +81,14 @@ public Default() {}
         }
     }
 
-    public static class Nested<P> extends MqttClientAutoReconnectImplBuilder<Nested<P>>
-            implements MqttClientAutoReconnectBuilder.Nested<P> {
+    public static class Nested<P> extends MqttAutoReconnectImplBuilder<Nested<P>>
+            implements MqttAutoReconnectBuilder.Nested<P> {
 
-        private final @NotNull Function<? super MqttClientAutoReconnectImpl, P> parentConsumer;
+        private final @NotNull Function<? super MqttAutoReconnectImpl, P> parentConsumer;
 
         public Nested(
-                final @Nullable MqttClientAutoReconnectImpl autoReconnect,
-                final @NotNull Function<? super MqttClientAutoReconnectImpl, P> parentConsumer) {
+                final @Nullable MqttAutoReconnectImpl autoReconnect,
+                final @NotNull Function<? super MqttAutoReconnectImpl, P> parentConsumer) {
 
             super(autoReconnect);
             this.parentConsumer = parentConsumer;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientConnectedContextImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttConnectedContextImpl.java
similarity index 65%
rename from src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientConnectedContextImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttConnectedContextImpl.java
index bd9ae8362..3181f617f 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientConnectedContextImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttConnectedContextImpl.java
@@ -14,38 +14,38 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.lifecycle;
+package com.hivemq.client2.internal.mqtt.lifecycle;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.lifecycle.mqtt3.Mqtt3ClientConnectedContextView;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.mqtt.MqttVersion;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedContext;
-import com.hivemq.client.mqtt.mqtt5.lifecycle.Mqtt5ClientConnectedContext;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.lifecycle.mqtt3.Mqtt3ConnectedContextView;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.mqtt.MqttVersion;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedContext;
+import com.hivemq.client2.mqtt.mqtt5.lifecycle.Mqtt5ConnectedContext;
 import org.jetbrains.annotations.NotNull;
 
 /**
  * @author Silvio Giebl
  */
-public class MqttClientConnectedContextImpl implements Mqtt5ClientConnectedContext {
+public class MqttConnectedContextImpl implements Mqtt5ConnectedContext {
 
-    public static @NotNull MqttClientConnectedContext of(
+    public static @NotNull MqttConnectedContext of(
             final @NotNull MqttClientConfig clientConfig,
             final @NotNull MqttConnect connect,
             final @NotNull MqttConnAck connAck) {
 
         if (clientConfig.getMqttVersion() == MqttVersion.MQTT_3_1_1) {
-            return Mqtt3ClientConnectedContextView.of(clientConfig, connect, connAck);
+            return Mqtt3ConnectedContextView.of(clientConfig, connect, connAck);
         }
-        return new MqttClientConnectedContextImpl(clientConfig, connect, connAck);
+        return new MqttConnectedContextImpl(clientConfig, connect, connAck);
     }
 
     private final @NotNull MqttClientConfig clientConfig;
     private final @NotNull MqttConnect connect;
     private final @NotNull MqttConnAck connAck;
 
-    private MqttClientConnectedContextImpl(
+    private MqttConnectedContextImpl(
             final @NotNull MqttClientConfig clientConfig,
             final @NotNull MqttConnect connect,
             final @NotNull MqttConnAck connAck) {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientDisconnectedContextImpl.java b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttDisconnectedContextImpl.java
similarity index 61%
rename from src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientDisconnectedContextImpl.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttDisconnectedContextImpl.java
index 9296bea82..8ba674f2d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientDisconnectedContextImpl.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttDisconnectedContextImpl.java
@@ -14,43 +14,43 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.lifecycle;
+package com.hivemq.client2.internal.mqtt.lifecycle;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.lifecycle.mqtt3.Mqtt3ClientDisconnectedContextView;
-import com.hivemq.client.mqtt.MqttVersion;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedContext;
-import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource;
-import com.hivemq.client.mqtt.mqtt5.lifecycle.Mqtt5ClientDisconnectedContext;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.lifecycle.mqtt3.Mqtt3DisconnectedContextView;
+import com.hivemq.client2.mqtt.MqttVersion;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectSource;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedContext;
+import com.hivemq.client2.mqtt.mqtt5.lifecycle.Mqtt5DisconnectedContext;
 import org.jetbrains.annotations.NotNull;
 
 /**
  * @author Silvio Giebl
  */
-public class MqttClientDisconnectedContextImpl implements Mqtt5ClientDisconnectedContext {
+public class MqttDisconnectedContextImpl implements Mqtt5DisconnectedContext {
 
-    public static @NotNull MqttClientDisconnectedContext of(
+    public static @NotNull MqttDisconnectedContext of(
             final @NotNull MqttClientConfig clientConfig,
             final @NotNull MqttDisconnectSource source,
             final @NotNull Throwable cause,
-            final @NotNull MqttClientReconnector reconnector) {
+            final @NotNull MqttReconnector reconnector) {
 
         if (clientConfig.getMqttVersion() == MqttVersion.MQTT_3_1_1) {
-            return Mqtt3ClientDisconnectedContextView.of(clientConfig, source, cause, reconnector);
+            return Mqtt3DisconnectedContextView.of(clientConfig, source, cause, reconnector);
         }
-        return new MqttClientDisconnectedContextImpl(clientConfig, source, cause, reconnector);
+        return new MqttDisconnectedContextImpl(clientConfig, source, cause, reconnector);
     }
 
     private final @NotNull MqttClientConfig clientConfig;
     private final @NotNull MqttDisconnectSource source;
     private final @NotNull Throwable cause;
-    private final @NotNull MqttClientReconnector reconnector;
+    private final @NotNull MqttReconnector reconnector;
 
-    private MqttClientDisconnectedContextImpl(
+    private MqttDisconnectedContextImpl(
             final @NotNull MqttClientConfig clientConfig,
             final @NotNull MqttDisconnectSource source,
             final @NotNull Throwable cause,
-            final @NotNull MqttClientReconnector reconnector) {
+            final @NotNull MqttReconnector reconnector) {
 
         this.clientConfig = clientConfig;
         this.source = source;
@@ -74,7 +74,7 @@ private MqttClientDisconnectedContextImpl(
     }
 
     @Override
-    public @NotNull MqttClientReconnector getReconnector() {
+    public @NotNull MqttReconnector getReconnector() {
         return reconnector;
     }
 }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientReconnector.java b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttReconnector.java
similarity index 67%
rename from src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientReconnector.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttReconnector.java
index 48ee6b414..7d4af210c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/MqttClientReconnector.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/MqttReconnector.java
@@ -14,20 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.lifecycle;
-
-import com.hivemq.client.internal.mqtt.MqttClientTransportConfigImpl;
-import com.hivemq.client.internal.mqtt.MqttClientTransportConfigImplBuilder;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttClientTransportConfig;
-import com.hivemq.client.mqtt.mqtt5.lifecycle.Mqtt5ClientReconnector;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
+package com.hivemq.client2.internal.mqtt.lifecycle;
+
+import com.hivemq.client2.internal.mqtt.MqttTransportConfigImpl;
+import com.hivemq.client2.internal.mqtt.MqttTransportConfigImplBuilder;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttTransportConfig;
+import com.hivemq.client2.mqtt.mqtt5.lifecycle.Mqtt5Reconnector;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
 import io.netty.channel.EventLoop;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
@@ -36,25 +37,25 @@
 /**
  * @author Silvio Giebl
  */
-public class MqttClientReconnector implements Mqtt5ClientReconnector {
+public class MqttReconnector implements Mqtt5Reconnector {
 
     private final @NotNull EventLoop eventLoop;
-    private final int attempts;
+    private final @Range(from = 0, to = Integer.MAX_VALUE) int attempts;
     private boolean reconnect = DEFAULT_RECONNECT;
     private @Nullable CompletableFuture<?> future;
     private boolean resubscribeIfSessionExpired = DEFAULT_RESUBSCRIBE_IF_SESSION_EXPIRED;
     private boolean republishIfSessionExpired = DEFAULT_REPUBLISH_IF_SESSION_EXPIRED;
     private long delayNanos = TimeUnit.MILLISECONDS.toNanos(DEFAULT_DELAY_MS);
-    private @NotNull MqttClientTransportConfigImpl transportConfig;
+    private @NotNull MqttTransportConfigImpl transportConfig;
     private @NotNull MqttConnect connect;
 
     private boolean afterOnDisconnected;
 
-    public MqttClientReconnector(
+    public MqttReconnector(
             final @NotNull EventLoop eventLoop,
-            final int attempts,
+            final @Range(from = 0, to = Integer.MAX_VALUE) int attempts,
             final @NotNull MqttConnect connect,
-            final @NotNull MqttClientTransportConfigImpl transportConfig) {
+            final @NotNull MqttTransportConfigImpl transportConfig) {
 
         this.eventLoop = eventLoop;
         this.attempts = attempts;
@@ -63,20 +64,20 @@ public MqttClientReconnector(
     }
 
     @Override
-    public int getAttempts() {
+    public @Range(from = 0, to = Integer.MAX_VALUE) int getAttempts() {
         checkInEventLoop();
         return attempts;
     }
 
     @Override
-    public @NotNull MqttClientReconnector reconnect(final boolean reconnect) {
+    public @NotNull MqttReconnector reconnect(final boolean reconnect) {
         checkInEventLoop();
         this.reconnect = reconnect;
         return this;
     }
 
     @Override
-    public <T> @NotNull MqttClientReconnector reconnectWhen(
+    public <T> @NotNull MqttReconnector reconnectWhen(
             @Nullable CompletableFuture<T> future, final @Nullable BiConsumer<? super T, ? super Throwable> callback) {
 
         checkInOnDisconnected("reconnectWhen");
@@ -101,7 +102,7 @@ public boolean isReconnect() {
     }
 
     @Override
-    public @NotNull MqttClientReconnector resubscribeIfSessionExpired(final boolean resubscribe) {
+    public @NotNull MqttReconnector resubscribeIfSessionExpired(final boolean resubscribe) {
         checkInOnDisconnected("resubscribeIfSessionExpired");
         resubscribeIfSessionExpired = resubscribe;
         return this;
@@ -114,7 +115,7 @@ public boolean isResubscribeIfSessionExpired() {
     }
 
     @Override
-    public @NotNull MqttClientReconnector republishIfSessionExpired(final boolean republish) {
+    public @NotNull MqttReconnector republishIfSessionExpired(final boolean republish) {
         checkInOnDisconnected("republishIfSessionExpired");
         republishIfSessionExpired = republish;
         return this;
@@ -127,7 +128,7 @@ public boolean isRepublishIfSessionExpired() {
     }
 
     @Override
-    public @NotNull MqttClientReconnector delay(final long delay, final @Nullable TimeUnit timeUnit) {
+    public @NotNull MqttReconnector delay(final long delay, final @Nullable TimeUnit timeUnit) {
         checkInOnDisconnected("delay");
         Checks.notNull(timeUnit, "Time unit");
         this.delayNanos = timeUnit.toNanos(delay);
@@ -142,34 +143,34 @@ public long getDelay(final @NotNull TimeUnit timeUnit) {
     }
 
     @Override
-    public @NotNull MqttClientReconnector transportConfig(final @Nullable MqttClientTransportConfig transportConfig) {
+    public @NotNull MqttReconnector transportConfig(final @Nullable MqttTransportConfig transportConfig) {
         checkInEventLoop();
         this.transportConfig =
-                Checks.notImplemented(transportConfig, MqttClientTransportConfigImpl.class, "Transport config");
+                Checks.notImplemented(transportConfig, MqttTransportConfigImpl.class, "Transport config");
         return this;
     }
 
     @Override
-    public MqttClientTransportConfigImplBuilder.@NotNull Nested<MqttClientReconnector> transportConfig() {
+    public MqttTransportConfigImplBuilder.@NotNull Nested<MqttReconnector> transportConfigWith() {
         checkInEventLoop();
-        return new MqttClientTransportConfigImplBuilder.Nested<>(transportConfig, this::transportConfig);
+        return new MqttTransportConfigImplBuilder.Nested<>(transportConfig, this::transportConfig);
     }
 
     @Override
-    public @NotNull MqttClientTransportConfigImpl getTransportConfig() {
+    public @NotNull MqttTransportConfigImpl getTransportConfig() {
         checkInEventLoop();
         return transportConfig;
     }
 
     @Override
-    public @NotNull MqttClientReconnector connect(final @Nullable Mqtt5Connect connect) {
+    public @NotNull MqttReconnector connect(final @Nullable Mqtt5Connect connect) {
         checkInEventLoop();
         this.connect = MqttChecks.connect(connect);
         return this;
     }
 
     @Override
-    public MqttConnectBuilder.@NotNull Nested<MqttClientReconnector> connectWith() {
+    public MqttConnectBuilder.@NotNull Nested<MqttReconnector> connectWith() {
         checkInEventLoop();
         return new MqttConnectBuilder.Nested<>(connect, this::connect);
     }
@@ -185,7 +186,7 @@ public void afterOnDisconnected() {
     }
 
     private void checkInEventLoop() {
-        Checks.state(eventLoop.inEventLoop(), "MqttClientReconnector must be called from the eventLoop.");
+        Checks.state(eventLoop.inEventLoop(), "MqttReconnector must be called from the eventLoop.");
     }
 
     private void checkInOnDisconnected(final @NotNull String method) {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/mqtt3/Mqtt3ClientConnectedContextView.java b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/mqtt3/Mqtt3ConnectedContextView.java
similarity index 66%
rename from src/main/java/com/hivemq/client/internal/mqtt/lifecycle/mqtt3/Mqtt3ClientConnectedContextView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/mqtt3/Mqtt3ConnectedContextView.java
index aac46e0f5..8f6158647 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/mqtt3/Mqtt3ClientConnectedContextView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/mqtt3/Mqtt3ConnectedContextView.java
@@ -14,29 +14,29 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.lifecycle.mqtt3;
+package com.hivemq.client2.internal.mqtt.lifecycle.mqtt3;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.internal.mqtt.message.connect.connack.mqtt3.Mqtt3ConnAckView;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
-import com.hivemq.client.internal.mqtt.mqtt3.Mqtt3ClientConfigView;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedContext;
-import com.hivemq.client.mqtt.mqtt3.lifecycle.Mqtt3ClientConnectedContext;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnAckView;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
+import com.hivemq.client2.internal.mqtt.mqtt3.Mqtt3ClientConfigView;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedContext;
+import com.hivemq.client2.mqtt.mqtt3.lifecycle.Mqtt3ConnectedContext;
 import org.jetbrains.annotations.NotNull;
 
 /**
  * @author Silvio Giebl
  */
-public class Mqtt3ClientConnectedContextView implements Mqtt3ClientConnectedContext {
+public class Mqtt3ConnectedContextView implements Mqtt3ConnectedContext {
 
-    public static @NotNull MqttClientConnectedContext of(
+    public static @NotNull MqttConnectedContext of(
             final @NotNull MqttClientConfig clientConfig,
             final @NotNull MqttConnect connect,
             final @NotNull MqttConnAck connAck) {
 
-        return new Mqtt3ClientConnectedContextView(
+        return new Mqtt3ConnectedContextView(
                 new Mqtt3ClientConfigView(clientConfig), Mqtt3ConnectView.of(connect), Mqtt3ConnAckView.of(connAck));
     }
 
@@ -44,7 +44,7 @@ public class Mqtt3ClientConnectedContextView implements Mqtt3ClientConnectedCont
     private final @NotNull Mqtt3ConnectView connect;
     private final @NotNull Mqtt3ConnAckView connAck;
 
-    private Mqtt3ClientConnectedContextView(
+    private Mqtt3ConnectedContextView(
             final @NotNull Mqtt3ClientConfigView clientConfig,
             final @NotNull Mqtt3ConnectView connect,
             final @NotNull Mqtt3ConnAckView connAck) {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/mqtt3/Mqtt3ClientDisconnectedContextView.java b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/mqtt3/Mqtt3DisconnectedContextView.java
similarity index 58%
rename from src/main/java/com/hivemq/client/internal/mqtt/lifecycle/mqtt3/Mqtt3ClientDisconnectedContextView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/mqtt3/Mqtt3DisconnectedContextView.java
index bf65d8596..a34c3a412 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/mqtt3/Mqtt3ClientDisconnectedContextView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/mqtt3/Mqtt3DisconnectedContextView.java
@@ -14,42 +14,42 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.lifecycle.mqtt3;
+package com.hivemq.client2.internal.mqtt.lifecycle.mqtt3;
 
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.exceptions.mqtt3.Mqtt3ExceptionFactory;
-import com.hivemq.client.internal.mqtt.lifecycle.MqttClientReconnector;
-import com.hivemq.client.internal.mqtt.mqtt3.Mqtt3ClientConfigView;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedContext;
-import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource;
-import com.hivemq.client.mqtt.mqtt3.lifecycle.Mqtt3ClientDisconnectedContext;
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.exceptions.mqtt3.Mqtt3ExceptionFactory;
+import com.hivemq.client2.internal.mqtt.lifecycle.MqttReconnector;
+import com.hivemq.client2.internal.mqtt.mqtt3.Mqtt3ClientConfigView;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectSource;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedContext;
+import com.hivemq.client2.mqtt.mqtt3.lifecycle.Mqtt3DisconnectedContext;
 import org.jetbrains.annotations.NotNull;
 
 /**
  * @author Silvio Giebl
  */
-public class Mqtt3ClientDisconnectedContextView implements Mqtt3ClientDisconnectedContext {
+public class Mqtt3DisconnectedContextView implements Mqtt3DisconnectedContext {
 
-    public static @NotNull MqttClientDisconnectedContext of(
+    public static @NotNull MqttDisconnectedContext of(
             final @NotNull MqttClientConfig clientConfig,
             final @NotNull MqttDisconnectSource source,
             final @NotNull Throwable cause,
-            final @NotNull MqttClientReconnector reconnector) {
+            final @NotNull MqttReconnector reconnector) {
 
-        return new Mqtt3ClientDisconnectedContextView(new Mqtt3ClientConfigView(clientConfig), source,
-                Mqtt3ExceptionFactory.map(cause), new Mqtt3ClientReconnectorView(reconnector));
+        return new Mqtt3DisconnectedContextView(new Mqtt3ClientConfigView(clientConfig), source,
+                Mqtt3ExceptionFactory.map(cause), new Mqtt3ReconnectorView(reconnector));
     }
 
     private final @NotNull Mqtt3ClientConfigView clientConfig;
     private final @NotNull MqttDisconnectSource source;
     private final @NotNull Throwable cause;
-    private final @NotNull Mqtt3ClientReconnectorView reconnector;
+    private final @NotNull Mqtt3ReconnectorView reconnector;
 
-    private Mqtt3ClientDisconnectedContextView(
+    private Mqtt3DisconnectedContextView(
             final @NotNull Mqtt3ClientConfigView clientConfig,
             final @NotNull MqttDisconnectSource source,
             final @NotNull Throwable cause,
-            final @NotNull Mqtt3ClientReconnectorView reconnector) {
+            final @NotNull Mqtt3ReconnectorView reconnector) {
 
         this.clientConfig = clientConfig;
         this.source = source;
@@ -73,7 +73,7 @@ private Mqtt3ClientDisconnectedContextView(
     }
 
     @Override
-    public @NotNull Mqtt3ClientReconnectorView getReconnector() {
+    public @NotNull Mqtt3ReconnectorView getReconnector() {
         return reconnector;
     }
 }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/mqtt3/Mqtt3ClientReconnectorView.java b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/mqtt3/Mqtt3ReconnectorView.java
similarity index 56%
rename from src/main/java/com/hivemq/client/internal/mqtt/lifecycle/mqtt3/Mqtt3ClientReconnectorView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/mqtt3/Mqtt3ReconnectorView.java
index d56bf3763..510970ffb 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/lifecycle/mqtt3/Mqtt3ClientReconnectorView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/lifecycle/mqtt3/Mqtt3ReconnectorView.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.lifecycle.mqtt3;
-
-import com.hivemq.client.internal.mqtt.MqttClientTransportConfigImpl;
-import com.hivemq.client.internal.mqtt.MqttClientTransportConfigImplBuilder;
-import com.hivemq.client.internal.mqtt.lifecycle.MqttClientReconnector;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.mqtt.MqttClientTransportConfig;
-import com.hivemq.client.mqtt.mqtt3.lifecycle.Mqtt3ClientReconnector;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
+package com.hivemq.client2.internal.mqtt.lifecycle.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.MqttTransportConfigImpl;
+import com.hivemq.client2.internal.mqtt.MqttTransportConfigImplBuilder;
+import com.hivemq.client2.internal.mqtt.lifecycle.MqttReconnector;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.mqtt.MqttTransportConfig;
+import com.hivemq.client2.mqtt.mqtt3.lifecycle.Mqtt3Reconnector;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -35,22 +35,22 @@
 /**
  * @author Silvio Giebl
  */
-public class Mqtt3ClientReconnectorView implements Mqtt3ClientReconnector {
+public class Mqtt3ReconnectorView implements Mqtt3Reconnector {
 
-    private final @NotNull MqttClientReconnector delegate;
+    private final @NotNull MqttReconnector delegate;
 
-    Mqtt3ClientReconnectorView(final @NotNull MqttClientReconnector delegate) {
+    Mqtt3ReconnectorView(final @NotNull MqttReconnector delegate) {
         this.delegate = delegate;
     }
 
     @Override
-    public @NotNull Mqtt3ClientReconnectorView reconnect(final boolean reconnect) {
+    public @NotNull Mqtt3ReconnectorView reconnect(final boolean reconnect) {
         delegate.reconnect(reconnect);
         return this;
     }
 
     @Override
-    public @NotNull <T> Mqtt3ClientReconnectorView reconnectWhen(
+    public @NotNull <T> Mqtt3ReconnectorView reconnectWhen(
             final @Nullable CompletableFuture<T> future,
             final @Nullable BiConsumer<? super T, ? super Throwable> callback) {
 
@@ -64,7 +64,7 @@ public boolean isReconnect() {
     }
 
     @Override
-    public @NotNull Mqtt3ClientReconnectorView resubscribeIfSessionExpired(final boolean resubscribe) {
+    public @NotNull Mqtt3ReconnectorView resubscribeIfSessionExpired(final boolean resubscribe) {
         delegate.resubscribeIfSessionExpired(resubscribe);
         return this;
     }
@@ -75,7 +75,7 @@ public boolean isResubscribeIfSessionExpired() {
     }
 
     @Override
-    public @NotNull Mqtt3ClientReconnectorView republishIfSessionExpired(final boolean republish) {
+    public @NotNull Mqtt3ReconnectorView republishIfSessionExpired(final boolean republish) {
         delegate.republishIfSessionExpired(republish);
         return this;
     }
@@ -91,7 +91,7 @@ public int getAttempts() {
     }
 
     @Override
-    public @NotNull Mqtt3ClientReconnectorView delay(final long delay, final @Nullable TimeUnit timeUnit) {
+    public @NotNull Mqtt3ReconnectorView delay(final long delay, final @Nullable TimeUnit timeUnit) {
         delegate.delay(delay, timeUnit);
         return this;
     }
@@ -102,31 +102,29 @@ public long getDelay(final @NotNull TimeUnit timeUnit) {
     }
 
     @Override
-    public @NotNull Mqtt3ClientReconnectorView transportConfig(
-            final @Nullable MqttClientTransportConfig transportConfig) {
-
+    public @NotNull Mqtt3ReconnectorView transportConfig(final @Nullable MqttTransportConfig transportConfig) {
         delegate.transportConfig(transportConfig);
         return this;
     }
 
     @Override
-    public MqttClientTransportConfigImplBuilder.@NotNull Nested<Mqtt3ClientReconnectorView> transportConfig() {
-        return new MqttClientTransportConfigImplBuilder.Nested<>(getTransportConfig(), this::transportConfig);
+    public MqttTransportConfigImplBuilder.@NotNull Nested<Mqtt3ReconnectorView> transportConfigWith() {
+        return new MqttTransportConfigImplBuilder.Nested<>(getTransportConfig(), this::transportConfig);
     }
 
     @Override
-    public @NotNull MqttClientTransportConfigImpl getTransportConfig() {
+    public @NotNull MqttTransportConfigImpl getTransportConfig() {
         return delegate.getTransportConfig();
     }
 
     @Override
-    public @NotNull Mqtt3ClientReconnectorView connect(final @Nullable Mqtt3Connect connect) {
+    public @NotNull Mqtt3ReconnectorView connect(final @Nullable Mqtt3Connect connect) {
         delegate.connect(MqttChecks.connect(connect));
         return this;
     }
 
     @Override
-    public Mqtt3ConnectViewBuilder.@NotNull Nested<Mqtt3ClientReconnectorView> connectWith() {
+    public Mqtt3ConnectViewBuilder.@NotNull Nested<Mqtt3ReconnectorView> connectWith() {
         return new Mqtt3ConnectViewBuilder.Nested<>(getConnect(), this::connect);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/MqttMessage.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttMessage.java
similarity index 84%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/MqttMessage.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/MqttMessage.java
index 373e7acc5..7b498242c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/MqttMessage.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttMessage.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message;
+package com.hivemq.client2.internal.mqtt.message;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/MqttMessageWithUserProperties.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttMessageWithUserProperties.java
similarity index 91%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/MqttMessageWithUserProperties.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/MqttMessageWithUserProperties.java
index 897a88879..4a2150619 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/MqttMessageWithUserProperties.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttMessageWithUserProperties.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.util.StringUtil;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
+package com.hivemq.client2.internal.mqtt.message;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.util.StringUtil;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -165,11 +165,11 @@ public abstract static class WithCodesAndId<R extends Mqtt5ReasonCode> extends W
                 implements MqttMessage.WithId {
 
             private final int packetIdentifier;
-            private final @NotNull ImmutableList<@NotNull R> reasonCodes;
+            private final @NotNull ImmutableList<R> reasonCodes;
 
             protected WithCodesAndId(
                     final int packetIdentifier,
-                    final @NotNull ImmutableList<@NotNull R> reasonCodes,
+                    final @NotNull ImmutableList<R> reasonCodes,
                     final @Nullable MqttUtf8StringImpl reasonString,
                     final @NotNull MqttUserPropertiesImpl userProperties) {
 
@@ -183,7 +183,7 @@ public int getPacketIdentifier() {
                 return packetIdentifier;
             }
 
-            public @NotNull ImmutableList<@NotNull R> getReasonCodes() {
+            public @NotNull ImmutableList<R> getReasonCodes() {
                 return reasonCodes;
             }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/MqttProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttProperty.java
similarity index 97%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/MqttProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/MqttProperty.java
index dc8cbf3ba..21656b89a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/MqttProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttProperty.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message;
+package com.hivemq.client2.internal.mqtt.message;
 
 /**
  * All possible MQTT properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttReasonCodes.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttReasonCodes.java
new file mode 100644
index 000000000..958915e8f
--- /dev/null
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttReasonCodes.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2018-present HiveMQ and the HiveMQ Community
+ *
+ * Licensed 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
+ *
+ *     http://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 com.hivemq.client2.internal.mqtt.message;
+
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * MQTT Reason Codes according to the MQTT 5 specification.
+ *
+ * @author Silvio Giebl
+ */
+public class MqttReasonCodes {
+
+    public static final int SUCCESS = 0x00;
+    public static final int GRANTED_QOS_1 = 0x01;
+    public static final int GRANTED_QOS_2 = 0x02;
+    public static final int DISCONNECT_WITH_WILL_MESSAGE = 0x04;
+    public static final int NO_MATCHING_SUBSCRIBERS = 0x10;
+    public static final int NO_SUBSCRIPTIONS_EXISTED = 0x11;
+    public static final int CONTINUE_AUTHENTICATION = 0x18;
+    public static final int REAUTHENTICATE = 0x19;
+    public static final int UNSPECIFIED_ERROR = 0x80;
+    public static final int MALFORMED_PACKET = 0x81;
+    public static final int PROTOCOL_ERROR = 0x82;
+    public static final int IMPLEMENTATION_SPECIFIC_ERROR = 0x83;
+    public static final int UNSUPPORTED_PROTOCOL_VERSION = 0x84;
+    public static final int CLIENT_IDENTIFIER_NOT_VALID = 0x85;
+    public static final int BAD_USER_NAME_OR_PASSWORD = 0x86;
+    public static final int NOT_AUTHORIZED = 0x87;
+    public static final int SERVER_UNAVAILABLE = 0x88;
+    public static final int SERVER_BUSY = 0x89;
+    public static final int BANNED = 0x8A;
+    public static final int SERVER_SHUTTING_DOWN = 0x8B;
+    public static final int BAD_AUTHENTICATION_METHOD = 0x8C;
+    public static final int KEEP_ALIVE_TIMEOUT = 0x8D;
+    public static final int SESSION_TAKEN_OVER = 0x8E;
+    public static final int TOPIC_FILTER_INVALID = 0x8F;
+    public static final int TOPIC_NAME_INVALID = 0x90;
+    public static final int PACKET_IDENTIFIER_IN_USE = 0x91;
+    public static final int PACKET_IDENTIFIER_NOT_FOUND = 0x92;
+    public static final int RECEIVE_MAXIMUM_EXCEEDED = 0x93;
+    public static final int TOPIC_ALIAS_INVALID = 0x94;
+    public static final int PACKET_TOO_LARGE = 0x95;
+    public static final int MESSAGE_RATE_TOO_HIGH = 0x96;
+    public static final int QUOTA_EXCEEDED = 0x97;
+    public static final int ADMINISTRATIVE_ACTION = 0x98;
+    public static final int PAYLOAD_FORMAT_INVALID = 0x99;
+    public static final int RETAIN_NOT_SUPPORTED = 0x9A;
+    public static final int QOS_NOT_SUPPORTED = 0x9B;
+    public static final int USE_ANOTHER_SERVER = 0x9C;
+    public static final int SERVER_MOVED = 0x9D;
+    public static final int SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 0x9E;
+    public static final int CONNECTION_RATE_EXCEEDED = 0x9F;
+    public static final int MAXIMUM_CONNECT_TIME = 0xA0;
+    public static final int SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 0xA1;
+    public static final int WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 0xA2;
+
+    public static boolean allErrors(final @NotNull ImmutableList<? extends Mqtt5ReasonCode> reasonCodes) {
+        //noinspection ForLoopReplaceableByForEach
+        for (int i = 0; i < reasonCodes.size(); i++) {
+            if (!reasonCodes.get(i).isError()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private MqttReasonCodes() {}
+}
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/MqttStatefulMessage.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttStatefulMessage.java
similarity index 93%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/MqttStatefulMessage.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/MqttStatefulMessage.java
index 2c50ff506..a52332453 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/MqttStatefulMessage.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/MqttStatefulMessage.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message;
+package com.hivemq.client2.internal.mqtt.message;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuth.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuth.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuth.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuth.java
index 7d7a44cad..8983d708a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuth.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuth.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth;
+package com.hivemq.client2.internal.mqtt.message.auth;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.internal.util.ByteBufferUtil;
-import com.hivemq.client.internal.util.StringUtil;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5Auth;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.internal.util.ByteBufferUtil;
+import com.hivemq.client2.internal.util.StringUtil;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5Auth;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.nio.ByteBuffer;
 import java.util.Objects;
@@ -34,7 +34,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttAuth extends MqttMessageWithUserProperties.WithReason.WithCode<Mqtt5AuthReasonCode>
         implements Mqtt5Auth {
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuthBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuthBuilder.java
similarity index 80%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuthBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuthBuilder.java
index 9294f60fa..8d5061c1c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuthBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuthBuilder.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth;
+package com.hivemq.client2.internal.mqtt.message.auth;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -79,7 +79,7 @@ public MqttAuthBuilder(final @NotNull Mqtt5AuthReasonCode reasonCode, final @Not
     }
 
     @Override
-    public MqttUserPropertiesImplBuilder.@NotNull Nested<MqttAuthBuilder> userProperties() {
+    public MqttUserPropertiesImplBuilder.@NotNull Nested<MqttAuthBuilder> userPropertiesWith() {
         return new MqttUserPropertiesImplBuilder.Nested<>(userProperties, this::userProperties);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuthProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuthProperty.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuthProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuthProperty.java
index 8e7243954..e8c74354d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuthProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuthProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth;
+package com.hivemq.client2.internal.mqtt.message.auth;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT AUTH properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttEnhancedAuth.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttEnhancedAuth.java
similarity index 87%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttEnhancedAuth.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttEnhancedAuth.java
index a5bf5ad82..21f94aa47 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttEnhancedAuth.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttEnhancedAuth.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth;
+package com.hivemq.client2.internal.mqtt.message.auth;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.util.ByteBufferUtil;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuth;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.util.ByteBufferUtil;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuth;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.nio.ByteBuffer;
 import java.util.Objects;
@@ -30,7 +30,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttEnhancedAuth implements Mqtt5EnhancedAuth {
 
     private final @NotNull MqttUtf8StringImpl method;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttEnhancedAuthBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttEnhancedAuthBuilder.java
similarity index 83%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttEnhancedAuthBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttEnhancedAuthBuilder.java
index f842235e0..b1b4701d9 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttEnhancedAuthBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttEnhancedAuthBuilder.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth;
+package com.hivemq.client2.internal.mqtt.message.auth;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuthBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuthBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttSimpleAuth.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttSimpleAuth.java
similarity index 87%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttSimpleAuth.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttSimpleAuth.java
index 3a2f46d1c..d9e955728 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttSimpleAuth.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttSimpleAuth.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth;
+package com.hivemq.client2.internal.mqtt.message.auth;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.util.ByteBufferUtil;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.util.ByteBufferUtil;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.nio.ByteBuffer;
 import java.util.Objects;
@@ -31,7 +31,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttSimpleAuth implements Mqtt5SimpleAuth {
 
     private final @Nullable MqttUtf8StringImpl username;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttSimpleAuthBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttSimpleAuthBuilder.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttSimpleAuthBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttSimpleAuthBuilder.java
index f75f3984a..aa2e8346d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/MqttSimpleAuthBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/MqttSimpleAuthBuilder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth;
+package com.hivemq.client2.internal.mqtt.message.auth;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuthBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuthBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthView.java
similarity index 85%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthView.java
index 2b13c3b6c..1a14806df 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthView.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
+package com.hivemq.client2.internal.mqtt.message.auth.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.nio.ByteBuffer;
 import java.util.Optional;
@@ -31,7 +31,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3SimpleAuthView implements Mqtt3SimpleAuth {
 
     private static @NotNull MqttSimpleAuth delegate(
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewBuilder.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewBuilder.java
index 208858663..921cb43b8 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewBuilder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.auth.mqtt3;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuthBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuthBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAck.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAck.java
similarity index 81%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAck.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAck.java
index 582e38938..1caf8c551 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAck.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAck.java
@@ -14,21 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect.connack;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttClientIdentifierImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.internal.util.StringUtil;
-import com.hivemq.client.mqtt.datatypes.MqttClientIdentifier;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuth;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckReasonCode;
+package com.hivemq.client2.internal.mqtt.message.connect;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttClientIdentifierImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.internal.util.StringUtil;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttClientIdentifier;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.Objects;
 import java.util.Optional;
@@ -38,7 +40,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttConnAck extends MqttMessageWithUserProperties.WithReason.WithCode<Mqtt5ConnAckReasonCode>
         implements Mqtt5ConnAck {
 
@@ -46,8 +48,8 @@ public class MqttConnAck extends MqttMessageWithUserProperties.WithReason.WithCo
     public static final int KEEP_ALIVE_FROM_CONNECT = -1;
 
     private final boolean sessionPresent;
-    private final long sessionExpiryInterval;
-    private final int serverKeepAlive;
+    private final @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval;
+    private final @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int serverKeepAlive;
     private final @Nullable MqttClientIdentifierImpl assignedClientIdentifier;
     private final @Nullable Mqtt5EnhancedAuth enhancedAuth;
     private final @NotNull MqttConnAckRestrictions restrictions;
@@ -57,8 +59,8 @@ public class MqttConnAck extends MqttMessageWithUserProperties.WithReason.WithCo
     public MqttConnAck(
             final @NotNull Mqtt5ConnAckReasonCode reasonCode,
             final boolean sessionPresent,
-            final long sessionExpiryInterval,
-            final int serverKeepAlive,
+            final @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval,
+            final @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int serverKeepAlive,
             final @Nullable MqttClientIdentifierImpl assignedClientIdentifier,
             final @Nullable Mqtt5EnhancedAuth enhancedAuth,
             final @NotNull MqttConnAckRestrictions restrictions,
@@ -89,7 +91,7 @@ public boolean isSessionPresent() {
                 OptionalLong.of(sessionExpiryInterval);
     }
 
-    public long getRawSessionExpiryInterval() {
+    public @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long getRawSessionExpiryInterval() {
         return sessionExpiryInterval;
     }
 
@@ -98,7 +100,7 @@ public long getRawSessionExpiryInterval() {
         return (serverKeepAlive == KEEP_ALIVE_FROM_CONNECT) ? OptionalInt.empty() : OptionalInt.of(serverKeepAlive);
     }
 
-    public int getRawServerKeepAlive() {
+    public @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getRawServerKeepAlive() {
         return serverKeepAlive;
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckProperty.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckProperty.java
index 6d734ca6e..05e58a1d1 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect.connack;
+package com.hivemq.client2.internal.mqtt.message.connect;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT CONNACK properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckRestrictions.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckRestrictions.java
similarity index 78%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckRestrictions.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckRestrictions.java
index 6489af4f9..963269d56 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckRestrictions.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckRestrictions.java
@@ -14,18 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect.connack;
+package com.hivemq.client2.internal.mqtt.message.connect;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttConnAckRestrictions implements Mqtt5ConnAckRestrictions {
 
     public static final @NotNull MqttConnAckRestrictions DEFAULT =
@@ -34,9 +37,9 @@ public class MqttConnAckRestrictions implements Mqtt5ConnAckRestrictions {
                     DEFAULT_WILDCARD_SUBSCRIPTION_AVAILABLE, DEFAULT_SHARED_SUBSCRIPTION_AVAILABLE,
                     DEFAULT_SUBSCRIPTION_IDENTIFIERS_AVAILABLE);
 
-    private final int receiveMaximum;
-    private final int maximumPacketSize;
-    private final int topicAliasMaximum;
+    private final @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int receiveMaximum;
+    private final @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int maximumPacketSize;
+    private final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int topicAliasMaximum;
     private final @NotNull MqttQos maximumQos;
     private final boolean retainAvailable;
     private final boolean wildcardSubscriptionAvailable;
@@ -44,9 +47,9 @@ public class MqttConnAckRestrictions implements Mqtt5ConnAckRestrictions {
     private final boolean subscriptionIdentifiersAvailable;
 
     public MqttConnAckRestrictions(
-            final int receiveMaximum,
-            final int maximumPacketSize,
-            final int topicAliasMaximum,
+            final @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int receiveMaximum,
+            final @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int maximumPacketSize,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int topicAliasMaximum,
             final @NotNull MqttQos maximumQos,
             final boolean retainAvailable,
             final boolean wildcardSubscriptionAvailable,
@@ -64,17 +67,17 @@ public MqttConnAckRestrictions(
     }
 
     @Override
-    public int getReceiveMaximum() {
+    public @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getReceiveMaximum() {
         return receiveMaximum;
     }
 
     @Override
-    public int getMaximumPacketSize() {
+    public @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int getMaximumPacketSize() {
         return maximumPacketSize;
     }
 
     @Override
-    public int getTopicAliasMaximum() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getTopicAliasMaximum() {
         return topicAliasMaximum;
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnect.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnect.java
similarity index 80%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnect.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnect.java
index 1933a069b..72fb031c2 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnect.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnect.java
@@ -14,23 +14,25 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.datatypes.MqttClientIdentifierImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.internal.mqtt.message.auth.MqttEnhancedAuth;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.util.StringUtil;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
+package com.hivemq.client2.internal.mqtt.message.connect;
+
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttClientIdentifierImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttEnhancedAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.util.StringUtil;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.Objects;
 import java.util.Optional;
@@ -38,25 +40,25 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttConnect extends MqttMessageWithUserProperties implements Mqtt5Connect {
 
     public static final @NotNull MqttConnect DEFAULT =
             new MqttConnect(DEFAULT_KEEP_ALIVE, DEFAULT_CLEAN_START, DEFAULT_SESSION_EXPIRY_INTERVAL,
                     MqttConnectRestrictions.DEFAULT, null, null, null, MqttUserPropertiesImpl.NO_USER_PROPERTIES);
 
-    private final int keepAlive;
+    private final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int keepAlive;
     private final boolean cleanStart;
-    private final long sessionExpiryInterval;
+    private final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval;
     private final @NotNull MqttConnectRestrictions restrictions;
     private final @Nullable MqttSimpleAuth simpleAuth;
     private final @Nullable Mqtt5EnhancedAuthMechanism enhancedAuthMechanism;
     private final @Nullable MqttWillPublish willPublish;
 
     public MqttConnect(
-            final int keepAlive,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int keepAlive,
             final boolean cleanStart,
-            final long sessionExpiryInterval,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval,
             final @NotNull MqttConnectRestrictions restrictions,
             final @Nullable MqttSimpleAuth simpleAuth,
             final @Nullable Mqtt5EnhancedAuthMechanism enhancedAuthMechanism,
@@ -74,7 +76,7 @@ public MqttConnect(
     }
 
     @Override
-    public int getKeepAlive() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getKeepAlive() {
         return keepAlive;
     }
 
@@ -84,7 +86,7 @@ public boolean isCleanStart() {
     }
 
     @Override
-    public long getSessionExpiryInterval() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long getSessionExpiryInterval() {
         return sessionExpiryInterval;
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectBuilder.java
similarity index 79%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectBuilder.java
index 884c9b242..080dcc6a8 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectBuilder.java
@@ -14,25 +14,27 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuthBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
+package com.hivemq.client2.internal.mqtt.message.connect;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuthBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.util.function.Function;
 
@@ -41,9 +43,11 @@
  */
 public abstract class MqttConnectBuilder<B extends MqttConnectBuilder<B>> {
 
-    private int keepAlive = MqttConnect.DEFAULT_KEEP_ALIVE;
+    private @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int keepAlive =
+            MqttConnect.DEFAULT_KEEP_ALIVE;
     private boolean cleanStart = MqttConnect.DEFAULT_CLEAN_START;
-    private long sessionExpiryInterval = MqttConnect.DEFAULT_SESSION_EXPIRY_INTERVAL;
+    private @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval =
+            MqttConnect.DEFAULT_SESSION_EXPIRY_INTERVAL;
     private @NotNull MqttConnectRestrictions restrictions = MqttConnectRestrictions.DEFAULT;
     private @Nullable MqttSimpleAuth simpleAuth;
     private @Nullable Mqtt5EnhancedAuthMechanism enhancedAuthMechanism;
@@ -95,7 +99,7 @@ public abstract class MqttConnectBuilder<B extends MqttConnectBuilder<B>> {
         return self();
     }
 
-    public MqttConnectRestrictionsBuilder.@NotNull Nested<B> restrictions() {
+    public MqttConnectRestrictionsBuilder.@NotNull Nested<B> restrictionsWith() {
         return new MqttConnectRestrictionsBuilder.Nested<>(restrictions, this::restrictions);
     }
 
@@ -104,7 +108,7 @@ public abstract class MqttConnectBuilder<B extends MqttConnectBuilder<B>> {
         return self();
     }
 
-    public MqttSimpleAuthBuilder.@NotNull Nested<B> simpleAuth() {
+    public MqttSimpleAuthBuilder.@NotNull Nested<B> simpleAuthWith() {
         return new MqttSimpleAuthBuilder.Nested<>(this::simpleAuth);
     }
 
@@ -119,7 +123,7 @@ public abstract class MqttConnectBuilder<B extends MqttConnectBuilder<B>> {
         return self();
     }
 
-    public MqttPublishBuilder.@NotNull WillNested<B> willPublish() {
+    public MqttPublishBuilder.@NotNull WillNested<B> willPublishWith() {
         return new MqttPublishBuilder.WillNested<>(this::willPublish);
     }
 
@@ -128,7 +132,7 @@ public abstract class MqttConnectBuilder<B extends MqttConnectBuilder<B>> {
         return self();
     }
 
-    public MqttUserPropertiesImplBuilder.@NotNull Nested<B> userProperties() {
+    public MqttUserPropertiesImplBuilder.@NotNull Nested<B> userPropertiesWith() {
         return new MqttUserPropertiesImplBuilder.Nested<>(userProperties, this::userProperties);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectProperty.java
similarity index 93%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectProperty.java
index ab7af390a..37a221c2c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect;
+package com.hivemq.client2.internal.mqtt.message.connect;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT CONNECT properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectRestrictions.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectRestrictions.java
similarity index 66%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectRestrictions.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectRestrictions.java
index 31f9000bd..9db802f7b 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectRestrictions.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectRestrictions.java
@@ -14,17 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect;
+package com.hivemq.client2.internal.mqtt.message.connect;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttConnectRestrictions implements Mqtt5ConnectRestrictions {
 
     public static final @NotNull MqttConnectRestrictions DEFAULT =
@@ -32,22 +35,22 @@ public class MqttConnectRestrictions implements Mqtt5ConnectRestrictions {
                     DEFAULT_SEND_MAXIMUM_PACKET_SIZE, DEFAULT_TOPIC_ALIAS_MAXIMUM, DEFAULT_SEND_TOPIC_ALIAS_MAXIMUM,
                     DEFAULT_REQUEST_PROBLEM_INFORMATION, DEFAULT_REQUEST_RESPONSE_INFORMATION);
 
-    private final int receiveMaximum;
-    private final int sendMaximum;
-    private final int maximumPacketSize;
-    private final int sendMaximumPacketSize;
-    private final int topicAliasMaximum;
-    private final int sendTopicAliasMaximum;
+    private final @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int receiveMaximum;
+    private final @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int sendMaximum;
+    private final @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int maximumPacketSize;
+    private final @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int sendMaximumPacketSize;
+    private final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int topicAliasMaximum;
+    private final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int sendTopicAliasMaximum;
     private final boolean requestProblemInformation;
     private final boolean requestResponseInformation;
 
     public MqttConnectRestrictions(
-            final int receiveMaximum,
-            final int sendMaximum,
-            final int maximumPacketSize,
-            final int sendMaximumPacketSize,
-            final int topicAliasMaximum,
-            final int sendTopicAliasMaximum,
+            final @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int receiveMaximum,
+            final @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int sendMaximum,
+            final @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int maximumPacketSize,
+            final @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int sendMaximumPacketSize,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int topicAliasMaximum,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int sendTopicAliasMaximum,
             final boolean requestProblemInformation,
             final boolean requestResponseInformation) {
 
@@ -62,32 +65,32 @@ public MqttConnectRestrictions(
     }
 
     @Override
-    public int getReceiveMaximum() {
+    public @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getReceiveMaximum() {
         return receiveMaximum;
     }
 
     @Override
-    public int getSendMaximum() {
+    public @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getSendMaximum() {
         return sendMaximum;
     }
 
     @Override
-    public int getMaximumPacketSize() {
+    public @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int getMaximumPacketSize() {
         return maximumPacketSize;
     }
 
     @Override
-    public int getSendMaximumPacketSize() {
+    public @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int getSendMaximumPacketSize() {
         return sendMaximumPacketSize;
     }
 
     @Override
-    public int getTopicAliasMaximum() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getTopicAliasMaximum() {
         return topicAliasMaximum;
     }
 
     @Override
-    public int getSendTopicAliasMaximum() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getSendTopicAliasMaximum() {
         return sendTopicAliasMaximum;
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectRestrictionsBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectRestrictionsBuilder.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectRestrictionsBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectRestrictionsBuilder.java
index be9e533af..0b67f84ed 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectRestrictionsBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectRestrictionsBuilder.java
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect;
+package com.hivemq.client2.internal.mqtt.message.connect;
 
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictionsBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictionsBuilder;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.util.function.Function;
 
@@ -28,12 +31,18 @@
  */
 public abstract class MqttConnectRestrictionsBuilder<B extends MqttConnectRestrictionsBuilder<B>> {
 
-    private int receiveMaximum = MqttConnectRestrictions.DEFAULT_RECEIVE_MAXIMUM;
-    private int sendMaximum = MqttConnectRestrictions.DEFAULT_SEND_MAXIMUM;
-    private int maximumPacketSize = MqttConnectRestrictions.DEFAULT_MAXIMUM_PACKET_SIZE;
-    private int sendMaximumPacketSize = MqttConnectRestrictions.DEFAULT_SEND_MAXIMUM_PACKET_SIZE;
-    private int topicAliasMaximum = MqttConnectRestrictions.DEFAULT_TOPIC_ALIAS_MAXIMUM;
-    private int sendTopicAliasMaximum = MqttConnectRestrictions.DEFAULT_SEND_TOPIC_ALIAS_MAXIMUM;
+    private @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int receiveMaximum =
+            MqttConnectRestrictions.DEFAULT_RECEIVE_MAXIMUM;
+    private @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int sendMaximum =
+            MqttConnectRestrictions.DEFAULT_SEND_MAXIMUM;
+    private @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int maximumPacketSize =
+            MqttConnectRestrictions.DEFAULT_MAXIMUM_PACKET_SIZE;
+    private @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int sendMaximumPacketSize =
+            MqttConnectRestrictions.DEFAULT_SEND_MAXIMUM_PACKET_SIZE;
+    private @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int topicAliasMaximum =
+            MqttConnectRestrictions.DEFAULT_TOPIC_ALIAS_MAXIMUM;
+    private @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int sendTopicAliasMaximum =
+            MqttConnectRestrictions.DEFAULT_SEND_TOPIC_ALIAS_MAXIMUM;
     private boolean requestProblemInformation = MqttConnectRestrictions.DEFAULT_REQUEST_PROBLEM_INFORMATION;
     private boolean requestResponseInformation = MqttConnectRestrictions.DEFAULT_REQUEST_RESPONSE_INFORMATION;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttStatefulConnect.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttStatefulConnect.java
similarity index 84%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttStatefulConnect.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttStatefulConnect.java
index 9dd27a79e..dd83617e2 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/MqttStatefulConnect.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/MqttStatefulConnect.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect;
+package com.hivemq.client2.internal.mqtt.message.connect;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttClientIdentifierImpl;
-import com.hivemq.client.internal.mqtt.message.MqttStatefulMessage;
-import com.hivemq.client.internal.mqtt.message.auth.MqttEnhancedAuth;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttClientIdentifierImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttStatefulMessage;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttEnhancedAuth;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttStatefulConnect extends MqttStatefulMessage<MqttConnect> {
 
     private final @NotNull MqttClientIdentifierImpl clientIdentifier;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/mqtt3/Mqtt3ConnAckView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnAckView.java
similarity index 84%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/mqtt3/Mqtt3ConnAckView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnAckView.java
index 161315ec9..123bb7df0 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/connack/mqtt3/Mqtt3ConnAckView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnAckView.java
@@ -14,26 +14,26 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect.connack.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAckRestrictions;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAckReturnCode;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckReasonCode;
-import io.reactivex.functions.Function;
+package com.hivemq.client2.internal.mqtt.message.connect.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAckRestrictions;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAckReturnCode;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckReasonCode;
+import io.reactivex.rxjava3.functions.Function;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
-import static com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAckReturnCode.*;
+import static com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAckReturnCode.*;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3ConnAckView implements Mqtt3ConnAck {
 
     public static final @NotNull Function<Mqtt5ConnAck, Mqtt3ConnAck> MAPPER = Mqtt3ConnAckView::of;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectView.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectView.java
index 12bc13374..eb2348a2b 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectView.java
@@ -14,34 +14,36 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthView;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictions;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
+package com.hivemq.client2.internal.mqtt.message.connect.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthView;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectRestrictions;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.Optional;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3ConnectView implements Mqtt3Connect {
 
     public static final @NotNull Mqtt3ConnectView DEFAULT = of(DEFAULT_KEEP_ALIVE, DEFAULT_CLEAN_SESSION, null, null);
 
     private static @NotNull MqttConnect delegate(
-            final int keepAlive,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int keepAlive,
             final boolean cleanSession,
             final @Nullable MqttSimpleAuth simpleAuth,
             final @Nullable MqttWillPublish willPublish) {
@@ -52,7 +54,7 @@ public class Mqtt3ConnectView implements Mqtt3Connect {
     }
 
     static @NotNull Mqtt3ConnectView of(
-            final int keepAlive,
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int keepAlive,
             final boolean cleanSession,
             final @Nullable MqttSimpleAuth simpleAuth,
             final @Nullable MqttWillPublish willPublish) {
@@ -71,7 +73,7 @@ private Mqtt3ConnectView(final @NotNull MqttConnect delegate) {
     }
 
     @Override
-    public int getKeepAlive() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getKeepAlive() {
         return delegate.getKeepAlive();
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewBuilder.java
similarity index 80%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewBuilder.java
index 81325a6c2..715c23474 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewBuilder.java
@@ -14,21 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect.mqtt3;
-
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthView;
-import com.hivemq.client.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthViewBuilder;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishViewBuilder;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
+package com.hivemq.client2.internal.mqtt.message.connect.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthView;
+import com.hivemq.client2.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishViewBuilder;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.util.function.Function;
 
@@ -37,7 +39,8 @@
  */
 public abstract class Mqtt3ConnectViewBuilder<B extends Mqtt3ConnectViewBuilder<B>> {
 
-    private int keepAliveSeconds = Mqtt3ConnectView.DEFAULT_KEEP_ALIVE;
+    private @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int keepAliveSeconds =
+            Mqtt3ConnectView.DEFAULT_KEEP_ALIVE;
     private boolean cleanSession = Mqtt3ConnectView.DEFAULT_CLEAN_SESSION;
     private @Nullable MqttSimpleAuth simpleAuth;
     private @Nullable MqttWillPublish willPublish;
@@ -75,7 +78,7 @@ public abstract class Mqtt3ConnectViewBuilder<B extends Mqtt3ConnectViewBuilder<
         return self();
     }
 
-    public Mqtt3SimpleAuthViewBuilder.@NotNull Nested<B> simpleAuth() {
+    public Mqtt3SimpleAuthViewBuilder.@NotNull Nested<B> simpleAuthWith() {
         return new Mqtt3SimpleAuthViewBuilder.Nested<>(this::simpleAuth);
     }
 
@@ -85,7 +88,7 @@ public abstract class Mqtt3ConnectViewBuilder<B extends Mqtt3ConnectViewBuilder<
         return self();
     }
 
-    public Mqtt3PublishViewBuilder.@NotNull WillNested<B> willPublish() {
+    public Mqtt3PublishViewBuilder.@NotNull WillNested<B> willPublishWith() {
         return new Mqtt3PublishViewBuilder.WillNested<>(this::willPublish);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnect.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnect.java
similarity index 78%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnect.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnect.java
index 0805c82d0..977094ab2 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnect.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnect.java
@@ -14,18 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.disconnect;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.internal.util.StringUtil;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.message.disconnect;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.internal.util.StringUtil;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.Objects;
 import java.util.Optional;
@@ -34,7 +36,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttDisconnect extends MqttMessageWithUserProperties.WithReason.WithCode<Mqtt5DisconnectReasonCode>
         implements Mqtt5Disconnect {
 
@@ -43,12 +45,12 @@ public class MqttDisconnect extends MqttMessageWithUserProperties.WithReason.Wit
             new MqttDisconnect(DEFAULT_REASON_CODE, SESSION_EXPIRY_INTERVAL_FROM_CONNECT, null, null,
                     MqttUserPropertiesImpl.NO_USER_PROPERTIES);
 
-    private final long sessionExpiryInterval;
+    private final @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval;
     private final @Nullable MqttUtf8StringImpl serverReference;
 
     public MqttDisconnect(
             final @NotNull Mqtt5DisconnectReasonCode reasonCode,
-            final long sessionExpiryInterval,
+            final @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval,
             final @Nullable MqttUtf8StringImpl serverReference,
             final @Nullable MqttUtf8StringImpl reasonString,
             final @NotNull MqttUserPropertiesImpl userProperties) {
@@ -64,7 +66,7 @@ public MqttDisconnect(
                 OptionalLong.of(sessionExpiryInterval);
     }
 
-    public long getRawSessionExpiryInterval() {
+    public @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long getRawSessionExpiryInterval() {
         return sessionExpiryInterval;
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnectBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnectBuilder.java
similarity index 84%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnectBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnectBuilder.java
index 16beb24ac..fe4c9cf64 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnectBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnectBuilder.java
@@ -14,20 +14,22 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.disconnect;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.message.disconnect;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -38,7 +40,8 @@
 public abstract class MqttDisconnectBuilder<B extends MqttDisconnectBuilder<B>> {
 
     private @NotNull Mqtt5DisconnectReasonCode reasonCode = MqttDisconnect.DEFAULT_REASON_CODE;
-    private long sessionExpiryInterval = MqttDisconnect.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
+    private @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval =
+            MqttDisconnect.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
     private @Nullable MqttUtf8StringImpl serverReference;
     private @Nullable MqttUtf8StringImpl reasonString;
     private @NotNull MqttUserPropertiesImpl userProperties = MqttUserPropertiesImpl.NO_USER_PROPERTIES;
@@ -95,7 +98,7 @@ public abstract class MqttDisconnectBuilder<B extends MqttDisconnectBuilder<B>>
         return self();
     }
 
-    public MqttUserPropertiesImplBuilder.@NotNull Nested<B> userProperties() {
+    public MqttUserPropertiesImplBuilder.@NotNull Nested<B> userPropertiesWith() {
         return new MqttUserPropertiesImplBuilder.Nested<>(userProperties, this::userProperties);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnectProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnectProperty.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnectProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnectProperty.java
index 1f262e462..a06ab7629 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnectProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnectProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.disconnect;
+package com.hivemq.client2.internal.mqtt.message.disconnect;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT DISCONNECT properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/mqtt3/Mqtt3DisconnectView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/mqtt3/Mqtt3DisconnectView.java
similarity index 75%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/mqtt3/Mqtt3DisconnectView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/mqtt3/Mqtt3DisconnectView.java
index 30445d6d0..7f19b9c43 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/disconnect/mqtt3/Mqtt3DisconnectView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/disconnect/mqtt3/Mqtt3DisconnectView.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.disconnect.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt3.message.disconnect.Mqtt3Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.message.disconnect.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.disconnect.Mqtt3Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3DisconnectView implements Mqtt3Disconnect {
 
     public static final @NotNull MqttDisconnect DELEGATE =
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/ping/MqttPingReq.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/ping/MqttPingReq.java
similarity index 79%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/ping/MqttPingReq.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/ping/MqttPingReq.java
index a9cd0ebfe..bda63bc49 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/ping/MqttPingReq.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/ping/MqttPingReq.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.ping;
+package com.hivemq.client2.internal.mqtt.message.ping;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.message.MqttMessage;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.ping.Mqtt5PingReq;
+import com.hivemq.client2.internal.mqtt.message.MqttMessage;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.ping.Mqtt5PingReq;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttPingReq implements MqttMessage, Mqtt5PingReq {
 
     public static final @NotNull MqttPingReq INSTANCE = new MqttPingReq();
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/ping/MqttPingResp.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/ping/MqttPingResp.java
similarity index 79%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/ping/MqttPingResp.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/ping/MqttPingResp.java
index 8d0c3d6f4..1cc78956a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/ping/MqttPingResp.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/ping/MqttPingResp.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.ping;
+package com.hivemq.client2.internal.mqtt.message.ping;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.message.MqttMessage;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.ping.Mqtt5PingResp;
+import com.hivemq.client2.internal.mqtt.message.MqttMessage;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.ping.Mqtt5PingResp;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttPingResp implements MqttMessage, Mqtt5PingResp {
 
     public static final @NotNull MqttPingResp INSTANCE = new MqttPingResp();
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/ping/mqtt3/Mqtt3PingReqView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/ping/mqtt3/Mqtt3PingReqView.java
similarity index 83%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/ping/mqtt3/Mqtt3PingReqView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/ping/mqtt3/Mqtt3PingReqView.java
index 9d2f1fd0a..3446c897e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/ping/mqtt3/Mqtt3PingReqView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/ping/mqtt3/Mqtt3PingReqView.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.ping.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.ping.mqtt3;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt3.message.ping.Mqtt3PingReq;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.ping.Mqtt3PingReq;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3PingReqView implements Mqtt3PingReq {
 
     public static final @NotNull Mqtt3PingReqView INSTANCE = new Mqtt3PingReqView();
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/ping/mqtt3/Mqtt3PingRespView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/ping/mqtt3/Mqtt3PingRespView.java
similarity index 83%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/ping/mqtt3/Mqtt3PingRespView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/ping/mqtt3/Mqtt3PingRespView.java
index 7284eff1d..0e5b4e557 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/ping/mqtt3/Mqtt3PingRespView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/ping/mqtt3/Mqtt3PingRespView.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.ping.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.ping.mqtt3;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt3.message.ping.Mqtt3PingResp;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.ping.Mqtt3PingResp;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3PingRespView implements Mqtt3PingResp {
 
     public static final @NotNull Mqtt3PingRespView INSTANCE = new Mqtt3PingRespView();
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAck.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAck.java
similarity index 78%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAck.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAck.java
index 3c1e04c03..998c60b76 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAck.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAck.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.puback;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAck;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAckReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAckReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttPubAck extends MqttMessageWithUserProperties.WithReason.WithCode.WithId<Mqtt5PubAckReasonCode>
         implements Mqtt5PubAck {
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAckBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAckBuilder.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAckBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAckBuilder.java
index d30cb0d89..ef50835b5 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAckBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAckBuilder.java
@@ -14,18 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.puback;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAckBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAckReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAckBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAckReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -68,7 +67,7 @@ public MqttPubAckBuilder(final @NotNull MqttStatefulPublish publish) {
     }
 
     @Override
-    public MqttUserPropertiesImplBuilder.@NotNull Nested<MqttPubAckBuilder> userProperties() {
+    public MqttUserPropertiesImplBuilder.@NotNull Nested<MqttPubAckBuilder> userPropertiesWith() {
         return new MqttUserPropertiesImplBuilder.Nested<>(userProperties, this::userProperties);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAckProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAckProperty.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAckProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAckProperty.java
index 463058f49..12441536b 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAckProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAckProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.puback;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT PUBACK properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubComp.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubComp.java
similarity index 78%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubComp.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubComp.java
index 6caae0dd5..e7662933b 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubComp.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubComp.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubcomp;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubComp;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubComp;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttPubComp extends MqttMessageWithUserProperties.WithReason.WithCode.WithId<Mqtt5PubCompReasonCode>
         implements Mqtt5PubComp {
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubCompBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubCompBuilder.java
similarity index 77%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubCompBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubCompBuilder.java
index d61b528e3..2a25d90fa 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubCompBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubCompBuilder.java
@@ -14,17 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubcomp;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -66,7 +65,7 @@ public MqttPubCompBuilder(final @NotNull MqttPubRel pubRel) {
     }
 
     @Override
-    public MqttUserPropertiesImplBuilder.@NotNull Nested<MqttPubCompBuilder> userProperties() {
+    public MqttUserPropertiesImplBuilder.@NotNull Nested<MqttPubCompBuilder> userPropertiesWith() {
         return new MqttUserPropertiesImplBuilder.Nested<>(userProperties, this::userProperties);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubCompProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubCompProperty.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubCompProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubCompProperty.java
index 080018da4..cdc1f6dc0 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubCompProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubCompProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubcomp;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT PUBCOMP properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRec.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRec.java
similarity index 78%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRec.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRec.java
index 5bf73fa3f..3d1788adf 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRec.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRec.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubrec;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRec;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRec;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttPubRec extends MqttMessageWithUserProperties.WithReason.WithCode.WithId<Mqtt5PubRecReasonCode>
         implements Mqtt5PubRec {
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRecBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRecBuilder.java
similarity index 76%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRecBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRecBuilder.java
index d74e3565c..bb678ff18 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRecBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRecBuilder.java
@@ -14,18 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubrec;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -68,7 +67,7 @@ public MqttPubRecBuilder(final @NotNull MqttStatefulPublish publish) {
     }
 
     @Override
-    public MqttUserPropertiesImplBuilder.@NotNull Nested<MqttPubRecBuilder> userProperties() {
+    public MqttUserPropertiesImplBuilder.@NotNull Nested<MqttPubRecBuilder> userPropertiesWith() {
         return new MqttUserPropertiesImplBuilder.Nested<>(userProperties, this::userProperties);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRecProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRecProperty.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRecProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRecProperty.java
index c73445414..97234fa5a 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRecProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRecProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubrec;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT PUBREC properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRel.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRel.java
similarity index 78%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRel.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRel.java
index ba10053b4..d9907fd31 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRel.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRel.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubrel;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRel;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRel;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRelReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttPubRel extends MqttMessageWithUserProperties.WithReason.WithCode.WithId<Mqtt5PubRelReasonCode>
         implements Mqtt5PubRel {
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRelBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRelBuilder.java
similarity index 77%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRelBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRelBuilder.java
index 98d06c267..3656cbc5c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRelBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRelBuilder.java
@@ -14,17 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubrel;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRelBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRelReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -66,7 +65,7 @@ public MqttPubRelBuilder(final @NotNull MqttPubRec pubRec) {
     }
 
     @Override
-    public MqttUserPropertiesImplBuilder.@NotNull Nested<MqttPubRelBuilder> userProperties() {
+    public MqttUserPropertiesImplBuilder.@NotNull Nested<MqttPubRelBuilder> userPropertiesWith() {
         return new MqttUserPropertiesImplBuilder.Nested<>(userProperties, this::userProperties);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRelProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRelProperty.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRelProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRelProperty.java
index 828ad9be9..86a789b3d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRelProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRelProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubrel;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT PUBREL properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublish.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublish.java
similarity index 83%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublish.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublish.java
index 385079152..005cbcda6 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublish.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublish.java
@@ -14,47 +14,49 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.checkpoint.Confirmable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttTopicAliasMapping;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.internal.util.ByteBufferUtil;
-import com.hivemq.client.internal.util.StringUtil;
-import com.hivemq.client.internal.util.collections.ImmutableIntList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
+package com.hivemq.client2.internal.mqtt.message.publish;
+
+import com.hivemq.client2.internal.checkpoint.Confirmable;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.handler.publish.outgoing.MqttTopicAliasMapping;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.internal.util.ByteBufferUtil;
+import com.hivemq.client2.internal.util.StringUtil;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.internal.util.collections.ImmutableIntList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.nio.ByteBuffer;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.OptionalLong;
 
-import static com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish.DEFAULT_NO_SUBSCRIPTION_IDENTIFIERS;
-import static com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish.DEFAULT_NO_TOPIC_ALIAS;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish.DEFAULT_NO_SUBSCRIPTION_IDENTIFIERS;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish.DEFAULT_NO_TOPIC_ALIAS;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttPublish extends MqttMessageWithUserProperties implements Mqtt5Publish {
 
-    public static final long NO_MESSAGE_EXPIRY = Long.MAX_VALUE;
+    public static final long NO_MESSAGE_EXPIRY = -1;
 
     private final @NotNull MqttTopicImpl topic;
     private final @Nullable ByteBuffer payload;
     private final @NotNull MqttQos qos;
     private final boolean retain;
-    private final long messageExpiryInterval;
+    private final @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long messageExpiryInterval;
     private final @Nullable Mqtt5PayloadFormatIndicator payloadFormatIndicator;
     private final @Nullable MqttUtf8StringImpl contentType;
     private final @Nullable MqttTopicImpl responseTopic;
@@ -67,7 +69,7 @@ public MqttPublish(
             final @Nullable ByteBuffer payload,
             final @NotNull MqttQos qos,
             final boolean retain,
-            final long messageExpiryInterval,
+            final @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long messageExpiryInterval,
             final @Nullable Mqtt5PayloadFormatIndicator payloadFormatIndicator,
             final @Nullable MqttUtf8StringImpl contentType,
             final @Nullable MqttTopicImpl responseTopic,
@@ -123,7 +125,7 @@ public boolean isRetain() {
                 OptionalLong.of(messageExpiryInterval);
     }
 
-    public long getRawMessageExpiryInterval() {
+    public @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) long getRawMessageExpiryInterval() {
         return messageExpiryInterval;
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishBuilder.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishBuilder.java
index fe603468a..23e041bea 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishBuilder.java
@@ -14,21 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish;
-
-import com.hivemq.client.internal.mqtt.datatypes.*;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.ByteBufferUtil;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublishBuilder;
+package com.hivemq.client2.internal.mqtt.message.publish;
+
+import com.hivemq.client2.internal.mqtt.datatypes.*;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.ByteBufferUtil;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5WillPublishBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.nio.ByteBuffer;
 import java.util.function.Function;
@@ -89,7 +91,7 @@ public abstract class MqttPublishBuilder<B extends MqttPublishBuilder<B>> {
         return self();
     }
 
-    public MqttTopicImplBuilder.@NotNull Nested<B> topic() {
+    public MqttTopicImplBuilder.@NotNull Nested<B> topicWith() {
         return new MqttTopicImplBuilder.Nested<>(this::topic);
     }
 
@@ -138,7 +140,7 @@ public abstract class MqttPublishBuilder<B extends MqttPublishBuilder<B>> {
         return self();
     }
 
-    public MqttTopicImplBuilder.@NotNull Nested<B> responseTopic() {
+    public MqttTopicImplBuilder.@NotNull Nested<B> responseTopicWith() {
         return new MqttTopicImplBuilder.Nested<>(this::responseTopic);
     }
 
@@ -157,7 +159,7 @@ public abstract class MqttPublishBuilder<B extends MqttPublishBuilder<B>> {
         return self();
     }
 
-    public MqttUserPropertiesImplBuilder.@NotNull Nested<B> userProperties() {
+    public MqttUserPropertiesImplBuilder.@NotNull Nested<B> userPropertiesWith() {
         return new MqttUserPropertiesImplBuilder.Nested<>(userProperties, this::userProperties);
     }
 
@@ -244,7 +246,8 @@ public Send(final @NotNull Function<? super MqttPublish, P> parentConsumer) {
 
     private static abstract class WillBase<B extends WillBase<B>> extends MqttPublishBuilder<B> {
 
-        private long delayInterval = MqttWillPublish.DEFAULT_DELAY_INTERVAL;
+        private @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long delayInterval =
+                MqttWillPublish.DEFAULT_DELAY_INTERVAL;
 
         WillBase() {}
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishProperty.java
similarity index 92%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishProperty.java
index 3181f7ef7..6a583580c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT PUBLISH properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishResult.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishResult.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishResult.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishResult.java
index 86b387deb..a8f6e0eba 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishResult.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishResult.java
@@ -14,13 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttStatefulPublish.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttStatefulPublish.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttStatefulPublish.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttStatefulPublish.java
index 17c6ed990..fa17a4cb6 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttStatefulPublish.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttStatefulPublish.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.message.MqttStatefulMessage;
-import com.hivemq.client.internal.util.UnsignedDataTypes;
-import com.hivemq.client.internal.util.collections.ImmutableIntList;
+import com.hivemq.client2.internal.mqtt.message.MqttStatefulMessage;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.internal.util.collections.ImmutableIntList;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttStatefulPublish extends MqttStatefulMessage.WithId<MqttPublish> {
 
     public static final int NO_PACKET_IDENTIFIER_QOS_0 = -1;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttWillPublish.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttWillPublish.java
similarity index 72%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttWillPublish.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttWillPublish.java
index b767658dd..dcf878f2c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttWillPublish.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttWillPublish.java
@@ -14,40 +14,42 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
+package com.hivemq.client2.internal.mqtt.message.publish;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.nio.ByteBuffer;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttWillPublish extends MqttPublish implements Mqtt5WillPublish {
 
-    private final long delayInterval;
+    private final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long delayInterval;
 
     public MqttWillPublish(
             final @NotNull MqttTopicImpl topic,
             final @Nullable ByteBuffer payload,
             final @NotNull MqttQos qos,
             final boolean isRetain,
-            final long messageExpiryInterval,
+            final @Range(from = -1, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long messageExpiryInterval,
             final @Nullable Mqtt5PayloadFormatIndicator payloadFormatIndicator,
             final @Nullable MqttUtf8StringImpl contentType,
             final @Nullable MqttTopicImpl responseTopic,
             final @Nullable ByteBuffer correlationData,
             final @NotNull MqttUserPropertiesImpl userProperties,
-            final long delayInterval) {
+            final @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long delayInterval) {
 
         super(topic, payload, qos, isRetain, messageExpiryInterval, payloadFormatIndicator, contentType, responseTopic,
                 correlationData, userProperties, null);
@@ -55,7 +57,7 @@ public MqttWillPublish(
     }
 
     @Override
-    public long getDelayInterval() {
+    public @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long getDelayInterval() {
         return delayInterval;
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttWillPublishProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttWillPublishProperty.java
similarity index 92%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttWillPublishProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttWillPublishProperty.java
index 5b0a4047d..dcba584bb 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/MqttWillPublishProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/MqttWillPublishProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT Will Publish properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/mqtt3/Mqtt3PubAckView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubAckView.java
similarity index 74%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/mqtt3/Mqtt3PubAckView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubAckView.java
index 107829fcb..deb66fd38 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/puback/mqtt3/Mqtt3PubAckView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubAckView.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.puback.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt3.message.publish.puback.Mqtt3PubAck;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.message.publish.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAckReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3PubAckView implements Mqtt3PubAck {
 
     public static final @NotNull Mqtt3PubAckView INSTANCE = new Mqtt3PubAckView();
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/mqtt3/Mqtt3PubCompView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubCompView.java
similarity index 74%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/mqtt3/Mqtt3PubCompView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubCompView.java
index 90cc97b97..2a4d311b6 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/mqtt3/Mqtt3PubCompView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubCompView.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubcomp.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt3.message.publish.pubcomp.Mqtt3PubComp;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompReasonCode;
+package com.hivemq.client2.internal.mqtt.message.publish.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PubComp;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3PubCompView implements Mqtt3PubComp {
 
     public static final @NotNull Mqtt3PubCompView INSTANCE = new Mqtt3PubCompView();
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/mqtt3/Mqtt3PubRecView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubRecView.java
similarity index 74%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/mqtt3/Mqtt3PubRecView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubRecView.java
index 9c419db34..603a98fee 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/mqtt3/Mqtt3PubRecView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubRecView.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubrec.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt3.message.publish.pubrec.Mqtt3PubRec;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecReasonCode;
+package com.hivemq.client2.internal.mqtt.message.publish.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PubRec;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3PubRecView implements Mqtt3PubRec {
 
     public static final @NotNull Mqtt3PubRecView INSTANCE = new Mqtt3PubRecView();
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/mqtt3/Mqtt3PubRelView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubRelView.java
similarity index 74%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/mqtt3/Mqtt3PubRelView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubRelView.java
index 0ad2176ef..b3912d638 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/mqtt3/Mqtt3PubRelView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PubRelView.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubrel.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt3.message.publish.pubrel.Mqtt3PubRel;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelReasonCode;
+package com.hivemq.client2.internal.mqtt.message.publish.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PubRel;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRelReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3PubRelView implements Mqtt3PubRel {
 
     public static final @NotNull Mqtt3PubRelView INSTANCE = new Mqtt3PubRelView();
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultView.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultView.java
index 938ccaa22..e3cfdc76d 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultView.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.publish.mqtt3;
 
-import com.hivemq.client.internal.mqtt.exceptions.mqtt3.Mqtt3ExceptionFactory;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishResult;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import io.reactivex.functions.Function;
+import com.hivemq.client2.internal.mqtt.exceptions.mqtt3.Mqtt3ExceptionFactory;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishResult;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import io.reactivex.rxjava3.functions.Function;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishView.java
similarity index 84%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishView.java
index e5861a92a..b0f28b12f 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishView.java
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
-import io.reactivex.functions.Function;
+package com.hivemq.client2.internal.mqtt.message.publish.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
+import io.reactivex.rxjava3.functions.Function;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.nio.ByteBuffer;
 import java.util.Optional;
@@ -37,7 +37,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3PublishView implements Mqtt3Publish {
 
     public static final @NotNull Function<Mqtt5Publish, Mqtt3Publish> MAPPER = Mqtt3PublishView::of;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewBuilder.java
similarity index 81%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewBuilder.java
index ef68aa515..ccc02c4d3 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewBuilder.java
@@ -14,24 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.mqtt3;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImplBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.ByteBufferUtil;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3WillPublishBuilder;
+package com.hivemq.client2.internal.mqtt.message.publish.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImplBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.ByteBufferUtil;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3WillPublishBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.nio.ByteBuffer;
-import java.util.function.Consumer;
 import java.util.function.Function;
 
 /**
@@ -66,7 +65,7 @@ public abstract class Mqtt3PublishViewBuilder<B extends Mqtt3PublishViewBuilder<
         return self();
     }
 
-    public MqttTopicImplBuilder.@NotNull Nested<B> topic() {
+    public MqttTopicImplBuilder.@NotNull Nested<B> topicWith() {
         return new MqttTopicImplBuilder.Nested<>(this::topic);
     }
 
@@ -156,25 +155,6 @@ public Send(final @NotNull Function<? super Mqtt3PublishView, P> parentConsumer)
         }
     }
 
-    public static class SendVoid extends Base<SendVoid> implements Mqtt3PublishBuilder.SendVoid.Complete {
-
-        private final @NotNull Consumer<? super Mqtt3PublishView> parentConsumer;
-
-        public SendVoid(final @NotNull Consumer<? super Mqtt3PublishView> parentConsumer) {
-            this.parentConsumer = parentConsumer;
-        }
-
-        @Override
-        protected @NotNull SendVoid self() {
-            return this;
-        }
-
-        @Override
-        public void send() {
-            parentConsumer.accept(build());
-        }
-    }
-
     private static abstract class WillBase<B extends WillBase<B>> extends Mqtt3PublishViewBuilder<B> {
 
         WillBase() {}
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttStatefulSubscribe.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttStatefulSubscribe.java
similarity index 85%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttStatefulSubscribe.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttStatefulSubscribe.java
index 86228ef20..25e3773eb 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttStatefulSubscribe.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttStatefulSubscribe.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.message.MqttStatefulMessage;
+import com.hivemq.client2.internal.mqtt.message.MqttStatefulMessage;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttStatefulSubscribe extends MqttStatefulMessage.WithId<MqttSubscribe> {
 
     public static final int DEFAULT_NO_SUBSCRIPTION_IDENTIFIER = -1;
@@ -44,7 +44,7 @@ public int getSubscriptionIdentifier() {
     @Override
     protected @NotNull String toAttributeString() {
         return super.toAttributeString() + ((subscriptionIdentifier == DEFAULT_NO_SUBSCRIPTION_IDENTIFIER) ? "" :
-                "subscriptionIdentifier=" + subscriptionIdentifier);
+                ", subscriptionIdentifier=" + subscriptionIdentifier);
     }
 
     @Override
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/MqttSubAck.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubAck.java
similarity index 75%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/MqttSubAck.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubAck.java
index 0b6623d37..ea2ca9b82 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/MqttSubAck.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubAck.java
@@ -14,23 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.suback;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.internal.util.StringUtil;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAckReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.internal.util.StringUtil;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAckReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttSubAck extends MqttMessageWithUserProperties.WithReason.WithCodesAndId<Mqtt5SubAckReasonCode>
         implements Mqtt5SubAck {
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/MqttSubAckProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubAckProperty.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/MqttSubAckProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubAckProperty.java
index 7b5b26fd0..86c2e1086 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/MqttSubAckProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubAckProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.suback;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT SUBACK properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribe.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribe.java
similarity index 83%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribe.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribe.java
index c6942f2fd..8fd09c793 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribe.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribe.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.internal.util.StringUtil;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.internal.util.StringUtil;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttSubscribe extends MqttMessageWithUserProperties implements Mqtt5Subscribe {
 
     private final @NotNull ImmutableList<MqttSubscription> subscriptions;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeBuilder.java
similarity index 87%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeBuilder.java
index 0bff4c02a..bc4716648 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeBuilder.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscription;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscription;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -62,7 +62,7 @@ protected MqttSubscribeBuilder() {
         return self();
     }
 
-    public MqttSubscriptionBuilder.@NotNull Nested<B> addSubscription() {
+    public MqttSubscriptionBuilder.@NotNull Nested<B> addSubscriptionWith() {
         return new MqttSubscriptionBuilder.Nested<>(this::addSubscription);
     }
 
@@ -101,7 +101,7 @@ protected MqttSubscribeBuilder() {
         return self();
     }
 
-    public MqttUserPropertiesImplBuilder.@NotNull Nested<B> userProperties() {
+    public MqttUserPropertiesImplBuilder.@NotNull Nested<B> userPropertiesWith() {
         return new MqttUserPropertiesImplBuilder.Nested<>(userProperties, this::userProperties);
     }
 
@@ -129,12 +129,12 @@ private void buildFirstSubscription() {
         return self();
     }
 
-    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilter() {
+    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilterWith() {
         return new MqttTopicFilterImplBuilder.Nested<>(this::topicFilter);
     }
 
-    public @NotNull B qos(final @Nullable MqttQos qos) {
-        getFirstSubscriptionBuilder().qos(qos);
+    public @NotNull B maxQos(final @Nullable MqttQos maxQos) {
+        getFirstSubscriptionBuilder().maxQos(maxQos);
         return self();
     }
 
@@ -218,7 +218,8 @@ public Send(final @NotNull Function<? super MqttSubscribe, P> parentConsumer) {
     }
 
     public static abstract class Publishes<P> extends MqttSubscribeBuilder<Publishes<P>>
-            implements Mqtt5SubscribeBuilder.Publishes.Start.Complete<P>, Mqtt5SubscribeBuilder.Publishes.Args<P> {
+            implements Mqtt5SubscribeBuilder.Publishes.Start.Complete<P>,
+            Mqtt5SubscribeBuilder.Publishes.AfterComplete<P> {
 
         protected boolean manualAcknowledgement;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeProperty.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeProperty.java
index dcf1fd3ef..36860aa10 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscription.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscription.java
similarity index 79%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscription.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscription.java
index fab965266..cfe8abcb2 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscription.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscription.java
@@ -14,37 +14,37 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscription;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscription;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttSubscription implements Mqtt5Subscription {
 
     private final @NotNull MqttTopicFilterImpl topicFilter;
-    private final @NotNull MqttQos qos;
+    private final @NotNull MqttQos maxQos;
     private final boolean noLocal;
     private final @NotNull Mqtt5RetainHandling retainHandling;
     private final boolean retainAsPublished;
 
     public MqttSubscription(
             final @NotNull MqttTopicFilterImpl topicFilter,
-            final @NotNull MqttQos qos,
+            final @NotNull MqttQos maxQos,
             final boolean noLocal,
             final @NotNull Mqtt5RetainHandling retainHandling,
             final boolean retainAsPublished) {
 
         this.topicFilter = topicFilter;
-        this.qos = qos;
+        this.maxQos = maxQos;
         this.noLocal = noLocal;
         this.retainHandling = retainHandling;
         this.retainAsPublished = retainAsPublished;
@@ -56,8 +56,8 @@ public MqttSubscription(
     }
 
     @Override
-    public @NotNull MqttQos getQos() {
-        return qos;
+    public @NotNull MqttQos getMaxQos() {
+        return maxQos;
     }
 
     @Override
@@ -81,7 +81,7 @@ public boolean isRetainAsPublished() {
     }
 
     private @NotNull String toAttributeString() {
-        return "topicFilter=" + topicFilter + ", qos=" + qos + ", noLocal=" + noLocal + ", retainHandling=" +
+        return "topicFilter=" + topicFilter + ", maxQos=" + maxQos + ", noLocal=" + noLocal + ", retainHandling=" +
                 retainHandling + ", retainAsPublished=" + retainAsPublished;
     }
 
@@ -100,14 +100,14 @@ public boolean equals(final @Nullable Object o) {
         }
         final MqttSubscription that = (MqttSubscription) o;
 
-        return topicFilter.equals(that.topicFilter) && (qos == that.qos) && (noLocal == that.noLocal) &&
+        return topicFilter.equals(that.topicFilter) && (maxQos == that.maxQos) && (noLocal == that.noLocal) &&
                 (retainHandling == that.retainHandling) && (retainAsPublished == that.retainAsPublished);
     }
 
     @Override
     public int hashCode() {
         int result = topicFilter.hashCode();
-        result = 31 * result + qos.hashCode();
+        result = 31 * result + maxQos.hashCode();
         result = 31 * result + Boolean.hashCode(noLocal);
         result = 31 * result + retainHandling.hashCode();
         result = 31 * result + Boolean.hashCode(retainAsPublished);
@@ -123,11 +123,11 @@ public byte encodeSubscriptionOptions() {
         if (noLocal) {
             subscriptionOptions |= 0b0000_0100;
         }
-        subscriptionOptions |= qos.getCode();
+        subscriptionOptions |= maxQos.getCode();
         return subscriptionOptions;
     }
 
-    public static @Nullable MqttQos decodeQos(final byte subscriptionOptions) {
+    public static @Nullable MqttQos decodeMaxQos(final byte subscriptionOptions) {
         return MqttQos.fromCode(subscriptionOptions & 0b0000_0011);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscriptionBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscriptionBuilder.java
similarity index 79%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscriptionBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscriptionBuilder.java
index 176bdadd1..6ce79b3aa 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscriptionBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscriptionBuilder.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscription;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5SubscriptionBuilder;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscription;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubscriptionBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -36,7 +36,7 @@
 public abstract class MqttSubscriptionBuilder<B extends MqttSubscriptionBuilder<B>> {
 
     private @Nullable MqttTopicFilterImpl topicFilter;
-    private @NotNull MqttQos qos = MqttSubscription.DEFAULT_QOS;
+    private @NotNull MqttQos maxQos = MqttSubscription.DEFAULT_QOS;
     private boolean noLocal = MqttSubscription.DEFAULT_NO_LOCAL;
     private @NotNull Mqtt5RetainHandling retainHandling = MqttSubscription.DEFAULT_RETAIN_HANDLING;
     private boolean retainAsPublished = MqttSubscription.DEFAULT_RETAIN_AS_PUBLISHED;
@@ -45,7 +45,7 @@ public abstract class MqttSubscriptionBuilder<B extends MqttSubscriptionBuilder<
 
     MqttSubscriptionBuilder(final @NotNull MqttSubscription subscription) {
         topicFilter = subscription.getTopicFilter();
-        qos = subscription.getQos();
+        maxQos = subscription.getMaxQos();
         noLocal = subscription.isNoLocal();
         retainHandling = subscription.getRetainHandling();
         retainAsPublished = subscription.isRetainAsPublished();
@@ -63,12 +63,12 @@ public abstract class MqttSubscriptionBuilder<B extends MqttSubscriptionBuilder<
         return self();
     }
 
-    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilter() {
+    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilterWith() {
         return new MqttTopicFilterImplBuilder.Nested<>(this::topicFilter);
     }
 
-    public @NotNull B qos(final @Nullable MqttQos qos) {
-        this.qos = Checks.notNull(qos, "QoS");
+    public @NotNull B maxQos(final @Nullable MqttQos maxQos) {
+        this.maxQos = Checks.notNull(maxQos, "Maximum QoS");
         return self();
     }
 
@@ -92,7 +92,7 @@ public abstract class MqttSubscriptionBuilder<B extends MqttSubscriptionBuilder<
         Checks.state(
                 !(topicFilter.isShared() && noLocal),
                 "It is a Protocol Error to set no local to true on a Shared Subscription.");
-        return new MqttSubscription(topicFilter, qos, noLocal, retainHandling, retainAsPublished);
+        return new MqttSubscription(topicFilter, maxQos, noLocal, retainHandling, retainAsPublished);
     }
 
     public static class Default extends MqttSubscriptionBuilder<Default> implements Mqtt5SubscriptionBuilder.Complete {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/mqtt3/Mqtt3SubAckView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubAckView.java
similarity index 85%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/mqtt3/Mqtt3SubAckView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubAckView.java
index 940507d6c..c857839a1 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/mqtt3/Mqtt3SubAckView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubAckView.java
@@ -14,24 +14,24 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.suback.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAck;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAckReturnCode;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAckReasonCode;
-import io.reactivex.functions.Function;
+package com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAck;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAckReturnCode;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAckReasonCode;
+import io.reactivex.rxjava3.functions.Function;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3SubAckView implements Mqtt3SubAck {
 
     public static final @NotNull Function<Mqtt5SubAck, Mqtt3SubAck> MAPPER = Mqtt3SubAckView::of;
@@ -110,7 +110,7 @@ private Mqtt3SubAckView(final @NotNull MqttSubAck delegate) {
     }
 
     @Override
-    public @NotNull ImmutableList<@NotNull Mqtt3SubAckReturnCode> getReturnCodes() {
+    public @NotNull ImmutableList<Mqtt3SubAckReturnCode> getReturnCodes() {
         return viewReasonCodes(delegate.getReasonCodes());
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeView.java
similarity index 85%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeView.java
index 18c7dd1ab..5ffe1b8a9 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeView.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+package com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3SubscribeView implements Mqtt3Subscribe {
 
     private static @NotNull MqttSubscribe delegate(final @NotNull ImmutableList<MqttSubscription> subscriptions) {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilder.java
index 818f2fbf9..33d03ab9c 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilder.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.mqtt3;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
+package com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -58,7 +58,7 @@ protected Mqtt3SubscribeViewBuilder() {
         return self();
     }
 
-    public Mqtt3SubscriptionViewBuilder.@NotNull Nested<B> addSubscription() {
+    public Mqtt3SubscriptionViewBuilder.@NotNull Nested<B> addSubscriptionWith() {
         return new Mqtt3SubscriptionViewBuilder.Nested<>(this::addSubscription);
     }
 
@@ -116,12 +116,12 @@ private void buildFirstSubscription() {
         return self();
     }
 
-    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilter() {
+    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilterWith() {
         return new MqttTopicFilterImplBuilder.Nested<>(this::topicFilter);
     }
 
-    public @NotNull B qos(final @Nullable MqttQos qos) {
-        getFirstSubscriptionBuilder().qos(qos);
+    public @NotNull B maxQos(final @Nullable MqttQos maxQos) {
+        getFirstSubscriptionBuilder().maxQos(maxQos);
         return self();
     }
 
@@ -191,7 +191,8 @@ public Send(final @NotNull Function<? super Mqtt3SubscribeView, P> parentConsume
     }
 
     public static abstract class Publishes<P> extends Mqtt3SubscribeViewBuilder<Publishes<P>>
-            implements Mqtt3SubscribeBuilder.Publishes.Start.Complete<P>, Mqtt3SubscribeBuilder.Publishes.Args<P> {
+            implements Mqtt3SubscribeBuilder.Publishes.Start.Complete<P>,
+            Mqtt3SubscribeBuilder.Publishes.AfterComplete<P> {
 
         protected boolean manualAcknowledgement;
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionView.java
similarity index 75%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionView.java
index 9e9c02388..be0e6e699 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionView.java
@@ -14,26 +14,28 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.mqtt3;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
+package com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
+@Unmodifiable
 public class Mqtt3SubscriptionView implements Mqtt3Subscription {
 
     private static @NotNull MqttSubscription delegate(
-            final @NotNull MqttTopicFilterImpl topicFilter, final @NotNull MqttQos qos) {
+            final @NotNull MqttTopicFilterImpl topicFilter, final @NotNull MqttQos maxQos) {
 
-        return new MqttSubscription(topicFilter, qos, false, Mqtt5RetainHandling.SEND, false);
+        return new MqttSubscription(topicFilter, maxQos, false, Mqtt5RetainHandling.SEND, false);
     }
 
     static @NotNull Mqtt3SubscriptionView of(
@@ -58,8 +60,8 @@ private Mqtt3SubscriptionView(final @NotNull MqttSubscription delegate) {
     }
 
     @Override
-    public @NotNull MqttQos getQos() {
-        return delegate.getQos();
+    public @NotNull MqttQos getMaxQos() {
+        return delegate.getMaxQos();
     }
 
     public @NotNull MqttSubscription getDelegate() {
@@ -72,7 +74,7 @@ private Mqtt3SubscriptionView(final @NotNull MqttSubscription delegate) {
     }
 
     private @NotNull String toAttributeString() {
-        return "topicFilter=" + getTopicFilter() + ", qos=" + getQos();
+        return "topicFilter=" + getTopicFilter() + ", maxQos=" + getMaxQos();
     }
 
     @Override
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewBuilder.java
similarity index 74%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewBuilder.java
index 495c11fc3..af42c4dee 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewBuilder.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.mqtt3;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3SubscriptionBuilder;
+package com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubscriptionBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -36,14 +36,14 @@
 public abstract class Mqtt3SubscriptionViewBuilder<B extends Mqtt3SubscriptionViewBuilder<B>> {
 
     private @Nullable MqttTopicFilterImpl topicFilter;
-    private @NotNull MqttQos qos = Mqtt3SubscriptionView.DEFAULT_QOS;
+    private @NotNull MqttQos maxQos = Mqtt3SubscriptionView.DEFAULT_QOS;
 
     Mqtt3SubscriptionViewBuilder() {}
 
     Mqtt3SubscriptionViewBuilder(final @NotNull Mqtt3SubscriptionView subscription) {
         final MqttSubscription delegate = subscription.getDelegate();
         topicFilter = delegate.getTopicFilter();
-        qos = delegate.getQos();
+        maxQos = delegate.getMaxQos();
     }
 
     abstract @NotNull B self();
@@ -58,18 +58,18 @@ public abstract class Mqtt3SubscriptionViewBuilder<B extends Mqtt3SubscriptionVi
         return self();
     }
 
-    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilter() {
+    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilterWith() {
         return new MqttTopicFilterImplBuilder.Nested<>(this::topicFilter);
     }
 
-    public @NotNull B qos(final @Nullable MqttQos qos) {
-        this.qos = Checks.notNull(qos, "QoS");
+    public @NotNull B maxQos(final @Nullable MqttQos maxQos) {
+        this.maxQos = Checks.notNull(maxQos, "Maximum QoS");
         return self();
     }
 
     public @NotNull Mqtt3SubscriptionView build() {
         Checks.notNull(topicFilter, "Topic filter");
-        return Mqtt3SubscriptionView.of(topicFilter, qos);
+        return Mqtt3SubscriptionView.of(topicFilter, maxQos);
     }
 
     public static class Default extends Mqtt3SubscriptionViewBuilder<Default>
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttStatefulUnsubscribe.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttStatefulUnsubscribe.java
similarity index 84%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttStatefulUnsubscribe.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttStatefulUnsubscribe.java
index 5cdeb140f..b15c04858 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttStatefulUnsubscribe.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttStatefulUnsubscribe.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.message.MqttStatefulMessage;
+import com.hivemq.client2.internal.mqtt.message.MqttStatefulMessage;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttStatefulUnsubscribe extends MqttStatefulMessage.WithId<MqttUnsubscribe> {
 
     MqttStatefulUnsubscribe(final @NotNull MqttUnsubscribe unsubscribe, final int packetIdentifier) {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/MqttUnsubAck.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubAck.java
similarity index 75%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/MqttUnsubAck.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubAck.java
index 519b6bff4..162e21608 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/MqttUnsubAck.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubAck.java
@@ -14,23 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.internal.util.StringUtil;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAckReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.internal.util.StringUtil;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAckReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttUnsubAck extends MqttMessageWithUserProperties.WithReason.WithCodesAndId<Mqtt5UnsubAckReasonCode>
         implements Mqtt5UnsubAck {
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/MqttUnsubAckProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubAckProperty.java
similarity index 88%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/MqttUnsubAckProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubAckProperty.java
index c86c09163..65756d976 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/MqttUnsubAckProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubAckProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * All possible MQTT UNSUBACK properties and its byte code according to the MQTT 5 specification.
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribe.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribe.java
similarity index 81%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribe.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribe.java
index 7ba7bf629..c1a26ee9e 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribe.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribe.java
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.MqttMessageWithUserProperties;
-import com.hivemq.client.internal.util.StringUtil;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.MqttMessageWithUserProperties;
+import com.hivemq.client2.internal.util.StringUtil;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class MqttUnsubscribe extends MqttMessageWithUserProperties implements Mqtt5Unsubscribe {
 
     private final @NotNull ImmutableList<MqttTopicFilterImpl> topicFilters;
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilder.java
similarity index 86%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilder.java
index 42a0529cf..f6ad88aa0 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilder.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -65,7 +65,7 @@ public abstract class MqttUnsubscribeBuilder<B extends MqttUnsubscribeBuilder<B>
         return self();
     }
 
-    public MqttTopicFilterImplBuilder.@NotNull Nested<B> addTopicFilter() {
+    public MqttTopicFilterImplBuilder.@NotNull Nested<B> addTopicFilterWith() {
         return new MqttTopicFilterImplBuilder.Nested<>(this::addTopicFilter);
     }
 
@@ -107,7 +107,7 @@ public abstract class MqttUnsubscribeBuilder<B extends MqttUnsubscribeBuilder<B>
         return self();
     }
 
-    public MqttUserPropertiesImplBuilder.@NotNull Nested<B> userProperties() {
+    public MqttUserPropertiesImplBuilder.@NotNull Nested<B> userPropertiesWith() {
         return new MqttUserPropertiesImplBuilder.Nested<>(userProperties, this::userProperties);
     }
 
@@ -119,7 +119,7 @@ public abstract class MqttUnsubscribeBuilder<B extends MqttUnsubscribeBuilder<B>
         return addTopicFilter(topicFilter);
     }
 
-    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilter() {
+    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilterWith() {
         return new MqttTopicFilterImplBuilder.Nested<>(this::topicFilter);
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeProperty.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeProperty.java
similarity index 86%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeProperty.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeProperty.java
index 1ec39727d..a710dadf1 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeProperty.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeProperty.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/mqtt3/Mqtt3UnsubAckView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubAckView.java
similarity index 66%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/mqtt3/Mqtt3UnsubAckView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubAckView.java
index 8f6f2050a..d3d83c7f2 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/mqtt3/Mqtt3UnsubAckView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubAckView.java
@@ -14,26 +14,29 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.MqttUnsubAck;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.unsuback.Mqtt3UnsubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubAck;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAckReasonCode;
+import io.reactivex.rxjava3.functions.Function;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3UnsubAckView implements Mqtt3UnsubAck {
 
     public static final @NotNull ImmutableList<Mqtt5UnsubAckReasonCode> REASON_CODES_ALL_SUCCESS = ImmutableList.of();
     public static final @NotNull Mqtt3UnsubAckView INSTANCE = new Mqtt3UnsubAckView();
+    public static final @NotNull Function<Mqtt5UnsubAck, Mqtt3UnsubAck> MAPPER = (unsubAck) -> INSTANCE;
 
     public static @NotNull MqttUnsubAck delegate(final int packetIdentifier) {
         return new MqttUnsubAck(
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeView.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeView.java
similarity index 83%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeView.java
index 49da21777..d0d2a79be 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeView.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public class Mqtt3UnsubscribeView implements Mqtt3Unsubscribe {
 
     private static @NotNull MqttUnsubscribe delegate(final @NotNull ImmutableList<MqttTopicFilterImpl> topicFilters) {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilder.java
similarity index 81%
rename from src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilder.java
index 29e98aa8a..17b6909f7 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilder.java
@@ -14,22 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe.mqtt3;
-
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubscribeBuilder;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubscribeBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Collection;
-import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
@@ -62,7 +61,7 @@ public abstract class Mqtt3UnsubscribeViewBuilder<B extends Mqtt3UnsubscribeView
         return self();
     }
 
-    public MqttTopicFilterImplBuilder.@NotNull Nested<B> addTopicFilter() {
+    public MqttTopicFilterImplBuilder.@NotNull Nested<B> addTopicFilterWith() {
         return new MqttTopicFilterImplBuilder.Nested<>(this::addTopicFilter);
     }
 
@@ -107,7 +106,7 @@ public abstract class Mqtt3UnsubscribeViewBuilder<B extends Mqtt3UnsubscribeView
         return addTopicFilter(topicFilter);
     }
 
-    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilter() {
+    public MqttTopicFilterImplBuilder.@NotNull Nested<B> topicFilterWith() {
         return new MqttTopicFilterImplBuilder.Nested<>(this::topicFilter);
     }
 
@@ -174,24 +173,4 @@ public Send(final @NotNull Function<? super Mqtt3UnsubscribeView, P> parentConsu
             return parentConsumer.apply(build());
         }
     }
-
-    public static class SendVoid extends Mqtt3UnsubscribeViewBuilder<SendVoid>
-            implements Mqtt3UnsubscribeBuilder.SendVoid.Complete, Mqtt3UnsubscribeBuilder.SendVoid.Start {
-
-        private final @NotNull Consumer<? super Mqtt3UnsubscribeView> parentConsumer;
-
-        public SendVoid(final @NotNull Consumer<? super Mqtt3UnsubscribeView> parentConsumer) {
-            this.parentConsumer = parentConsumer;
-        }
-
-        @Override
-        @NotNull SendVoid self() {
-            return this;
-        }
-
-        @Override
-        public void send() {
-            parentConsumer.accept(build());
-        }
-    }
 }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3AsyncClientView.java b/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3AsyncClientView.java
similarity index 71%
rename from src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3AsyncClientView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3AsyncClientView.java
index 33359785b..74fa35e03 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3AsyncClientView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3AsyncClientView.java
@@ -14,38 +14,42 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.mqtt3;
-
-import com.hivemq.client.internal.mqtt.MqttAsyncClient;
-import com.hivemq.client.internal.mqtt.exceptions.mqtt3.Mqtt3ExceptionFactory;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.connack.mqtt3.Mqtt3ConnAckView;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
-import com.hivemq.client.internal.mqtt.message.disconnect.mqtt3.Mqtt3DisconnectView;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishViewBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeViewBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.mqtt3.Mqtt3SubAckView;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeViewBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3BlockingClient;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientConfig;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3RxClient;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
+package com.hivemq.client2.internal.mqtt.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.MqttAsyncClient;
+import com.hivemq.client2.internal.mqtt.exceptions.mqtt3.Mqtt3ExceptionFactory;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnAckView;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.disconnect.mqtt3.Mqtt3DisconnectView;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishResultView;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubAckView;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubAckView;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeViewBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3AsyncClient;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3BlockingClient;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientConfig;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3RxClient;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -159,8 +163,8 @@ public class Mqtt3AsyncClientView implements Mqtt3AsyncClient {
     }
 
     @Override
-    public @NotNull Mqtt3SubscribeViewAndCallbackBuilder subscribeWith() {
-        return new Mqtt3SubscribeViewAndCallbackBuilder();
+    public @NotNull SubscribeViewBuilder subscribeWith() {
+        return new SubscribeViewBuilder();
     }
 
     @Override
@@ -206,42 +210,42 @@ public void publishes(
     }
 
     @Override
-    public @NotNull CompletableFuture<Void> unsubscribe(final @Nullable Mqtt3Unsubscribe unsubscribe) {
+    public @NotNull CompletableFuture<Mqtt3UnsubAck> unsubscribe(final @Nullable Mqtt3Unsubscribe unsubscribe) {
         final MqttUnsubscribe mqttUnsubscribe = MqttChecks.unsubscribe(unsubscribe);
 
-        final CompletableFuture<Void> future = new CompletableFuture<>();
+        final CompletableFuture<Mqtt3UnsubAck> future = new CompletableFuture<>();
         delegate.unsubscribe(mqttUnsubscribe).whenComplete((unsubAck, throwable) -> {
             if (throwable != null) {
                 future.completeExceptionally(Mqtt3ExceptionFactory.map(throwable));
             } else {
-                future.complete(null);
+                future.complete(Mqtt3UnsubAckView.INSTANCE);
             }
         });
         return future;
     }
 
     @Override
-    public Mqtt3UnsubscribeViewBuilder.@NotNull Send<CompletableFuture<Void>> unsubscribeWith() {
+    public Mqtt3UnsubscribeViewBuilder.@NotNull Send<CompletableFuture<Mqtt3UnsubAck>> unsubscribeWith() {
         return new Mqtt3UnsubscribeViewBuilder.Send<>(this::unsubscribe);
     }
 
     @Override
-    public @NotNull CompletableFuture<@NotNull Mqtt3Publish> publish(final @Nullable Mqtt3Publish publish) {
+    public @NotNull CompletableFuture<@NotNull Mqtt3PublishResult> publish(final @Nullable Mqtt3Publish publish) {
         final MqttPublish mqttPublish = MqttChecks.publish(publish);
 
-        final CompletableFuture<Mqtt3Publish> future = new CompletableFuture<>();
+        final CompletableFuture<Mqtt3PublishResult> future = new CompletableFuture<>();
         delegate.publish(mqttPublish).whenComplete((publishResult, throwable) -> {
             if (throwable != null) {
                 future.completeExceptionally(Mqtt3ExceptionFactory.map(throwable));
             } else {
-                future.complete(Mqtt3PublishView.of(publishResult.getPublish()));
+                future.complete(Mqtt3PublishResultView.of(publishResult));
             }
         });
         return future;
     }
 
     @Override
-    public Mqtt3PublishViewBuilder.@NotNull Send<CompletableFuture<Mqtt3Publish>> publishWith() {
+    public Mqtt3PublishViewBuilder.@NotNull Send<CompletableFuture<Mqtt3PublishResult>> publishWith() {
         return new Mqtt3PublishViewBuilder.Send<>(this::publish);
     }
 
@@ -273,35 +277,32 @@ public void publishes(
         return new Mqtt3BlockingClientView(delegate.toBlocking());
     }
 
-    private class Mqtt3SubscribeViewAndCallbackBuilder
-            extends Mqtt3SubscribeViewBuilder<Mqtt3SubscribeViewAndCallbackBuilder>
-            implements Mqtt3SubscribeAndCallbackBuilder.Start.Complete, Mqtt3SubscribeAndCallbackBuilder.Call.Ex {
+    private class SubscribeViewBuilder extends Mqtt3SubscribeViewBuilder<SubscribeViewBuilder>
+            implements SubscribeBuilder.Start.Complete, SubscribeBuilder.AfterCallback {
 
         private @Nullable Consumer<Mqtt3Publish> callback;
         private @Nullable Executor executor;
         private boolean manualAcknowledgement;
 
         @Override
-        protected @NotNull Mqtt3SubscribeViewAndCallbackBuilder self() {
+        protected @NotNull SubscribeViewBuilder self() {
             return this;
         }
 
         @Override
-        public @NotNull Mqtt3SubscribeViewAndCallbackBuilder callback(final @Nullable Consumer<Mqtt3Publish> callback) {
+        public @NotNull SubscribeViewBuilder callback(final @Nullable Consumer<Mqtt3Publish> callback) {
             this.callback = Checks.notNull(callback, "Callback");
             return this;
         }
 
         @Override
-        public @NotNull Mqtt3SubscribeViewAndCallbackBuilder executor(final @Nullable Executor executor) {
+        public @NotNull SubscribeViewBuilder executor(final @Nullable Executor executor) {
             this.executor = Checks.notNull(executor, "Executor");
             return this;
         }
 
         @Override
-        public @NotNull Mqtt3SubscribeViewAndCallbackBuilder manualAcknowledgement(
-                final boolean manualAcknowledgement) {
-
+        public @NotNull SubscribeViewBuilder manualAcknowledgement(final boolean manualAcknowledgement) {
             this.manualAcknowledgement = manualAcknowledgement;
             return this;
         }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3BlockingClientView.java b/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3BlockingClientView.java
similarity index 58%
rename from src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3BlockingClientView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3BlockingClientView.java
index 2b732b470..fb1cf3975 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3BlockingClientView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3BlockingClientView.java
@@ -14,38 +14,42 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.mqtt3;
-
-import com.hivemq.client.internal.mqtt.MqttBlockingClient;
-import com.hivemq.client.internal.mqtt.exceptions.mqtt3.Mqtt3ExceptionFactory;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.connack.mqtt3.Mqtt3ConnAckView;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
-import com.hivemq.client.internal.mqtt.message.disconnect.mqtt3.Mqtt3DisconnectView;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishViewBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeViewBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.mqtt3.Mqtt3SubAckView;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeViewBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3BlockingClient;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientConfig;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3RxClient;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5MessageException;
+package com.hivemq.client2.internal.mqtt.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.MqttBlockingClient;
+import com.hivemq.client2.internal.mqtt.exceptions.mqtt3.Mqtt3ExceptionFactory;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnAckView;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.disconnect.mqtt3.Mqtt3DisconnectView;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishResultView;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubAckView;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubAckView;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeViewBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3AsyncClient;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3BlockingClient;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientConfig;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3RxClient;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5BlockingClient;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5MessageException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -101,47 +105,48 @@ public class Mqtt3BlockingClientView implements Mqtt3BlockingClient {
     }
 
     @Override
-    public @NotNull Mqtt3Publishes publishes(final @Nullable MqttGlobalPublishFilter filter) {
+    public @NotNull PublishesView publishes(final @Nullable MqttGlobalPublishFilter filter) {
         return publishes(filter, false);
     }
 
     @Override
-    public @NotNull Mqtt3Publishes publishes(
+    public @NotNull PublishesView publishes(
             final @Nullable MqttGlobalPublishFilter filter, final boolean manualAcknowledgement) {
 
         Checks.notNull(filter, "Global publish filter");
 
-        return new Mqtt3PublishesView(delegate.publishes(filter, manualAcknowledgement));
+        return new PublishesView(delegate.publishes(filter, manualAcknowledgement));
     }
 
     @Override
-    public void unsubscribe(final @Nullable Mqtt3Unsubscribe unsubscribe) {
+    public @NotNull Mqtt3UnsubAck unsubscribe(final @Nullable Mqtt3Unsubscribe unsubscribe) {
         final MqttUnsubscribe mqttUnsubscribe = MqttChecks.unsubscribe(unsubscribe);
         try {
             delegate.unsubscribe(mqttUnsubscribe);
+            return Mqtt3UnsubAckView.INSTANCE;
         } catch (final Mqtt5MessageException e) {
             throw Mqtt3ExceptionFactory.mapWithStackTrace(e);
         }
     }
 
     @Override
-    public Mqtt3UnsubscribeViewBuilder.@NotNull SendVoid unsubscribeWith() {
-        return new Mqtt3UnsubscribeViewBuilder.SendVoid(this::unsubscribe);
+    public Mqtt3UnsubscribeViewBuilder.@NotNull Send<Mqtt3UnsubAck> unsubscribeWith() {
+        return new Mqtt3UnsubscribeViewBuilder.Send<>(this::unsubscribe);
     }
 
     @Override
-    public void publish(final @Nullable Mqtt3Publish publish) {
+    public @NotNull Mqtt3PublishResult publish(final @Nullable Mqtt3Publish publish) {
         final MqttPublish mqttPublish = MqttChecks.publish(publish);
         try {
-            delegate.publish(mqttPublish);
+            return Mqtt3PublishResultView.of(delegate.publish(mqttPublish));
         } catch (final Mqtt5MessageException e) {
             throw Mqtt3ExceptionFactory.mapWithStackTrace(e);
         }
     }
 
     @Override
-    public Mqtt3PublishViewBuilder.@NotNull SendVoid publishWith() {
-        return new Mqtt3PublishViewBuilder.SendVoid(this::publish);
+    public Mqtt3PublishViewBuilder.@NotNull Send<Mqtt3PublishResult> publishWith() {
+        return new Mqtt3PublishViewBuilder.Send<>(this::publish);
     }
 
     @Override
@@ -168,11 +173,11 @@ public void disconnect() {
         return new Mqtt3AsyncClientView(delegate.toAsync());
     }
 
-    private static class Mqtt3PublishesView implements Mqtt3Publishes {
+    private static class PublishesView implements Publishes {
 
-        private final @NotNull Mqtt5BlockingClient.Mqtt5Publishes delegate;
+        private final @NotNull Mqtt5BlockingClient.Publishes delegate;
 
-        Mqtt3PublishesView(final @NotNull Mqtt5BlockingClient.Mqtt5Publishes delegate) {
+        PublishesView(final @NotNull Mqtt5BlockingClient.Publishes delegate) {
             this.delegate = delegate;
         }
 
@@ -189,9 +194,6 @@ private static class Mqtt3PublishesView implements Mqtt3Publishes {
         public @NotNull Optional<Mqtt3Publish> receive(
                 final long timeout, final @Nullable TimeUnit timeUnit) throws InterruptedException {
 
-            if (timeout < 0) {
-                throw new IllegalArgumentException("Timeout must be greater than 0.");
-            }
             Checks.notNull(timeUnit, "Time unit");
 
             try {
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3ClientConfigView.java b/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3ClientConfigView.java
similarity index 59%
rename from src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3ClientConfigView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3ClientConfigView.java
index 1002e1516..28700ecd7 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3ClientConfigView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3ClientConfigView.java
@@ -14,30 +14,29 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.mqtt3;
-
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthView;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
-import com.hivemq.client.mqtt.MqttClientExecutorConfig;
-import com.hivemq.client.mqtt.MqttClientState;
-import com.hivemq.client.mqtt.MqttClientTransportConfig;
-import com.hivemq.client.mqtt.MqttVersion;
-import com.hivemq.client.mqtt.datatypes.MqttClientIdentifier;
-import com.hivemq.client.mqtt.lifecycle.MqttClientAutoReconnect;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedListener;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientConfig;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientConnectionConfig;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
+package com.hivemq.client2.internal.mqtt.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthView;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.MqttClientState;
+import com.hivemq.client2.mqtt.MqttExecutorConfig;
+import com.hivemq.client2.mqtt.MqttTransportConfig;
+import com.hivemq.client2.mqtt.MqttVersion;
+import com.hivemq.client2.mqtt.datatypes.MqttClientIdentifier;
+import com.hivemq.client2.mqtt.lifecycle.MqttAutoReconnect;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedListener;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedListener;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientConfig;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientConnectionConfig;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.List;
 import java.util.Optional;
 
 /**
@@ -57,22 +56,22 @@ public Mqtt3ClientConfigView(final @NotNull MqttClientConfig delegate) {
     }
 
     @Override
-    public @NotNull Optional<MqttClientIdentifier> getClientIdentifier() {
-        return delegate.getClientIdentifier();
+    public @NotNull Optional<MqttClientIdentifier> getIdentifier() {
+        return delegate.getIdentifier();
     }
 
     @Override
-    public @NotNull MqttClientTransportConfig getTransportConfig() {
+    public @NotNull MqttTransportConfig getTransportConfig() {
         return delegate.getTransportConfig();
     }
 
     @Override
-    public @NotNull MqttClientExecutorConfig getExecutorConfig() {
+    public @NotNull MqttExecutorConfig getExecutorConfig() {
         return delegate.getExecutorConfig();
     }
 
     @Override
-    public @NotNull Optional<MqttClientAutoReconnect> getAutomaticReconnect() {
+    public @NotNull Optional<MqttAutoReconnect> getAutomaticReconnect() {
         return delegate.getAutomaticReconnect();
     }
 
@@ -97,12 +96,12 @@ public Mqtt3ClientConfigView(final @NotNull MqttClientConfig delegate) {
     }
 
     @Override
-    public @Immutable @NotNull List<@NotNull MqttClientConnectedListener> getConnectedListeners() {
+    public @NotNull ImmutableList<MqttConnectedListener> getConnectedListeners() {
         return delegate.getConnectedListeners();
     }
 
     @Override
-    public @Immutable @NotNull List<@NotNull MqttClientDisconnectedListener> getDisconnectedListeners() {
+    public @NotNull ImmutableList<MqttDisconnectedListener> getDisconnectedListeners() {
         return delegate.getDisconnectedListeners();
     }
 
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3RxClientView.java b/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3RxClientView.java
similarity index 64%
rename from src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3RxClientView.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3RxClientView.java
index b85701b6f..cb04de18f 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3RxClientView.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3RxClientView.java
@@ -14,45 +14,49 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.mqtt3;
-
-import com.hivemq.client.internal.mqtt.MqttRxClient;
-import com.hivemq.client.internal.mqtt.exceptions.mqtt3.Mqtt3ExceptionFactory;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.connack.mqtt3.Mqtt3ConnAckView;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
-import com.hivemq.client.internal.mqtt.message.disconnect.mqtt3.Mqtt3DisconnectView;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishResultView;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeViewBuilder;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.mqtt3.Mqtt3SubAckView;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeViewBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3RxClient;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.rx.FlowableWithSingle;
-import io.reactivex.Completable;
-import io.reactivex.Flowable;
-import io.reactivex.Single;
-import io.reactivex.functions.Function;
+package com.hivemq.client2.internal.mqtt.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.MqttRxClient;
+import com.hivemq.client2.internal.mqtt.exceptions.mqtt3.Mqtt3ExceptionFactory;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnAckView;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.disconnect.mqtt3.Mqtt3DisconnectView;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishResultView;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubAckView;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubAckView;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeViewBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3RxClient;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.rx.FlowableWithSingle;
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.Single;
+import io.reactivex.rxjava3.functions.Function;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.reactivestreams.Publisher;
 
 /**
  * @author Silvio Giebl
@@ -71,6 +75,9 @@ public class Mqtt3RxClientView implements Mqtt3RxClient {
     private static final @NotNull Function<Throwable, Single<Mqtt5SubAck>> EXCEPTION_MAPPER_SINGLE_SUBACK =
             e -> Single.error(Mqtt3ExceptionFactory.map(e));
 
+    private static final @NotNull Function<Throwable, Single<Mqtt5UnsubAck>> EXCEPTION_MAPPER_SINGLE_UNSUBACK =
+            e -> Single.error(Mqtt3ExceptionFactory.map(e));
+
     private static final @NotNull Function<Throwable, Flowable<Mqtt5Publish>> EXCEPTION_MAPPER_FLOWABLE_PUBLISH =
             e -> Flowable.error(Mqtt3ExceptionFactory.map(e));
 
@@ -118,18 +125,6 @@ public class Mqtt3RxClientView implements Mqtt3RxClient {
         return new Mqtt3SubscribeViewBuilder.Nested<>(this::subscribe);
     }
 
-    @Override
-    public @NotNull FlowableWithSingle<Mqtt3Publish, Mqtt3SubAck> subscribeStream(
-            final @NotNull Mqtt3Subscribe subscribe) {
-
-        return subscribePublishes(subscribe);
-    }
-
-    @Override
-    public Mqtt3SubscribeViewBuilder.@NotNull Nested<FlowableWithSingle<Mqtt3Publish, Mqtt3SubAck>> subscribeStreamWith() {
-        return new Mqtt3SubscribeViewBuilder.Nested<>(this::subscribeStream);
-    }
-
     @Override
     public @NotNull FlowableWithSingle<Mqtt3Publish, Mqtt3SubAck> subscribePublishes(
             final @Nullable Mqtt3Subscribe subscribe) {
@@ -170,22 +165,24 @@ public class Mqtt3RxClientView implements Mqtt3RxClient {
     }
 
     @Override
-    public @NotNull Completable unsubscribe(final @Nullable Mqtt3Unsubscribe unsubscribe) {
+    public @NotNull Single<Mqtt3UnsubAck> unsubscribe(final @Nullable Mqtt3Unsubscribe unsubscribe) {
         final MqttUnsubscribe mqttUnsubscribe = MqttChecks.unsubscribe(unsubscribe);
 
-        return delegate.unsubscribe(mqttUnsubscribe).ignoreElement().onErrorResumeNext(EXCEPTION_MAPPER_COMPLETABLE);
+        return delegate.unsubscribe(mqttUnsubscribe)
+                .onErrorResumeNext(EXCEPTION_MAPPER_SINGLE_UNSUBACK)
+                .map(Mqtt3UnsubAckView.MAPPER);
     }
 
     @Override
-    public Mqtt3UnsubscribeViewBuilder.@NotNull Nested<Completable> unsubscribeWith() {
+    public Mqtt3UnsubscribeViewBuilder.@NotNull Nested<Single<Mqtt3UnsubAck>> unsubscribeWith() {
         return new Mqtt3UnsubscribeViewBuilder.Nested<>(this::unsubscribe);
     }
 
     @Override
-    public @NotNull Flowable<Mqtt3PublishResult> publish(final @Nullable Flowable<Mqtt3Publish> publishFlowable) {
-        Checks.notNull(publishFlowable, "Publish flowable");
+    public @NotNull Flowable<Mqtt3PublishResult> publish(final @NotNull Publisher<Mqtt3Publish> publisher) {
+        Checks.notNull(publisher, "Publisher");
 
-        return delegate.publish(publishFlowable, PUBLISH_MAPPER)
+        return delegate.publish(publisher, PUBLISH_MAPPER)
                 .onErrorResumeNext(EXCEPTION_MAPPER_FLOWABLE_PUBLISH_RESULT)
                 .map(Mqtt3PublishResultView.MAPPER);
     }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3RxClientViewBuilder.java b/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3RxClientViewBuilder.java
similarity index 74%
rename from src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3RxClientViewBuilder.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3RxClientViewBuilder.java
index b935435b2..0c00c0d97 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3RxClientViewBuilder.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3RxClientViewBuilder.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.mqtt3;
-
-import com.hivemq.client.internal.mqtt.*;
-import com.hivemq.client.internal.mqtt.advanced.MqttClientAdvancedConfig;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthView;
-import com.hivemq.client.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthViewBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishViewBuilder;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.mqtt.MqttVersion;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
+package com.hivemq.client2.internal.mqtt.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.*;
+import com.hivemq.client2.internal.mqtt.advanced.MqttAdvancedConfig;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthView;
+import com.hivemq.client2.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthViewBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishViewBuilder;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.mqtt.MqttVersion;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -55,7 +55,7 @@ public Mqtt3RxClientViewBuilder(final @NotNull MqttRxClientBuilderBase<?> client
     }
 
     @Override
-    public Mqtt3SimpleAuthViewBuilder.@NotNull Nested<Mqtt3RxClientViewBuilder> simpleAuth() {
+    public Mqtt3SimpleAuthViewBuilder.@NotNull Nested<Mqtt3RxClientViewBuilder> simpleAuthWith() {
         return new Mqtt3SimpleAuthViewBuilder.Nested<>(this::simpleAuth);
     }
 
@@ -67,7 +67,7 @@ public Mqtt3RxClientViewBuilder(final @NotNull MqttRxClientBuilderBase<?> client
     }
 
     @Override
-    public Mqtt3PublishViewBuilder.@NotNull WillNested<Mqtt3RxClientViewBuilder> willPublish() {
+    public Mqtt3PublishViewBuilder.@NotNull WillNested<Mqtt3RxClientViewBuilder> willPublishWith() {
         return new Mqtt3PublishViewBuilder.WillNested<>(this::willPublish);
     }
 
@@ -109,7 +109,7 @@ public Mqtt3RxClientViewBuilder(final @NotNull MqttRxClientBuilderBase<?> client
     }
 
     private @NotNull MqttClientConfig buildClientConfig() {
-        return buildClientConfig(MqttVersion.MQTT_3_1_1, MqttClientAdvancedConfig.DEFAULT,
+        return buildClientConfig(MqttVersion.MQTT_3_1_1, MqttAdvancedConfig.DEFAULT,
                 MqttClientConfig.ConnectDefaults.of(simpleAuth, null, willPublish));
     }
 }
diff --git a/src/main/java/com/hivemq/client/internal/mqtt/util/MqttChecks.java b/src/main/java/com/hivemq/client2/internal/mqtt/util/MqttChecks.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/mqtt/util/MqttChecks.java
rename to src/main/java/com/hivemq/client2/internal/mqtt/util/MqttChecks.java
index f71cfad7a..200b24944 100644
--- a/src/main/java/com/hivemq/client/internal/mqtt/util/MqttChecks.java
+++ b/src/main/java/com/hivemq/client2/internal/mqtt/util/MqttChecks.java
@@ -14,35 +14,35 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.util;
-
-import com.hivemq.client.internal.mqtt.datatypes.*;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeView;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeView;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttClientIdentifier;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+package com.hivemq.client2.internal.mqtt.util;
+
+import com.hivemq.client2.internal.mqtt.datatypes.*;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishView;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeView;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeView;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttClientIdentifier;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperty;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/internal/netty/ContextFuture.java b/src/main/java/com/hivemq/client2/internal/netty/ContextFuture.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/netty/ContextFuture.java
rename to src/main/java/com/hivemq/client2/internal/netty/ContextFuture.java
index 63b4df478..3e7188ade 100644
--- a/src/main/java/com/hivemq/client/internal/netty/ContextFuture.java
+++ b/src/main/java/com/hivemq/client2/internal/netty/ContextFuture.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.netty;
+package com.hivemq.client2.internal.netty;
 
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelPromise;
diff --git a/src/main/java/com/hivemq/client/internal/netty/DefaultChannelOutboundHandler.java b/src/main/java/com/hivemq/client2/internal/netty/DefaultChannelOutboundHandler.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/netty/DefaultChannelOutboundHandler.java
rename to src/main/java/com/hivemq/client2/internal/netty/DefaultChannelOutboundHandler.java
index 159fb6e63..6560e4416 100644
--- a/src/main/java/com/hivemq/client/internal/netty/DefaultChannelOutboundHandler.java
+++ b/src/main/java/com/hivemq/client2/internal/netty/DefaultChannelOutboundHandler.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.netty;
+package com.hivemq.client2.internal.netty;
 
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelOutboundHandler;
diff --git a/src/main/java/com/hivemq/client/internal/netty/DefaultContextPromise.java b/src/main/java/com/hivemq/client2/internal/netty/DefaultContextPromise.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/netty/DefaultContextPromise.java
rename to src/main/java/com/hivemq/client2/internal/netty/DefaultContextPromise.java
index f77890c7b..d05c1b907 100644
--- a/src/main/java/com/hivemq/client/internal/netty/DefaultContextPromise.java
+++ b/src/main/java/com/hivemq/client2/internal/netty/DefaultContextPromise.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.netty;
+package com.hivemq.client2.internal.netty;
 
 import io.netty.channel.Channel;
 import io.netty.channel.DefaultChannelPromise;
diff --git a/src/main/java/com/hivemq/client/internal/netty/NettyEventLoopProvider.java b/src/main/java/com/hivemq/client2/internal/netty/NettyEventLoopProvider.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/netty/NettyEventLoopProvider.java
rename to src/main/java/com/hivemq/client2/internal/netty/NettyEventLoopProvider.java
index 5ef5044c4..623cb28c6 100644
--- a/src/main/java/com/hivemq/client/internal/netty/NettyEventLoopProvider.java
+++ b/src/main/java/com/hivemq/client2/internal/netty/NettyEventLoopProvider.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.netty;
+package com.hivemq.client2.internal.netty;
 
-import com.hivemq.client.internal.annotations.ThreadSafe;
-import com.hivemq.client.internal.logging.InternalLogger;
-import com.hivemq.client.internal.logging.InternalLoggerFactory;
-import com.hivemq.client.internal.mqtt.MqttClientExecutorConfigImpl;
-import com.hivemq.client.internal.util.ClassUtil;
+import com.hivemq.client2.internal.annotations.ThreadSafe;
+import com.hivemq.client2.internal.logging.InternalLogger;
+import com.hivemq.client2.internal.logging.InternalLoggerFactory;
+import com.hivemq.client2.internal.mqtt.MqttExecutorConfigImpl;
+import com.hivemq.client2.internal.util.ClassUtil;
 import io.netty.channel.ChannelFactory;
 import io.netty.channel.EventLoop;
 import io.netty.channel.MultithreadEventLoopGroup;
@@ -92,11 +92,11 @@ private NettyEventLoopProvider(
             if (executor == null) {
                 eventLoopGroup = eventLoopGroupFactory.apply(
                         threadCount, new ThreadPerTaskExecutor(
-                                new DefaultThreadFactory("com.hivemq.client.mqtt", Thread.MAX_PRIORITY)));
+                                new DefaultThreadFactory("com.hivemq.client2.mqtt", Thread.MAX_PRIORITY)));
 
             } else if (executor instanceof MultithreadEventLoopGroup) {
                 eventLoopGroup = (MultithreadEventLoopGroup) executor;
-                if ((threadCount != MqttClientExecutorConfigImpl.DEFAULT_NETTY_THREADS) &&
+                if ((threadCount != MqttExecutorConfigImpl.DEFAULT_NETTY_THREADS) &&
                         (eventLoopGroup.executorCount() != threadCount)) {
                     LOGGER.warn("Tried to use a different amount of Netty threads for the provided event loop. " +
                             "Using {} threads instead of {}", eventLoopGroup.executorCount(), threadCount);
@@ -107,7 +107,7 @@ threadCount, new ThreadPerTaskExecutor(
             entry = new Entry(eventLoopGroup);
             entries.put(executor, entry);
         } else {
-            if ((threadCount != MqttClientExecutorConfigImpl.DEFAULT_NETTY_THREADS) &&
+            if ((threadCount != MqttExecutorConfigImpl.DEFAULT_NETTY_THREADS) &&
                     (entry.eventLoopGroup.executorCount() != threadCount)) {
                 LOGGER.warn("Tried to use a different amount of Netty threads for the same executor. " +
                         "Using {} threads instead of {}", entry.eventLoopGroup.executorCount(), threadCount);
diff --git a/src/main/java/com/hivemq/client/internal/rx/CompletableFlow.java b/src/main/java/com/hivemq/client2/internal/rx/CompletableFlow.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/rx/CompletableFlow.java
rename to src/main/java/com/hivemq/client2/internal/rx/CompletableFlow.java
index c6acc42ee..573853d59 100644
--- a/src/main/java/com/hivemq/client/internal/rx/CompletableFlow.java
+++ b/src/main/java/com/hivemq/client2/internal/rx/CompletableFlow.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx;
+package com.hivemq.client2.internal.rx;
 
-import io.reactivex.CompletableObserver;
-import io.reactivex.disposables.Disposable;
+import io.reactivex.rxjava3.core.CompletableObserver;
+import io.reactivex.rxjava3.disposables.Disposable;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/rx/WithSingleConditionalSubscriber.java b/src/main/java/com/hivemq/client2/internal/rx/WithSingleConditionalSubscriber.java
similarity index 82%
rename from src/main/java/com/hivemq/client/internal/rx/WithSingleConditionalSubscriber.java
rename to src/main/java/com/hivemq/client2/internal/rx/WithSingleConditionalSubscriber.java
index a874ad7c2..e34d6cd07 100644
--- a/src/main/java/com/hivemq/client/internal/rx/WithSingleConditionalSubscriber.java
+++ b/src/main/java/com/hivemq/client2/internal/rx/WithSingleConditionalSubscriber.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx;
+package com.hivemq.client2.internal.rx;
 
-import com.hivemq.client.rx.FlowableWithSingleSubscriber;
-import io.reactivex.internal.fuseable.ConditionalSubscriber;
+import com.hivemq.client2.rx.FlowableWithSingleSubscriber;
+import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/rx/WithSingleStrictSubscriber.java b/src/main/java/com/hivemq/client2/internal/rx/WithSingleStrictSubscriber.java
similarity index 93%
rename from src/main/java/com/hivemq/client/internal/rx/WithSingleStrictSubscriber.java
rename to src/main/java/com/hivemq/client2/internal/rx/WithSingleStrictSubscriber.java
index 587b7a840..13ad3c06b 100644
--- a/src/main/java/com/hivemq/client/internal/rx/WithSingleStrictSubscriber.java
+++ b/src/main/java/com/hivemq/client2/internal/rx/WithSingleStrictSubscriber.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx;
+package com.hivemq.client2.internal.rx;
 
-import com.hivemq.client.rx.FlowableWithSingleSubscriber;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import io.reactivex.internal.subscriptions.SubscriptionHelper;
-import io.reactivex.internal.util.BackpressureHelper;
+import com.hivemq.client2.rx.FlowableWithSingleSubscriber;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper;
+import io.reactivex.rxjava3.internal.util.BackpressureHelper;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscription;
diff --git a/src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleCombine.java b/src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleCombine.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleCombine.java
rename to src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleCombine.java
index 2a6485a4f..29f57a8a1 100644
--- a/src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleCombine.java
+++ b/src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleCombine.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.operators;
-
-import com.hivemq.client.internal.rx.WithSingleConditionalSubscriber;
-import com.hivemq.client.rx.FlowableWithSingle;
-import com.hivemq.client.rx.FlowableWithSingleSubscriber;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import io.reactivex.Flowable;
-import io.reactivex.internal.fuseable.ConditionalSubscriber;
-import io.reactivex.internal.util.BackpressureHelper;
+package com.hivemq.client2.internal.rx.operators;
+
+import com.hivemq.client2.internal.rx.WithSingleConditionalSubscriber;
+import com.hivemq.client2.rx.FlowableWithSingle;
+import com.hivemq.client2.rx.FlowableWithSingleSubscriber;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber;
+import io.reactivex.rxjava3.internal.util.BackpressureHelper;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleMap.java b/src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleMap.java
similarity index 94%
rename from src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleMap.java
rename to src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleMap.java
index 1c26f0646..e32317038 100644
--- a/src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleMap.java
+++ b/src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleMap.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.operators;
-
-import com.hivemq.client.internal.rx.WithSingleConditionalSubscriber;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.rx.FlowableWithSingle;
-import com.hivemq.client.rx.FlowableWithSingleSubscriber;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import io.reactivex.exceptions.Exceptions;
-import io.reactivex.functions.Function;
-import io.reactivex.internal.fuseable.ConditionalSubscriber;
+package com.hivemq.client2.internal.rx.operators;
+
+import com.hivemq.client2.internal.rx.WithSingleConditionalSubscriber;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.rx.FlowableWithSingle;
+import com.hivemq.client2.rx.FlowableWithSingleSubscriber;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import io.reactivex.rxjava3.exceptions.Exceptions;
+import io.reactivex.rxjava3.functions.Function;
+import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleMapError.java b/src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleMapError.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleMapError.java
rename to src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleMapError.java
index f27ba8cbb..4e62d2a64 100644
--- a/src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleMapError.java
+++ b/src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleMapError.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.operators;
-
-import com.hivemq.client.internal.rx.WithSingleConditionalSubscriber;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.rx.FlowableWithSingle;
-import com.hivemq.client.rx.FlowableWithSingleSubscriber;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import io.reactivex.FlowableSubscriber;
-import io.reactivex.exceptions.CompositeException;
-import io.reactivex.exceptions.Exceptions;
-import io.reactivex.functions.Function;
-import io.reactivex.internal.fuseable.ConditionalSubscriber;
+package com.hivemq.client2.internal.rx.operators;
+
+import com.hivemq.client2.internal.rx.WithSingleConditionalSubscriber;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.rx.FlowableWithSingle;
+import com.hivemq.client2.rx.FlowableWithSingleSubscriber;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import io.reactivex.rxjava3.core.FlowableSubscriber;
+import io.reactivex.rxjava3.exceptions.CompositeException;
+import io.reactivex.rxjava3.exceptions.Exceptions;
+import io.reactivex.rxjava3.functions.Function;
+import io.reactivex.rxjava3.internal.fuseable.ConditionalSubscriber;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleObserveOn.java b/src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleObserveOn.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleObserveOn.java
rename to src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleObserveOn.java
index 0394f62da..f9fd17942 100644
--- a/src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleObserveOn.java
+++ b/src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleObserveOn.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.operators;
+package com.hivemq.client2.internal.rx.operators;
 
-import com.hivemq.client.rx.FlowableWithSingle;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import io.reactivex.Scheduler;
+import com.hivemq.client2.rx.FlowableWithSingle;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import io.reactivex.rxjava3.core.Scheduler;
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Subscriber;
 
diff --git a/src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleOperator.java b/src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleOperator.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleOperator.java
rename to src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleOperator.java
index af8738bb0..dbf362372 100644
--- a/src/main/java/com/hivemq/client/internal/rx/operators/FlowableWithSingleOperator.java
+++ b/src/main/java/com/hivemq/client2/internal/rx/operators/FlowableWithSingleOperator.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.rx.operators;
+package com.hivemq.client2.internal.rx.operators;
 
-import com.hivemq.client.rx.FlowableWithSingle;
+import com.hivemq.client2.rx.FlowableWithSingle;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/util/AsyncRuntimeException.java b/src/main/java/com/hivemq/client2/internal/util/AsyncRuntimeException.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/util/AsyncRuntimeException.java
rename to src/main/java/com/hivemq/client2/internal/util/AsyncRuntimeException.java
index f124a699d..86342be04 100644
--- a/src/main/java/com/hivemq/client/internal/util/AsyncRuntimeException.java
+++ b/src/main/java/com/hivemq/client2/internal/util/AsyncRuntimeException.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/internal/util/ByteArray.java b/src/main/java/com/hivemq/client2/internal/util/ByteArray.java
similarity index 97%
rename from src/main/java/com/hivemq/client/internal/util/ByteArray.java
rename to src/main/java/com/hivemq/client2/internal/util/ByteArray.java
index 8d8586ebf..498971f77 100644
--- a/src/main/java/com/hivemq/client/internal/util/ByteArray.java
+++ b/src/main/java/com/hivemq/client2/internal/util/ByteArray.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/internal/util/ByteArrayUtil.java b/src/main/java/com/hivemq/client2/internal/util/ByteArrayUtil.java
similarity index 97%
rename from src/main/java/com/hivemq/client/internal/util/ByteArrayUtil.java
rename to src/main/java/com/hivemq/client2/internal/util/ByteArrayUtil.java
index f70f44c33..b12d6d4ac 100644
--- a/src/main/java/com/hivemq/client/internal/util/ByteArrayUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/util/ByteArrayUtil.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/ByteBufferUtil.java b/src/main/java/com/hivemq/client2/internal/util/ByteBufferUtil.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/util/ByteBufferUtil.java
rename to src/main/java/com/hivemq/client2/internal/util/ByteBufferUtil.java
index e3832e276..9b04c8ecd 100644
--- a/src/main/java/com/hivemq/client/internal/util/ByteBufferUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/util/ByteBufferUtil.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/internal/util/Checks.java b/src/main/java/com/hivemq/client2/internal/util/Checks.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/util/Checks.java
rename to src/main/java/com/hivemq/client2/internal/util/Checks.java
index 18924785d..8cd4a0c7f 100644
--- a/src/main/java/com/hivemq/client/internal/util/Checks.java
+++ b/src/main/java/com/hivemq/client2/internal/util/Checks.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
-import com.hivemq.client.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/internal/util/ClassUtil.java b/src/main/java/com/hivemq/client2/internal/util/ClassUtil.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/util/ClassUtil.java
rename to src/main/java/com/hivemq/client2/internal/util/ClassUtil.java
index 6bf513719..e40313367 100644
--- a/src/main/java/com/hivemq/client/internal/util/ClassUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/util/ClassUtil.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/ExecutorUtil.java b/src/main/java/com/hivemq/client2/internal/util/ExecutorUtil.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/util/ExecutorUtil.java
rename to src/main/java/com/hivemq/client2/internal/util/ExecutorUtil.java
index 53211b263..3de35d923 100644
--- a/src/main/java/com/hivemq/client/internal/util/ExecutorUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/util/ExecutorUtil.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/InetSocketAddressUtil.java b/src/main/java/com/hivemq/client2/internal/util/InetSocketAddressUtil.java
similarity index 97%
rename from src/main/java/com/hivemq/client/internal/util/InetSocketAddressUtil.java
rename to src/main/java/com/hivemq/client2/internal/util/InetSocketAddressUtil.java
index fac25bf5b..a32e3419d 100644
--- a/src/main/java/com/hivemq/client/internal/util/InetSocketAddressUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/util/InetSocketAddressUtil.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import io.netty.util.NetUtil;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/main/java/com/hivemq/client/internal/util/Pow2Util.java b/src/main/java/com/hivemq/client2/internal/util/Pow2Util.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/util/Pow2Util.java
rename to src/main/java/com/hivemq/client2/internal/util/Pow2Util.java
index be17d92ca..cac9b709d 100644
--- a/src/main/java/com/hivemq/client/internal/util/Pow2Util.java
+++ b/src/main/java/com/hivemq/client2/internal/util/Pow2Util.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 /**
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/internal/util/Ranges.java b/src/main/java/com/hivemq/client2/internal/util/Ranges.java
similarity index 97%
rename from src/main/java/com/hivemq/client/internal/util/Ranges.java
rename to src/main/java/com/hivemq/client2/internal/util/Ranges.java
index 4c1a868b8..c395f2533 100644
--- a/src/main/java/com/hivemq/client/internal/util/Ranges.java
+++ b/src/main/java/com/hivemq/client2/internal/util/Ranges.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
-import com.hivemq.client.internal.annotations.NotThreadSafe;
+import com.hivemq.client2.internal.annotations.NotThreadSafe;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/StringUtil.java b/src/main/java/com/hivemq/client2/internal/util/StringUtil.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/util/StringUtil.java
rename to src/main/java/com/hivemq/client2/internal/util/StringUtil.java
index af7149032..6e13aaeac 100644
--- a/src/main/java/com/hivemq/client/internal/util/StringUtil.java
+++ b/src/main/java/com/hivemq/client2/internal/util/StringUtil.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/UnsignedDataTypes.java b/src/main/java/com/hivemq/client2/internal/util/UnsignedDataTypes.java
similarity index 91%
rename from src/main/java/com/hivemq/client/internal/util/UnsignedDataTypes.java
rename to src/main/java/com/hivemq/client2/internal/util/UnsignedDataTypes.java
index feea0d948..cf8ec6f32 100644
--- a/src/main/java/com/hivemq/client/internal/util/UnsignedDataTypes.java
+++ b/src/main/java/com/hivemq/client2/internal/util/UnsignedDataTypes.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 /**
  * @author Silvio Giebl
  */
 public final class UnsignedDataTypes {
 
+    public static final short UNSIGNED_BYTE_MAX_VALUE = 0xFF;
     public static final int UNSIGNED_SHORT_MAX_VALUE = 0xFFFF;
     public static final long UNSIGNED_INT_MAX_VALUE = 0xFFFF_FFFFL;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/Utf8Util.java b/src/main/java/com/hivemq/client2/internal/util/Utf8Util.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/util/Utf8Util.java
rename to src/main/java/com/hivemq/client2/internal/util/Utf8Util.java
index 600e35ccf..0f631c837 100644
--- a/src/main/java/com/hivemq/client/internal/util/Utf8Util.java
+++ b/src/main/java/com/hivemq/client2/internal/util/Utf8Util.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/ChunkedArrayQueue.java b/src/main/java/com/hivemq/client2/internal/util/collections/ChunkedArrayQueue.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/util/collections/ChunkedArrayQueue.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/ChunkedArrayQueue.java
index c567ca5bb..53f8f78ac 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/ChunkedArrayQueue.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/ChunkedArrayQueue.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.internal.annotations.NotThreadSafe;
+import com.hivemq.client2.internal.annotations.NotThreadSafe;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/HandleList.java b/src/main/java/com/hivemq/client2/internal/util/collections/HandleList.java
similarity index 91%
rename from src/main/java/com/hivemq/client/internal/util/collections/HandleList.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/HandleList.java
index 74d740859..1260afbfb 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/HandleList.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/HandleList.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.internal.annotations.NotThreadSafe;
+import com.hivemq.client2.internal.annotations.NotThreadSafe;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableArray.java b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableArray.java
similarity index 97%
rename from src/main/java/com/hivemq/client/internal/util/collections/ImmutableArray.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/ImmutableArray.java
index aaf7de16c..9f9e0d0b2 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableArray.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableArray.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.Checks;
+import com.hivemq.client2.internal.util.Checks;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.lang.reflect.Array;
 import java.util.*;
@@ -29,7 +29,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable class ImmutableArray<E> implements ImmutableList<E> {
+@Unmodifiable class ImmutableArray<E> implements ImmutableList<E> {
 
     @Contract("null -> fail")
     static <E> @NotNull ImmutableList<E> of(final @Nullable Object @Nullable ... elements) {
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableElement.java b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableElement.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/util/collections/ImmutableElement.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/ImmutableElement.java
index fb63a7918..89f2747ba 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableElement.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableElement.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.Checks;
+import com.hivemq.client2.internal.util.Checks;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.lang.reflect.Array;
 import java.util.List;
@@ -31,7 +31,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable class ImmutableElement<E> implements ImmutableList<E> {
+@Unmodifiable class ImmutableElement<E> implements ImmutableList<E> {
 
     @Contract("null -> fail")
     static <E> @NotNull ImmutableList<E> of(final @Nullable E e) {
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableEmptyIntList.java b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableEmptyIntList.java
similarity index 89%
rename from src/main/java/com/hivemq/client/internal/util/collections/ImmutableEmptyIntList.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/ImmutableEmptyIntList.java
index e4fa2d032..8cdd147e5 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableEmptyIntList.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableEmptyIntList.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.annotations.Immutable;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable class ImmutableEmptyIntList implements ImmutableIntList {
+@Unmodifiable class ImmutableEmptyIntList implements ImmutableIntList {
 
     static final @NotNull ImmutableEmptyIntList INSTANCE = new ImmutableEmptyIntList();
 
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableEmptyList.java b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableEmptyList.java
similarity index 95%
rename from src/main/java/com/hivemq/client/internal/util/collections/ImmutableEmptyList.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/ImmutableEmptyList.java
index 0659753f9..f48808111 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableEmptyList.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableEmptyList.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.Checks;
+import com.hivemq.client2.internal.util.Checks;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.List;
 import java.util.NoSuchElementException;
@@ -29,7 +29,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable class ImmutableEmptyList implements ImmutableList<Object> {
+@Unmodifiable class ImmutableEmptyList implements ImmutableList<Object> {
 
     private static final @NotNull ImmutableEmptyList INSTANCE = new ImmutableEmptyList();
     private static final @NotNull Object @NotNull [] EMPTY = {};
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableIntArray.java b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableIntArray.java
similarity index 90%
rename from src/main/java/com/hivemq/client/internal/util/collections/ImmutableIntArray.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/ImmutableIntArray.java
index fa3bf604b..40017516a 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableIntArray.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableIntArray.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.Checks;
+import com.hivemq.client2.internal.util.Checks;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.Arrays;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable class ImmutableIntArray implements ImmutableIntList {
+@Unmodifiable class ImmutableIntArray implements ImmutableIntList {
 
     private final int @NotNull [] array;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableIntElement.java b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableIntElement.java
similarity index 87%
rename from src/main/java/com/hivemq/client/internal/util/collections/ImmutableIntElement.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/ImmutableIntElement.java
index f5c79c252..ec8aad3a0 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableIntElement.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableIntElement.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.Checks;
+import com.hivemq.client2.internal.util.Checks;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 /**
  * @author Silvio Giebl
  */
-@Immutable class ImmutableIntElement implements ImmutableIntList {
+@Unmodifiable class ImmutableIntElement implements ImmutableIntList {
 
     private final int element;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableIntList.java b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableIntList.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/util/collections/ImmutableIntList.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/ImmutableIntList.java
index 2e6373415..7f2c3ea92 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableIntList.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableIntList.java
@@ -14,17 +14,19 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.internal.util.Checks;
+import com.hivemq.client2.internal.util.Checks;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.Arrays;
 
 /**
  * @author Silvio Giebl
  */
+@Unmodifiable
 public interface ImmutableIntList {
 
     static @NotNull ImmutableIntList of() {
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableList.java b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableList.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/util/collections/ImmutableList.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/ImmutableList.java
index d62fe628f..6c842e6a9 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/ImmutableList.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/ImmutableList.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.util.Checks;
+import com.hivemq.client2.internal.util.Checks;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.*;
 import java.util.function.Predicate;
@@ -29,7 +29,7 @@
 /**
  * @author Silvio Giebl
  */
-@Immutable
+@Unmodifiable
 public interface ImmutableList<@NotNull E> extends List<E>, RandomAccess {
 
     static <E> @NotNull ImmutableList<E> of() {
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/Index.java b/src/main/java/com/hivemq/client2/internal/util/collections/Index.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/util/collections/Index.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/Index.java
index 269150a3e..085d85b3e 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/Index.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/Index.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.internal.annotations.NotThreadSafe;
-import com.hivemq.client.internal.util.Pow2Util;
+import com.hivemq.client2.internal.annotations.NotThreadSafe;
+import com.hivemq.client2.internal.util.Pow2Util;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/IntIndex.java b/src/main/java/com/hivemq/client2/internal/util/collections/IntIndex.java
similarity index 98%
rename from src/main/java/com/hivemq/client/internal/util/collections/IntIndex.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/IntIndex.java
index 50d5de0f3..a1d569b81 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/IntIndex.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/IntIndex.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.internal.annotations.NotThreadSafe;
-import com.hivemq.client.internal.util.Pow2Util;
+import com.hivemq.client2.internal.annotations.NotThreadSafe;
+import com.hivemq.client2.internal.util.Pow2Util;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/internal/util/collections/NodeList.java b/src/main/java/com/hivemq/client2/internal/util/collections/NodeList.java
similarity index 96%
rename from src/main/java/com/hivemq/client/internal/util/collections/NodeList.java
rename to src/main/java/com/hivemq/client2/internal/util/collections/NodeList.java
index b020a19c5..2c0c57a31 100644
--- a/src/main/java/com/hivemq/client/internal/util/collections/NodeList.java
+++ b/src/main/java/com/hivemq/client2/internal/util/collections/NodeList.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.internal.annotations.NotThreadSafe;
+import com.hivemq.client2.internal.annotations.NotThreadSafe;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClient.java b/src/main/java/com/hivemq/client2/mqtt/MqttClient.java
similarity index 64%
rename from src/main/java/com/hivemq/client/mqtt/MqttClient.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttClient.java
index 62ff7dba6..5d78737d6 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClient.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttClient.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.MqttRxClientBuilderBase;
+import com.hivemq.client2.internal.mqtt.MqttRxClientBuilderBase;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,30 +26,9 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttClient {
 
-    /**
-     * The default server host.
-     */
-    @NotNull String DEFAULT_SERVER_HOST = "localhost";
-    /**
-     * The default server port.
-     */
-    int DEFAULT_SERVER_PORT = 1883;
-    /**
-     * The default server port when using SSL/TLS.
-     */
-    int DEFAULT_SERVER_PORT_SSL = 8883;
-    /**
-     * The default server port when using WebSocket.
-     */
-    int DEFAULT_SERVER_PORT_WEBSOCKET = 80;
-    /**
-     * The default server port when using SSL/TLS and WebSocket.
-     */
-    int DEFAULT_SERVER_PORT_WEBSOCKET_SSL = 443;
-
     /**
      * Creates a builder for an MQTT client.
      *
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientBuilder.java b/src/main/java/com/hivemq/client2/mqtt/MqttClientBuilder.java
similarity index 71%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttClientBuilder.java
index 9bb0003e8..825cc789b 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttClientBuilder.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientBuilder;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientBuilder;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,13 +28,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttClientBuilder extends MqttClientBuilderBase<MqttClientBuilder> {
 
     /**
      * Uses {@link MqttVersion#MQTT_3_1_1 MQTT version 3}.
      *
-     * @return the builder for the {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client Mqtt3Client}.
+     * @return the builder for the {@link com.hivemq.client2.mqtt.mqtt3.Mqtt3Client Mqtt3Client}.
      */
     @CheckReturnValue
     @NotNull Mqtt3ClientBuilder useMqttVersion3();
@@ -42,7 +42,7 @@ public interface MqttClientBuilder extends MqttClientBuilderBase<MqttClientBuild
     /**
      * Uses {@link MqttVersion#MQTT_5_0 MQTT version 5}.
      *
-     * @return the builder for the {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client Mqtt5Client}.
+     * @return the builder for the {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client Mqtt5Client}.
      */
     @CheckReturnValue
     @NotNull Mqtt5ClientBuilder useMqttVersion5();
diff --git a/src/main/java/com/hivemq/client2/mqtt/MqttClientBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/MqttClientBuilderBase.java
new file mode 100644
index 000000000..7cbeb83fd
--- /dev/null
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttClientBuilderBase.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2018-present HiveMQ and the HiveMQ Community
+ *
+ * Licensed 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
+ *
+ *     http://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 com.hivemq.client2.mqtt;
+
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttClientIdentifier;
+import com.hivemq.client2.mqtt.lifecycle.MqttAutoReconnect;
+import com.hivemq.client2.mqtt.lifecycle.MqttAutoReconnectBuilder;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedListener;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedListener;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Builder base for an {@link MqttClient}.
+ *
+ * @param <B> the type of the builder.
+ * @author Silvio Giebl
+ * @since 1.0
+ */
+@ApiStatus.NonExtendable
+public interface MqttClientBuilderBase<B extends MqttClientBuilderBase<B>> extends MqttTransportConfigBuilderBase<B> {
+
+    /**
+     * Sets the {@link MqttClientConfig#getIdentifier() Client Identifier}.
+     *
+     * @param identifier the string representation of the Client Identifier.
+     * @return the builder.
+     */
+    @CheckReturnValue
+    @NotNull B identifier(@NotNull String identifier);
+
+    /**
+     * Sets the {@link MqttClientConfig#getIdentifier() Client Identifier}.
+     *
+     * @param identifier the Client Identifier.
+     * @return the builder.
+     */
+    @CheckReturnValue
+    @NotNull B identifier(@NotNull MqttClientIdentifier identifier);
+
+    /**
+     * Sets the {@link MqttClientConfig#getTransportConfig() transport configuration}.
+     *
+     * @param transportConfig the transport configuration.
+     * @return the builder.
+     * @since 1.1
+     */
+    @CheckReturnValue
+    @NotNull B transportConfig(@NotNull MqttTransportConfig transportConfig);
+
+    /**
+     * Fluent counterpart of {@link #transportConfig(MqttTransportConfig)}.
+     * <p>
+     * Calling {@link MqttTransportConfigBuilder.Nested#applyTransportConfig()} on the returned builder has the effect
+     * of extending the current transport configuration.
+     *
+     * @return the fluent builder for the transport configuration.
+     * @see #transportConfig(MqttTransportConfig)
+     * @since 1.1
+     */
+    @CheckReturnValue
+    MqttTransportConfigBuilder.@NotNull Nested<? extends B> transportConfigWith();
+
+    /**
+     * Sets the {@link MqttClientConfig#getExecutorConfig() executor configuration}.
+     *
+     * @param executorConfig the executor configuration.
+     * @return the builder.
+     */
+    @CheckReturnValue
+    @NotNull B executorConfig(@NotNull MqttExecutorConfig executorConfig);
+
+    /**
+     * Fluent counterpart of {@link #executorConfig(MqttExecutorConfig)}.
+     * <p>
+     * Calling {@link MqttExecutorConfigBuilder.Nested#applyExecutorConfig()} on the returned builder has the effect of
+     * extending the current executor configuration.
+     *
+     * @return the fluent builder for the executor configuration.
+     * @see #executorConfig(MqttExecutorConfig)
+     */
+    @CheckReturnValue
+    MqttExecutorConfigBuilder.@NotNull Nested<? extends B> executorConfigWith();
+
+    /**
+     * Uses automatic reconnect with the default configuration.
+     *
+     * @return the builder.
+     * @since 1.1
+     */
+    @CheckReturnValue
+    @NotNull B automaticReconnect();
+
+    /**
+     * Sets the optional {@link MqttClientConfig#getAutomaticReconnect() automatic reconnect strategy}.
+     *
+     * @param autoReconnect the automatic reconnect strategy or <code>null</code> to remove any previously set automatic
+     *                      reconnect strategy.
+     * @return the builder.
+     * @since 1.1
+     */
+    @CheckReturnValue
+    @NotNull B automaticReconnect(@Nullable MqttAutoReconnect autoReconnect);
+
+    /**
+     * Fluent counterpart of {@link #automaticReconnect(MqttAutoReconnect)}.
+     * <p>
+     * Calling {@link MqttAutoReconnectBuilder.Nested#applyAutomaticReconnect()} on the returned builder has the effect
+     * of extending the current automatic reconnect strategy.
+     *
+     * @return the fluent builder for the automatic reconnect strategy.
+     * @see #automaticReconnect(MqttAutoReconnect)
+     * @since 1.1
+     */
+    @CheckReturnValue
+    MqttAutoReconnectBuilder.@NotNull Nested<? extends B> automaticReconnectWith();
+
+    /**
+     * Adds a listener which is notified when the client is connected (a successful ConnAck message is received).
+     * <p>
+     * The listeners are called in the same order in which they are added.
+     *
+     * @param connectedListener the listener to add.
+     * @return the builder.
+     * @since 1.1
+     */
+    @CheckReturnValue
+    @NotNull B addConnectedListener(@NotNull MqttConnectedListener connectedListener);
+
+    /**
+     * Adds a listener which is notified when the client is disconnected (with or without a Disconnect message) or the
+     * connection fails.
+     * <p>
+     * The listeners are called in the same order in which they are added.
+     *
+     * @param disconnectedListener the listener to add.
+     * @return the builder.
+     * @since 1.1
+     */
+    @CheckReturnValue
+    @NotNull B addDisconnectedListener(@NotNull MqttDisconnectedListener disconnectedListener);
+}
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientConfig.java b/src/main/java/com/hivemq/client2/mqtt/MqttClientConfig.java
similarity index 55%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttClientConfig.java
index f7b8c58ff..9b4c18c21 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttClientConfig.java
@@ -14,17 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.mqtt.datatypes.MqttClientIdentifier;
-import com.hivemq.client.mqtt.lifecycle.MqttClientAutoReconnect;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedListener;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener;
+import com.hivemq.client2.mqtt.datatypes.MqttClientIdentifier;
+import com.hivemq.client2.mqtt.lifecycle.MqttAutoReconnect;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedListener;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedListener;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
-import java.net.InetSocketAddress;
 import java.util.List;
 import java.util.Optional;
 
@@ -34,7 +33,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttClientConfig {
 
     /**
@@ -48,74 +47,38 @@ public interface MqttClientConfig {
      *
      * @return the (currently not present) identifier of the client.
      */
-    @NotNull Optional<MqttClientIdentifier> getClientIdentifier();
-
-    /**
-     * @return the server address the client connects to.
-     * @since 1.1
-     */
-    default @NotNull InetSocketAddress getServerAddress() {
-        return getTransportConfig().getServerAddress();
-    }
-
-    /**
-     * @return the server host the clients connects to.
-     */
-    default @NotNull String getServerHost() {
-        return getServerAddress().getHostString();
-    }
-
-    /**
-     * @return the server port the client connects to.
-     */
-    default int getServerPort() {
-        return getServerAddress().getPort();
-    }
-
-    /**
-     * @return the optional secure transport configuration of the client.
-     */
-    default @NotNull Optional<MqttClientSslConfig> getSslConfig() {
-        return getTransportConfig().getSslConfig();
-    }
-
-    /**
-     * @return the optional WebSocket configuration of the client.
-     */
-    default @NotNull Optional<MqttWebSocketConfig> getWebSocketConfig() {
-        return getTransportConfig().getWebSocketConfig();
-    }
+    @NotNull Optional<MqttClientIdentifier> getIdentifier();
 
     /**
      * @return the transport configuration of the client.
      * @since 1.1
      */
-    @NotNull MqttClientTransportConfig getTransportConfig();
+    @NotNull MqttTransportConfig getTransportConfig();
 
     /**
      * @return the executor configuration of the client.
      */
-    @NotNull MqttClientExecutorConfig getExecutorConfig();
+    @NotNull MqttExecutorConfig getExecutorConfig();
 
     /**
      * @return the optional automatic reconnect strategy of the client.
      * @since 1.1
      */
-    @NotNull Optional<MqttClientAutoReconnect> getAutomaticReconnect();
+    @NotNull Optional<MqttAutoReconnect> getAutomaticReconnect();
 
     /**
      * @return the listeners which are notified (in the order of the list) when this client is connected (a successful
      *         ConnAck message is received).
      * @since 1.1
      */
-    @Immutable @NotNull List<@NotNull MqttClientConnectedListener> getConnectedListeners();
+    @Unmodifiable @NotNull List<@NotNull MqttConnectedListener> getConnectedListeners();
 
     /**
      * @return the listeners which are notified (in the order of the list) when this client is disconnected (with or
      *         without a Disconnect message) or the connection fails.
      * @since 1.1
      */
-    @Immutable @NotNull List<@NotNull MqttClientDisconnectedListener> getDisconnectedListeners();
+    @Unmodifiable @NotNull List<@NotNull MqttDisconnectedListener> getDisconnectedListeners();
 
     /**
      * @return the state of the client.
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientConnectionConfig.java b/src/main/java/com/hivemq/client2/mqtt/MqttClientConnectionConfig.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientConnectionConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttClientConnectionConfig.java
index b4bdc75f8..147028243 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientConnectionConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttClientConnectionConfig.java
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 /**
  * Connection configuration of an {@link MqttClient}.
@@ -25,19 +27,19 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttClientConnectionConfig {
 
     /**
      * @return the transport configuration the client is connected with.
      * @since 1.1
      */
-    @NotNull MqttClientTransportConfig getTransportConfig();
+    @NotNull MqttTransportConfig getTransportConfig();
 
     /**
      * @return the keep alive in seconds that is used while the client is connected.
      */
-    int getKeepAlive();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getKeepAlive();
 
     /**
      * @return whether the client connected with simple authentication and/or authorization related data.
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientState.java b/src/main/java/com/hivemq/client2/mqtt/MqttClientState.java
similarity index 98%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientState.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttClientState.java
index 4413c4d39..61258a1c0 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientState.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttClientState.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
 import org.jetbrains.annotations.NotNull;
 
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientExecutorConfig.java b/src/main/java/com/hivemq/client2/mqtt/MqttExecutorConfig.java
similarity index 74%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientExecutorConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttExecutorConfig.java
index 5b98e764f..35ff991ab 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientExecutorConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttExecutorConfig.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.MqttClientExecutorConfigImplBuilder;
-import io.reactivex.Scheduler;
-import io.reactivex.schedulers.Schedulers;
+import com.hivemq.client2.internal.mqtt.MqttExecutorConfigImplBuilder;
+import io.reactivex.rxjava3.core.Scheduler;
+import io.reactivex.rxjava3.schedulers.Schedulers;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.util.Optional;
 import java.util.OptionalInt;
@@ -32,8 +33,8 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface MqttClientExecutorConfig {
+@ApiStatus.NonExtendable
+public interface MqttExecutorConfig {
 
     @NotNull Scheduler DEFAULT_APPLICATION_SCHEDULER = Schedulers.computation();
 
@@ -42,8 +43,8 @@ public interface MqttClientExecutorConfig {
      *
      * @return the created builder for an executor configuration.
      */
-    static @NotNull MqttClientExecutorConfigBuilder builder() {
-        return new MqttClientExecutorConfigImplBuilder.Default();
+    static @NotNull MqttExecutorConfigBuilder builder() {
+        return new MqttExecutorConfigImplBuilder.Default();
     }
 
     /**
@@ -54,7 +55,7 @@ public interface MqttClientExecutorConfig {
     /**
      * @return the optional user defined amount of threads Netty (network communication framework) will use.
      */
-    @NotNull OptionalInt getNettyThreads();
+    @Range(from = 1, to = Integer.MAX_VALUE) @NotNull OptionalInt getNettyThreads();
 
     /**
      * @return the {@link Scheduler} used for executing application specific code, such as callbacks.
@@ -67,5 +68,5 @@ public interface MqttClientExecutorConfig {
      * @return the created builder.
      * @since 1.1
      */
-    @NotNull MqttClientExecutorConfigBuilder extend();
+    @NotNull MqttExecutorConfigBuilder extend();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientExecutorConfigBuilder.java b/src/main/java/com/hivemq/client2/mqtt/MqttExecutorConfigBuilder.java
similarity index 50%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientExecutorConfigBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttExecutorConfigBuilder.java
index e1afc50f8..b8e62fb52 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientExecutorConfigBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttExecutorConfigBuilder.java
@@ -14,42 +14,41 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * Builder for a {@link MqttClientExecutorConfig}.
+ * Builder for a {@link MqttExecutorConfig}.
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface MqttClientExecutorConfigBuilder
-        extends MqttClientExecutorConfigBuilderBase<MqttClientExecutorConfigBuilder> {
+@ApiStatus.NonExtendable
+public interface MqttExecutorConfigBuilder extends MqttExecutorConfigBuilderBase<MqttExecutorConfigBuilder> {
 
     /**
-     * Builds the {@link MqttClientExecutorConfig}.
+     * Builds the {@link MqttExecutorConfig}.
      *
-     * @return the built {@link MqttClientExecutorConfig}.
+     * @return the built {@link MqttExecutorConfig}.
      */
     @CheckReturnValue
-    @NotNull MqttClientExecutorConfig build();
+    @NotNull MqttExecutorConfig build();
 
     /**
-     * Builder for a {@link MqttClientExecutorConfig} that is applied to a parent.
+     * Builder for a {@link MqttExecutorConfig} that is applied to a parent.
      *
-     * @param <P> the type of the result when the built {@link MqttClientExecutorConfig} is applied to the parent.
+     * @param <P> the type of the result when the built {@link MqttExecutorConfig} is applied to the parent.
      */
-    @DoNotImplement
-    interface Nested<P> extends MqttClientExecutorConfigBuilderBase<Nested<P>> {
+    @ApiStatus.NonExtendable
+    interface Nested<P> extends MqttExecutorConfigBuilderBase<Nested<P>> {
 
         /**
-         * Builds the {@link MqttClientExecutorConfig} and applies it to the parent.
+         * Builds the {@link MqttExecutorConfig} and applies it to the parent.
          *
-         * @return the result when the built {@link MqttClientExecutorConfig} is applied to the parent.
+         * @return the result when the built {@link MqttExecutorConfig} is applied to the parent.
          */
         @NotNull P applyExecutorConfig();
     }
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientExecutorConfigBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/MqttExecutorConfigBuilderBase.java
similarity index 63%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientExecutorConfigBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttExecutorConfigBuilderBase.java
index 1ac5696e0..a6282179e 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientExecutorConfigBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttExecutorConfigBuilderBase.java
@@ -14,28 +14,29 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import io.reactivex.Scheduler;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import io.reactivex.rxjava3.core.Scheduler;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.util.concurrent.Executor;
 
 /**
- * Builder base for a {@link MqttClientExecutorConfig}.
+ * Builder base for a {@link MqttExecutorConfig}.
  *
  * @param <B> the type of the builder.
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface MqttClientExecutorConfigBuilderBase<B extends MqttClientExecutorConfigBuilderBase<B>> {
+@ApiStatus.NonExtendable
+public interface MqttExecutorConfigBuilderBase<B extends MqttExecutorConfigBuilderBase<B>> {
 
     /**
-     * Sets the optional user defined {@link MqttClientExecutorConfig#getNettyExecutor() executor for Netty} (network
+     * Sets the optional user defined {@link MqttExecutorConfig#getNettyExecutor() executor for Netty} (network
      * communication framework).
      *
      * @param nettyExecutor the user defined executor for Netty or <code>null</code> to use the default executor.
@@ -45,18 +46,18 @@ public interface MqttClientExecutorConfigBuilderBase<B extends MqttClientExecuto
     @NotNull B nettyExecutor(@Nullable Executor nettyExecutor);
 
     /**
-     * Sets the optional user defined {@link MqttClientExecutorConfig#getNettyThreads() amount of threads Netty}
-     * (network communication framework).
+     * Sets the optional user defined {@link MqttExecutorConfig#getNettyThreads() amount of threads Netty} (network
+     * communication framework).
      *
      * @param nettyThreads the user defined amount of threads Netty.
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B nettyThreads(int nettyThreads);
+    @NotNull B nettyThreads(@Range(from = 1, to = Integer.MAX_VALUE) int nettyThreads);
 
     /**
-     * Sets the {@link MqttClientExecutorConfig#getApplicationScheduler() scheduler used for executing application
-     * specific code}.
+     * Sets the {@link MqttExecutorConfig#getApplicationScheduler() scheduler used for executing application specific
+     * code}.
      *
      * @param applicationScheduler the scheduler used for executing application specific code.
      * @return the builder.
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttGlobalPublishFilter.java b/src/main/java/com/hivemq/client2/mqtt/MqttGlobalPublishFilter.java
similarity index 98%
rename from src/main/java/com/hivemq/client/mqtt/MqttGlobalPublishFilter.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttGlobalPublishFilter.java
index 44330f36a..046294377 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttGlobalPublishFilter.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttGlobalPublishFilter.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
 /**
  * Global filter for incoming Publish messages.
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttProxyConfig.java b/src/main/java/com/hivemq/client2/mqtt/MqttProxyConfig.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/MqttProxyConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttProxyConfig.java
index 0ff13b44e..c450bbb95 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttProxyConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttProxyConfig.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.MqttProxyConfigImplBuilder;
+import com.hivemq.client2.internal.mqtt.MqttProxyConfigImplBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.net.InetSocketAddress;
 import java.util.Optional;
@@ -29,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.2
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttProxyConfig {
 
     /**
@@ -85,7 +86,7 @@ public interface MqttProxyConfig {
     /**
      * @return the proxy handshake timeout in milliseconds.
      */
-    int getHandshakeTimeoutMs();
+    @Range(from = 0, to = Integer.MAX_VALUE) int getHandshakeTimeoutMs();
 
     /**
      * Creates a builder for extending this proxy configuration.
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttProxyConfigBuilder.java b/src/main/java/com/hivemq/client2/mqtt/MqttProxyConfigBuilder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/MqttProxyConfigBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttProxyConfigBuilder.java
index 0c52135b5..46e44906c 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttProxyConfigBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttProxyConfigBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,7 +26,7 @@
  * @author Silvio Giebl
  * @since 1.2
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttProxyConfigBuilder extends MqttProxyConfigBuilderBase<MqttProxyConfigBuilder> {
 
     /**
@@ -42,7 +42,7 @@ public interface MqttProxyConfigBuilder extends MqttProxyConfigBuilderBase<MqttP
      *
      * @param <P> the type of the result when the built {@link MqttProxyConfig} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends MqttProxyConfigBuilderBase<Nested<P>> {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttProxyConfigBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/MqttProxyConfigBuilderBase.java
similarity index 95%
rename from src/main/java/com/hivemq/client/mqtt/MqttProxyConfigBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttProxyConfigBuilderBase.java
index c593cc832..f784761a8 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttProxyConfigBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttProxyConfigBuilderBase.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -32,7 +32,7 @@
  * @author Silvio Giebl
  * @since 1.2
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttProxyConfigBuilderBase<B extends MqttProxyConfigBuilderBase<B>> {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttProxyProtocol.java b/src/main/java/com/hivemq/client2/mqtt/MqttProxyProtocol.java
similarity index 96%
rename from src/main/java/com/hivemq/client/mqtt/MqttProxyProtocol.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttProxyProtocol.java
index 89ab1f907..d81e6e68f 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttProxyProtocol.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttProxyProtocol.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
 /**
  * Available proxy protocols for a {@link MqttProxyConfig}.
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientSslConfig.java b/src/main/java/com/hivemq/client2/mqtt/MqttTlsConfig.java
similarity index 63%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientSslConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttTlsConfig.java
index 8aa5f67a8..06f2a1ebf 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientSslConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttTlsConfig.java
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.MqttClientSslConfigImplBuilder;
+import com.hivemq.client2.internal.mqtt.MqttTlsConfigImplBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
+import org.jetbrains.annotations.Unmodifiable;
 
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.KeyManagerFactory;
@@ -28,27 +29,27 @@
 import java.util.Optional;
 
 /**
- * Configuration for a secure transport to use by {@link MqttClient MQTT clients}.
+ * Configuration for transport layer security to use by {@link MqttClient MQTT clients}.
  *
  * @author Christoph Schäbel
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface MqttClientSslConfig {
+@ApiStatus.NonExtendable
+public interface MqttTlsConfig {
 
     /**
-     * The default SSL/TLS handshake timeout in milliseconds.
+     * The default TLS handshake timeout in milliseconds.
      */
-    long DEFAULT_HANDSHAKE_TIMEOUT_MS = 10_000;
+    int DEFAULT_HANDSHAKE_TIMEOUT_MS = 10_000;
 
     /**
-     * Creates a builder for a secure transport configuration.
+     * Creates a builder for a transport layer security configuration.
      *
-     * @return the created builder for a secure transport configuration.
+     * @return the created builder for a transport layer security configuration.
      */
-    static @NotNull MqttClientSslConfigBuilder builder() {
-        return new MqttClientSslConfigImplBuilder.Default();
+    static @NotNull MqttTlsConfigBuilder builder() {
+        return new MqttTlsConfigImplBuilder.Default();
     }
 
     /**
@@ -67,7 +68,7 @@ public interface MqttClientSslConfig {
      *
      * @return the optional user defined cipher suites.
      */
-    @NotNull Optional<@Immutable List<@NotNull String>> getCipherSuites();
+    @NotNull Optional<@Unmodifiable List<@NotNull String>> getCipherSuites();
 
     /**
      * The optional user defined protocols. If absent, the default protocols of Netty (network communication framework)
@@ -75,12 +76,12 @@ public interface MqttClientSslConfig {
      *
      * @return the optional user defined protocols.
      */
-    @NotNull Optional<@Immutable List<@NotNull String>> getProtocols();
+    @NotNull Optional<@Unmodifiable List<@NotNull String>> getProtocols();
 
     /**
-     * @return the SSL/TLS handshake timeout in milliseconds.
+     * @return the TLS handshake timeout in milliseconds.
      */
-    long getHandshakeTimeoutMs();
+    @Range(from = 0, to = Integer.MAX_VALUE) int getHandshakeTimeoutMs();
 
     /**
      * @return the optional user defined hostname verifier. If absent, https hostname verification is performed.
@@ -89,10 +90,10 @@ public interface MqttClientSslConfig {
     @NotNull Optional<HostnameVerifier> getHostnameVerifier();
 
     /**
-     * Creates a builder for extending this secure transport configuration.
+     * Creates a builder for extending this transport layer security configuration.
      *
      * @return the created builder.
      * @since 1.1
      */
-    @NotNull MqttClientSslConfigBuilder extend();
+    @NotNull MqttTlsConfigBuilder extend();
 }
diff --git a/src/main/java/com/hivemq/client2/mqtt/MqttTlsConfigBuilder.java b/src/main/java/com/hivemq/client2/mqtt/MqttTlsConfigBuilder.java
new file mode 100644
index 000000000..ba74fbc5a
--- /dev/null
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttTlsConfigBuilder.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018-present HiveMQ and the HiveMQ Community
+ *
+ * Licensed 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
+ *
+ *     http://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 com.hivemq.client2.mqtt;
+
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Builder for a {@link MqttTlsConfig}.
+ *
+ * @author Silvio Giebl
+ * @since 1.0
+ */
+@ApiStatus.NonExtendable
+public interface MqttTlsConfigBuilder extends MqttTlsConfigBuilderBase<MqttTlsConfigBuilder> {
+
+    /**
+     * Builds the {@link MqttTlsConfig}.
+     *
+     * @return the built {@link MqttTlsConfig}.
+     */
+    @CheckReturnValue
+    @NotNull MqttTlsConfig build();
+
+    /**
+     * Builder for a {@link MqttTlsConfig} that is applied to a parent.
+     *
+     * @param <P> the type of the result when the built {@link MqttTlsConfig} is applied to the parent.
+     */
+    @ApiStatus.NonExtendable
+    interface Nested<P> extends MqttTlsConfigBuilderBase<Nested<P>> {
+
+        /**
+         * Builds the {@link MqttTlsConfig} and applies it to the parent.
+         *
+         * @return the result when the built {@link MqttTlsConfig} is applied to the parent.
+         */
+        @NotNull P applyTlsConfig();
+    }
+}
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientSslConfigBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/MqttTlsConfigBuilderBase.java
similarity index 74%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientSslConfigBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttTlsConfigBuilderBase.java
index b8aeb0692..026371840 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientSslConfigBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttTlsConfigBuilderBase.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -28,17 +28,17 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Builder base for a {@link MqttClientSslConfig}.
+ * Builder base for a {@link MqttTlsConfig}.
  *
  * @param <B> the type of the builder.
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface MqttClientSslConfigBuilderBase<B extends MqttClientSslConfigBuilderBase<B>> {
+@ApiStatus.NonExtendable
+public interface MqttTlsConfigBuilderBase<B extends MqttTlsConfigBuilderBase<B>> {
 
     /**
-     * Sets the optional user defined {@link MqttClientSslConfig#getKeyManagerFactory() key manager factory}.
+     * Sets the optional user defined {@link MqttTlsConfig#getKeyManagerFactory() key manager factory}.
      *
      * @param keyManagerFactory the key manager factory or <code>null</code> to remove any previously set key manager
      *                          factory.
@@ -48,7 +48,7 @@ public interface MqttClientSslConfigBuilderBase<B extends MqttClientSslConfigBui
     @NotNull B keyManagerFactory(@Nullable KeyManagerFactory keyManagerFactory);
 
     /**
-     * Sets the optional user defined {@link MqttClientSslConfig#getTrustManagerFactory() trust manager factory}.
+     * Sets the optional user defined {@link MqttTlsConfig#getTrustManagerFactory() trust manager factory}.
      *
      * @param trustManagerFactory the trust manager factory or <code>null</code> to remove any previously set trust
      *                            manager factory
@@ -58,7 +58,7 @@ public interface MqttClientSslConfigBuilderBase<B extends MqttClientSslConfigBui
     @NotNull B trustManagerFactory(@Nullable TrustManagerFactory trustManagerFactory);
 
     /**
-     * Sets the optional user defined {@link MqttClientSslConfig#getCipherSuites() cipher suites}.
+     * Sets the optional user defined {@link MqttTlsConfig#getCipherSuites() cipher suites}.
      *
      * @param cipherSuites the cipher suites or <code>null</code> to use the default cipher suites of Netty (network
      *                     communication framework).
@@ -68,7 +68,7 @@ public interface MqttClientSslConfigBuilderBase<B extends MqttClientSslConfigBui
     @NotNull B cipherSuites(@Nullable Collection<@NotNull String> cipherSuites);
 
     /**
-     * Sets the optional user defined {@link MqttClientSslConfig#getProtocols() protocols}.
+     * Sets the optional user defined {@link MqttTlsConfig#getProtocols() protocols}.
      *
      * @param protocols the protocols or <code>null</code> to use the default protocols of Netty (network communication
      *                  framework).
@@ -78,11 +78,11 @@ public interface MqttClientSslConfigBuilderBase<B extends MqttClientSslConfigBui
     @NotNull B protocols(@Nullable Collection<@NotNull String> protocols);
 
     /**
-     * Sets the {@link MqttClientSslConfig#getHandshakeTimeoutMs() SSL/TLS handshake timeout}.
+     * Sets the {@link MqttTlsConfig#getHandshakeTimeoutMs() TLS handshake timeout}.
      * <p>
      * The timeout in milliseconds must be in the range: [0, {@link Integer#MAX_VALUE}].
      *
-     * @param timeout  the SSL/TLS handshake timeout or <code>0</code> to disable the timeout.
+     * @param timeout  the TLS handshake timeout or <code>0</code> to disable the timeout.
      * @param timeUnit the time unit of the given timeout (this timeout only supports millisecond precision).
      * @return the builder.
      */
@@ -90,7 +90,7 @@ public interface MqttClientSslConfigBuilderBase<B extends MqttClientSslConfigBui
     @NotNull B handshakeTimeout(long timeout, @NotNull TimeUnit timeUnit);
 
     /**
-     * Sets the optional user defined {@link MqttClientSslConfig#getHostnameVerifier() hostname verifier}.
+     * Sets the optional user defined {@link MqttTlsConfig#getHostnameVerifier() hostname verifier}.
      *
      * @param hostnameVerifier the hostname verifier or <code>null</code> to use https hostname verification.
      * @return the builder.
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientTransportConfig.java b/src/main/java/com/hivemq/client2/mqtt/MqttTransportConfig.java
similarity index 65%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientTransportConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttTransportConfig.java
index f2e2a8233..ed1d8f9ad 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientTransportConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttTransportConfig.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.MqttClientTransportConfigImplBuilder;
+import com.hivemq.client2.internal.mqtt.MqttTransportConfigImplBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.net.InetSocketAddress;
 import java.util.Optional;
@@ -29,9 +30,29 @@
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface MqttClientTransportConfig {
+@ApiStatus.NonExtendable
+public interface MqttTransportConfig {
 
+    /**
+     * The default server host.
+     */
+    @NotNull String DEFAULT_SERVER_HOST = "localhost";
+    /**
+     * The default server port.
+     */
+    int DEFAULT_SERVER_PORT = 1883;
+    /**
+     * The default server port when using TLS.
+     */
+    int DEFAULT_SERVER_PORT_TLS = 8883;
+    /**
+     * The default server port when using WebSocket.
+     */
+    int DEFAULT_SERVER_PORT_WEBSOCKET = 80;
+    /**
+     * The default server port when using TLS and WebSocket.
+     */
+    int DEFAULT_SERVER_PORT_WEBSOCKET_TLS = 443;
     /**
      * The default timeout for connecting the socket to the server in milliseconds.
      *
@@ -50,8 +71,8 @@ public interface MqttClientTransportConfig {
      *
      * @return the created builder for a transport configuration.
      */
-    static @NotNull MqttClientTransportConfigBuilder builder() {
-        return new MqttClientTransportConfigImplBuilder.Default();
+    static @NotNull MqttTransportConfigBuilder builder() {
+        return new MqttTransportConfigImplBuilder.Default();
     }
 
     /**
@@ -66,9 +87,9 @@ public interface MqttClientTransportConfig {
     @NotNull Optional<InetSocketAddress> getLocalAddress();
 
     /**
-     * @return the optional secure transport configuration.
+     * @return the optional transport layer security configuration.
      */
-    @NotNull Optional<MqttClientSslConfig> getSslConfig();
+    @NotNull Optional<MqttTlsConfig> getTlsConfig();
 
     /**
      * @return the optional WebSocket transport configuration.
@@ -85,18 +106,18 @@ public interface MqttClientTransportConfig {
      * @return the timeout for connecting the socket to the server in milliseconds.
      * @since 1.2
      */
-    int getSocketConnectTimeoutMs();
+    @Range(from = 0, to = Integer.MAX_VALUE) int getSocketConnectTimeoutMs();
 
     /**
      * @return the timeout between sending the Connect and receiving the ConnAck message in milliseconds.
      * @since 1.2
      */
-    int getMqttConnectTimeoutMs();
+    @Range(from = 0, to = Integer.MAX_VALUE) int getMqttConnectTimeoutMs();
 
     /**
      * Creates a builder for extending this transport configuration.
      *
      * @return the created builder.
      */
-    @NotNull MqttClientTransportConfigBuilder extend();
+    @NotNull MqttTransportConfigBuilder extend();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientTransportConfigBuilder.java b/src/main/java/com/hivemq/client2/mqtt/MqttTransportConfigBuilder.java
similarity index 50%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientTransportConfigBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttTransportConfigBuilder.java
index 08dbe88c5..89bfe3aca 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientTransportConfigBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttTransportConfigBuilder.java
@@ -14,42 +14,41 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * Builder for a {@link MqttClientTransportConfig}.
+ * Builder for a {@link MqttTransportConfig}.
  *
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface MqttClientTransportConfigBuilder
-        extends MqttClientTransportConfigBuilderBase<MqttClientTransportConfigBuilder> {
+@ApiStatus.NonExtendable
+public interface MqttTransportConfigBuilder extends MqttTransportConfigBuilderBase<MqttTransportConfigBuilder> {
 
     /**
-     * Builds the {@link MqttClientTransportConfig}.
+     * Builds the {@link MqttTransportConfig}.
      *
-     * @return the built {@link MqttClientTransportConfig}.
+     * @return the built {@link MqttTransportConfig}.
      */
     @CheckReturnValue
-    @NotNull MqttClientTransportConfig build();
+    @NotNull MqttTransportConfig build();
 
     /**
-     * Builder for a {@link MqttClientTransportConfig} that is applied to a parent.
+     * Builder for a {@link MqttTransportConfig} that is applied to a parent.
      *
-     * @param <P> the type of the result when the built {@link MqttClientTransportConfig} is applied to the parent.
+     * @param <P> the type of the result when the built {@link MqttTransportConfig} is applied to the parent.
      */
-    @DoNotImplement
-    interface Nested<P> extends MqttClientTransportConfigBuilderBase<Nested<P>> {
+    @ApiStatus.NonExtendable
+    interface Nested<P> extends MqttTransportConfigBuilderBase<Nested<P>> {
 
         /**
-         * Builds the {@link MqttClientTransportConfig} and applies it to the parent.
+         * Builds the {@link MqttTransportConfig} and applies it to the parent.
          *
-         * @return the result when the built {@link MqttClientTransportConfig} is applied to the parent.
+         * @return the result when the built {@link MqttTransportConfig} is applied to the parent.
          */
         @NotNull P applyTransportConfig();
     }
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientTransportConfigBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/MqttTransportConfigBuilderBase.java
similarity index 70%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientTransportConfigBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttTransportConfigBuilderBase.java
index ef2840ccd..37f97a23d 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientTransportConfigBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttTransportConfigBuilderBase.java
@@ -14,29 +14,31 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.concurrent.TimeUnit;
 
 /**
- * Builder base for a {@link MqttClientTransportConfig}.
+ * Builder base for a {@link MqttTransportConfig}.
  *
  * @param <B> the type of the builder.
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface MqttClientTransportConfigBuilderBase<B extends MqttClientTransportConfigBuilderBase<B>> {
+@ApiStatus.NonExtendable
+public interface MqttTransportConfigBuilderBase<B extends MqttTransportConfigBuilderBase<B>> {
 
     /**
-     * Sets the {@link MqttClientTransportConfig#getServerAddress() server address} to connect to.
+     * Sets the {@link MqttTransportConfig#getServerAddress() server address} to connect to.
      *
      * @param address the server address.
      * @return the builder.
@@ -69,10 +71,10 @@ public interface MqttClientTransportConfigBuilderBase<B extends MqttClientTransp
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B serverPort(int port);
+    @NotNull B serverPort(@Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int port);
 
     /**
-     * Sets the optional {@link MqttClientTransportConfig#getLocalAddress() local bind address}.
+     * Sets the optional {@link MqttTransportConfig#getLocalAddress() local bind address}.
      * <p>
      * The address must be resolved.
      *
@@ -113,10 +115,10 @@ public interface MqttClientTransportConfigBuilderBase<B extends MqttClientTransp
      * @since 1.2
      */
     @CheckReturnValue
-    @NotNull B localPort(int port);
+    @NotNull B localPort(@Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int port);
 
     /**
-     * Sets the {@link MqttClientTransportConfig#getSslConfig() secure transport configuration} to the default
+     * Sets the {@link MqttTransportConfig#getTlsConfig() transport layer security configuration} to the default
      * configuration.
      * <p>
      * This means that the systems default trust store, ciphers and protocols are used.
@@ -124,41 +126,41 @@ public interface MqttClientTransportConfigBuilderBase<B extends MqttClientTransp
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B sslWithDefaultConfig();
+    @NotNull B tls();
 
     /**
-     * Sets the optional {@link MqttClientTransportConfig#getSslConfig() secure transport configuration}.
+     * Sets the optional {@link MqttTransportConfig#getTlsConfig() transport layer security configuration}.
      *
-     * @param sslConfig the secure transport configuration or <code>null</code> to remove any previously set secure
-     *                  transport configuration.
+     * @param tlsConfig the transport layer security configuration or <code>null</code> to remove any previously set
+     *                  transport layer security configuration.
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B sslConfig(@Nullable MqttClientSslConfig sslConfig);
+    @NotNull B tlsConfig(@Nullable MqttTlsConfig tlsConfig);
 
     /**
-     * Fluent counterpart of {@link #sslConfig(MqttClientSslConfig)}.
+     * Fluent counterpart of {@link #tlsConfig(MqttTlsConfig)}.
      * <p>
-     * Calling {@link MqttClientSslConfigBuilder.Nested#applySslConfig()} on the returned builder has the effect of
-     * extending the current secure transport configuration.
+     * Calling {@link MqttTlsConfigBuilder.Nested#applyTlsConfig()} on the returned builder has the effect of extending
+     * the current transport layer security configuration.
      *
-     * @return the fluent builder for the secure transport configuration.
-     * @see #sslConfig(MqttClientSslConfig)
+     * @return the fluent builder for the transport layer security configuration.
+     * @see #tlsConfig(MqttTlsConfig)
      */
     @CheckReturnValue
-    MqttClientSslConfigBuilder.@NotNull Nested<? extends B> sslConfig();
+    MqttTlsConfigBuilder.@NotNull Nested<? extends B> tlsConfigWith();
 
     /**
-     * Sets the {@link MqttClientTransportConfig#getWebSocketConfig() WebSocket transport configuration} to the default
+     * Sets the {@link MqttTransportConfig#getWebSocketConfig() WebSocket transport configuration} to the default
      * configuration.
      *
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B webSocketWithDefaultConfig();
+    @NotNull B webSocket();
 
     /**
-     * Sets the optional {@link MqttClientTransportConfig#getWebSocketConfig() WebSocket transport configuration}.
+     * Sets the optional {@link MqttTransportConfig#getWebSocketConfig() WebSocket transport configuration}.
      *
      * @param webSocketConfig the WebSocket transport configuration or <code>null</code> to remove any previously set
      *                        WebSocket transport configuration.
@@ -177,10 +179,10 @@ public interface MqttClientTransportConfigBuilderBase<B extends MqttClientTransp
      * @see #webSocketConfig(MqttWebSocketConfig)
      */
     @CheckReturnValue
-    MqttWebSocketConfigBuilder.@NotNull Nested<? extends B> webSocketConfig();
+    MqttWebSocketConfigBuilder.@NotNull Nested<? extends B> webSocketConfigWith();
 
     /**
-     * Sets the optional {@link MqttClientTransportConfig#getProxyConfig() proxy configuration}.
+     * Sets the optional {@link MqttTransportConfig#getProxyConfig() proxy configuration}.
      *
      * @param proxyConfig the proxy configuration or <code>null</code> to remove any previously set proxy
      *                    configuration.
@@ -201,10 +203,10 @@ public interface MqttClientTransportConfigBuilderBase<B extends MqttClientTransp
      * @since 1.2
      */
     @CheckReturnValue
-    MqttProxyConfigBuilder.@NotNull Nested<? extends B> proxyConfig();
+    MqttProxyConfigBuilder.@NotNull Nested<? extends B> proxyConfigWith();
 
     /**
-     * Sets the {@link MqttClientTransportConfig#getSocketConnectTimeoutMs() timeout for connecting the socket to the
+     * Sets the {@link MqttTransportConfig#getSocketConnectTimeoutMs() timeout for connecting the socket to the
      * server}.
      * <p>
      * The timeout in milliseconds must be in the range: [0, {@link Integer#MAX_VALUE}].
@@ -218,8 +220,8 @@ public interface MqttClientTransportConfigBuilderBase<B extends MqttClientTransp
     @NotNull B socketConnectTimeout(long timeout, @NotNull TimeUnit timeUnit);
 
     /**
-     * Sets the {@link MqttClientTransportConfig#getMqttConnectTimeoutMs() timeout between sending the Connect and
-     * receiving the ConnAck message}.
+     * Sets the {@link MqttTransportConfig#getMqttConnectTimeoutMs() timeout between sending the Connect and receiving
+     * the ConnAck message}.
      * <p>
      * The timeout in milliseconds must be in the range: [0, {@link Integer#MAX_VALUE}].
      *
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttVersion.java b/src/main/java/com/hivemq/client2/mqtt/MqttVersion.java
similarity index 97%
rename from src/main/java/com/hivemq/client/mqtt/MqttVersion.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttVersion.java
index d6dca9868..a30f5467e 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttVersion.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttVersion.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
 /**
  * Available MQTT versions of {@link MqttClient MQTT clients}.
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttWebSocketConfig.java b/src/main/java/com/hivemq/client2/mqtt/MqttWebSocketConfig.java
similarity index 71%
rename from src/main/java/com/hivemq/client/mqtt/MqttWebSocketConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttWebSocketConfig.java
index 41b17ff85..737fa171c 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttWebSocketConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttWebSocketConfig.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.MqttWebSocketConfigImplBuilder;
+import com.hivemq.client2.internal.mqtt.MqttWebSocketConfigImplBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 /**
  * Configuration for a WebSocket transport to use by {@link MqttClient MQTT clients}.
@@ -27,26 +28,26 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttWebSocketConfig {
 
     /**
-     * The default WebSocket server path.
+     * The default WebSocket path.
      */
-    @NotNull String DEFAULT_SERVER_PATH = "";
+    @NotNull String DEFAULT_PATH = "";
     /**
-     * The default WebSocket query string.
+     * The default WebSocket query.
      */
-    @NotNull String DEFAULT_QUERY_STRING = "";
+    @NotNull String DEFAULT_QUERY = "";
     /**
      * The default WebSocket subprotocol.
      * <p>
      * See the <a href="https://www.iana.org/assignments/websocket/websocket.xml#subprotocol-name">WebSocket Subprotocol
      * Name Registry</a>
      */
-    @NotNull String DEFAULT_MQTT_SUBPROTOCOL = "mqtt";
+    @NotNull String DEFAULT_SUBPROTOCOL = "mqtt";
     /**
-     * The default websocket handshake timeout in milliseconds.
+     * The default WebSocket handshake timeout in milliseconds.
      *
      * @since 1.2
      */
@@ -62,14 +63,14 @@ public interface MqttWebSocketConfig {
     }
 
     /**
-     * @return the WebSocket server path.
+     * @return the WebSocket path.
      */
-    @NotNull String getServerPath();
+    @NotNull String getPath();
 
     /**
-     * @return the WebSocket query string.
+     * @return the WebSocket query.
      */
-    @NotNull String getQueryString();
+    @NotNull String getQuery();
 
     /**
      * @return the WebSocket subprotocol.
@@ -77,10 +78,10 @@ public interface MqttWebSocketConfig {
     @NotNull String getSubprotocol();
 
     /**
-     * @return the websocket handshake timeout in milliseconds.
+     * @return the WebSocket handshake timeout in milliseconds.
      * @since 1.2
      */
-    int getHandshakeTimeoutMs();
+    @Range(from = 0, to = Integer.MAX_VALUE) int getHandshakeTimeoutMs();
 
     /**
      * Creates a builder for extending this WebSocket configuration.
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttWebSocketConfigBuilder.java b/src/main/java/com/hivemq/client2/mqtt/MqttWebSocketConfigBuilder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/MqttWebSocketConfigBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttWebSocketConfigBuilder.java
index 4ebde987b..beb52ecfd 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttWebSocketConfigBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttWebSocketConfigBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,7 +26,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttWebSocketConfigBuilder extends MqttWebSocketConfigBuilderBase<MqttWebSocketConfigBuilder> {
 
     /**
@@ -42,7 +42,7 @@ public interface MqttWebSocketConfigBuilder extends MqttWebSocketConfigBuilderBa
      *
      * @param <P> the type of the result when the built {@link MqttWebSocketConfig} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends MqttWebSocketConfigBuilderBase<Nested<P>> {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttWebSocketConfigBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/MqttWebSocketConfigBuilderBase.java
similarity index 75%
rename from src/main/java/com/hivemq/client/mqtt/MqttWebSocketConfigBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/MqttWebSocketConfigBuilderBase.java
index 79a0f1f82..2093b2271 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttWebSocketConfigBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/MqttWebSocketConfigBuilderBase.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.concurrent.TimeUnit;
@@ -29,26 +29,26 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttWebSocketConfigBuilderBase<B extends MqttWebSocketConfigBuilderBase<B>> {
 
     /**
-     * Sets the {@link MqttWebSocketConfig#getServerPath() server path}.
+     * Sets the {@link MqttWebSocketConfig#getPath() path}.
      *
-     * @param serverPath the server path.
+     * @param path the path.
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B serverPath(@NotNull String serverPath);
+    @NotNull B path(@NotNull String path);
 
     /**
-     * Sets the {@link MqttWebSocketConfig#getQueryString() query string}.
+     * Sets the {@link MqttWebSocketConfig#getQuery() query}.
      *
-     * @param queryString the query string.
+     * @param query the query.
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B queryString(@NotNull String queryString);
+    @NotNull B query(@NotNull String query);
 
     /**
      * Sets the {@link MqttWebSocketConfig#getSubprotocol() subprotocol}.
@@ -60,11 +60,11 @@ public interface MqttWebSocketConfigBuilderBase<B extends MqttWebSocketConfigBui
     @NotNull B subprotocol(@NotNull String subprotocol);
 
     /**
-     * Sets the {@link MqttWebSocketConfig#getHandshakeTimeoutMs() websocket handshake timeout}.
+     * Sets the {@link MqttWebSocketConfig#getHandshakeTimeoutMs() WebSocket handshake timeout}.
      * <p>
      * The timeout in milliseconds must be in the range: [0, {@link Integer#MAX_VALUE}].
      *
-     * @param timeout  the websocket handshake timeout or <code>0</code> to disable the timeout.
+     * @param timeout  the WebSocket handshake timeout or <code>0</code> to disable the timeout.
      * @param timeUnit the time unit of the given timeout (this timeout only supports millisecond precision).
      * @return the builder.
      * @since 1.2
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttClientIdentifier.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttClientIdentifier.java
similarity index 90%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttClientIdentifier.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttClientIdentifier.java
index 15d0c47e7..3c2075872 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttClientIdentifier.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttClientIdentifier.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.datatypes.MqttClientIdentifierImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttClientIdentifierImpl;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttClientIdentifier extends MqttUtf8String {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttQos.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttQos.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttQos.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttQos.java
index f4d21d4e0..e736ef0ab 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttQos.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttQos.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 /**
  * MQTT Quality of Service (QoS) according to the MQTT specification.
@@ -45,7 +46,7 @@ public enum MqttQos {
     /**
      * @return the byte code of this QoS.
      */
-    public int getCode() {
+    public @Range(from = 0, to = 2) int getCode() {
         return ordinal();
     }
 
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttSharedTopicFilter.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttSharedTopicFilter.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttSharedTopicFilter.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttSharedTopicFilter.java
index b5bec5938..2904eeb9a 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttSharedTopicFilter.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttSharedTopicFilter.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.datatypes.MqttSharedTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttSharedTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -39,7 +39,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttSharedTopicFilter extends MqttTopicFilter {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttSharedTopicFilterBuilder.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttSharedTopicFilterBuilder.java
similarity index 90%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttSharedTopicFilterBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttSharedTopicFilterBuilder.java
index 2948a92d7..adfb082fb 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttSharedTopicFilterBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttSharedTopicFilterBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -27,7 +27,7 @@
  * @since 1.0
  */
 // @formatter:off
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttSharedTopicFilterBuilder extends
         MqttTopicFilterBuilderBase.SharedBase<
                 MqttSharedTopicFilterBuilder, MqttSharedTopicFilterBuilder.Complete, MqttSharedTopicFilterBuilder.End> {
@@ -37,7 +37,7 @@ public interface MqttSharedTopicFilterBuilder extends
      * {@link MqttSharedTopicFilterBuilder} that is complete which means all mandatory fields are set.
      */
     // @formatter:off
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete extends MqttSharedTopicFilterBuilder, MqttSharedTopicFilterBuilder.End,
             MqttTopicFilterBuilderBase.SharedBase.Complete<
                     MqttSharedTopicFilterBuilder, MqttSharedTopicFilterBuilder.Complete,
@@ -47,7 +47,7 @@ interface Complete extends MqttSharedTopicFilterBuilder, MqttSharedTopicFilterBu
     /**
      * End of a {@link MqttSharedTopicFilterBuilder} that does not allow to add any more levels or wildcards.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface End extends MqttTopicFilterBuilderBase.End {
 
         /**
@@ -64,7 +64,7 @@ interface End extends MqttTopicFilterBuilderBase.End {
      *
      * @param <P> the type of the result when the built {@link MqttSharedTopicFilter} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends MqttTopicFilterBuilderBase.SharedBase<Nested<P>, Nested.Complete<P>, Nested.End<P>> {
 
         /**
@@ -72,14 +72,14 @@ interface Nested<P> extends MqttTopicFilterBuilderBase.SharedBase<Nested<P>, Nes
          *
          * @param <P> the type of the result when the built {@link MqttTopicFilter} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Nested.End<P>,
                 MqttTopicFilterBuilderBase.SharedBase.Complete<Nested<P>, Nested.Complete<P>, Nested.End<P>> {}
 
         /**
          * End of a {@link Nested} that does not allow to add any more levels or wildcards.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface End<P> extends MqttTopicFilterBuilderBase.End {
 
             /**
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopic.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopic.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopic.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopic.java
index 75e6ce1d6..1529a1d97 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopic.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopic.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicImplBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.List;
 
@@ -37,7 +37,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttTopic extends MqttUtf8String {
 
     /**
@@ -68,7 +68,7 @@ public interface MqttTopic extends MqttUtf8String {
     /**
      * @return the levels of this Topic Name.
      */
-    @Immutable @NotNull List<@NotNull String> getLevels();
+    @Unmodifiable @NotNull List<@NotNull String> getLevels();
 
     /**
      * @return a Topic Filter matching only this Topic Name.
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicBuilder.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicBuilder.java
similarity index 88%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicBuilder.java
index 4d55e5a89..7a21ae885 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,7 +26,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttTopicBuilder extends MqttTopicBuilderBase<MqttTopicBuilder.Complete> {
 
     /**
@@ -49,8 +49,8 @@ public interface MqttTopicBuilder extends MqttTopicBuilderBase<MqttTopicBuilder.
     /**
      * {@link MqttTopicBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
-    interface Complete extends MqttTopicBuilder, MqttTopicBuilderBase<MqttTopicBuilder.Complete> {
+    @ApiStatus.NonExtendable
+    interface Complete extends MqttTopicBuilder, MqttTopicBuilderBase.Complete<MqttTopicBuilder.Complete> {
 
         /**
          * Builds the {@link MqttTopic}.
@@ -66,7 +66,7 @@ interface Complete extends MqttTopicBuilder, MqttTopicBuilderBase<MqttTopicBuild
      *
      * @param <P> the type of the result when the built {@link MqttTopic} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends MqttTopicBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -74,8 +74,8 @@ interface Nested<P> extends MqttTopicBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link MqttTopic} is applied to the parent.
          */
-        @DoNotImplement
-        interface Complete<P> extends Nested<P>, MqttTopicBuilderBase<Nested.Complete<P>> {
+        @ApiStatus.NonExtendable
+        interface Complete<P> extends Nested<P>, MqttTopicBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
              * Builds the {@link MqttTopic} and applies it to the parent.
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicBuilderBase.java
similarity index 72%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicBuilderBase.java
index 6686f9b6b..ae3f8d5a3 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicBuilderBase.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -27,8 +27,8 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface MqttTopicBuilderBase<C extends MqttTopicBuilderBase<C>> {
+@ApiStatus.NonExtendable
+public interface MqttTopicBuilderBase<C extends MqttTopicBuilderBase.Complete<C>> {
 
     /**
      * Adds a {@link MqttTopic#getLevels() Topic level}.
@@ -38,4 +38,10 @@ public interface MqttTopicBuilderBase<C extends MqttTopicBuilderBase<C>> {
      */
     @CheckReturnValue
     @NotNull C addLevel(@NotNull String topicLevel);
+
+    /**
+     * {@link MqttTopicBuilderBase} that is complete which means all mandatory fields are set.
+     */
+    @ApiStatus.NonExtendable
+    interface Complete<C extends MqttTopicBuilderBase.Complete<C>> extends MqttTopicBuilderBase<C> {}
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicFilter.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicFilter.java
similarity index 90%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicFilter.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicFilter.java
index c88051899..681a675b3 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicFilter.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicFilter.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImplBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.List;
 
@@ -37,7 +37,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttTopicFilter extends MqttUtf8String {
 
     /**
@@ -72,7 +72,7 @@ public interface MqttTopicFilter extends MqttUtf8String {
     /**
      * @return the levels of this Topic Filter.
      */
-    @Immutable @NotNull List<@NotNull String> getLevels();
+    @Unmodifiable @NotNull List<@NotNull String> getLevels();
 
     /**
      * @return whether this Topic Filter contains wildcards.
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicFilterBuilder.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicFilterBuilder.java
similarity index 91%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicFilterBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicFilterBuilder.java
index 5d8770249..2d056f4d7 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicFilterBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicFilterBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -27,7 +27,7 @@
  * @since 1.0
  */
 // @formatter:off
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttTopicFilterBuilder extends
         MqttTopicFilterBuilderBase<
                 MqttTopicFilterBuilder.Complete, MqttTopicFilterBuilder.End, MqttSharedTopicFilterBuilder,
@@ -38,7 +38,7 @@ public interface MqttTopicFilterBuilder extends
      * {@link MqttTopicFilterBuilder} that is complete which means all mandatory fields are set.
      */
     // @formatter:off
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete extends MqttTopicFilterBuilder, MqttTopicFilterBuilder.End,
             MqttTopicFilterBuilderBase.Complete<
                     MqttTopicFilterBuilder.Complete, MqttTopicFilterBuilder.End, MqttSharedTopicFilterBuilder,
@@ -48,7 +48,7 @@ interface Complete extends MqttTopicFilterBuilder, MqttTopicFilterBuilder.End,
     /**
      * End of a {@link MqttTopicFilterBuilder} that does not allow to add any more levels or wildcards.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface End extends MqttTopicFilterBuilderBase.End {
 
         /**
@@ -66,7 +66,7 @@ interface End extends MqttTopicFilterBuilderBase.End {
      * @param <P> the type of the result when the built {@link MqttTopicFilter} is applied to the parent.
      */
     // @formatter:off
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends
             MqttTopicFilterBuilderBase<
                     Nested.Complete<P>, Nested.End<P>, MqttSharedTopicFilterBuilder.Nested<P>,
@@ -79,7 +79,7 @@ interface Nested<P> extends
          * @param <P> the type of the result when the built {@link MqttTopicFilter} is applied to the parent.
          */
         // @formatter:off
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Nested.End<P>,
                 MqttTopicFilterBuilderBase.Complete<
                         Nested.Complete<P>, Nested.End<P>, MqttSharedTopicFilterBuilder.Nested<P>,
@@ -89,7 +89,7 @@ interface Complete<P> extends Nested<P>, Nested.End<P>,
         /**
          * End of a {@link Nested} that does not allow to add any more levels or wildcards.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface End<P> extends MqttTopicFilterBuilderBase.End {
 
             /**
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicFilterBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicFilterBuilderBase.java
similarity index 94%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicFilterBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicFilterBuilderBase.java
index 4642ba8bb..7f8dc1a2d 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttTopicFilterBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttTopicFilterBuilderBase.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -32,7 +32,7 @@
  * @since 1.0
  */
 // @formatter:off
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttTopicFilterBuilderBase<
         C extends MqttTopicFilterBuilderBase<C, E, S, SC, SE>,
         E extends MqttTopicFilterBuilderBase.End,
@@ -85,7 +85,7 @@ public interface MqttTopicFilterBuilderBase<
      * @param <SE> the type of the end builder for a {@link MqttSharedTopicFilter}.
      */
     // @formatter:off
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete<
             C extends MqttTopicFilterBuilderBase<C, E, S, SC, SE>,
             E extends MqttTopicFilterBuilderBase.End,
@@ -109,7 +109,7 @@ interface Complete<
     /**
      * End of a {@link MqttTopicFilterBuilderBase} that does not allow to add any more levels or wildcards.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface End {}
 
     /**
@@ -120,7 +120,7 @@ interface End {}
      * @param <SE> the type of the end builder.
      */
     // @formatter:off
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface SharedBase<
             S extends SharedBase<S, SC, SE>,
             SC extends S,
@@ -136,7 +136,7 @@ interface SharedBase<
          * @param <SE> the type of the end builder.
          */
         // @formatter:off
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<
                 S extends SharedBase<S, SC, SE>,
                 SC extends S,
diff --git a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttUtf8String.java b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttUtf8String.java
similarity index 93%
rename from src/main/java/com/hivemq/client/mqtt/datatypes/MqttUtf8String.java
rename to src/main/java/com/hivemq/client2/mqtt/datatypes/MqttUtf8String.java
index 4bbe55ea9..d3894cb06 100644
--- a/src/main/java/com/hivemq/client/mqtt/datatypes/MqttUtf8String.java
+++ b/src/main/java/com/hivemq/client2/mqtt/datatypes/MqttUtf8String.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.nio.ByteBuffer;
@@ -45,7 +45,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface MqttUtf8String extends Comparable<MqttUtf8String> {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/exceptions/ConnectionClosedException.java b/src/main/java/com/hivemq/client2/mqtt/exceptions/ConnectionClosedException.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/exceptions/ConnectionClosedException.java
rename to src/main/java/com/hivemq/client2/mqtt/exceptions/ConnectionClosedException.java
index 49a97ab92..68b17af68 100644
--- a/src/main/java/com/hivemq/client/mqtt/exceptions/ConnectionClosedException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/exceptions/ConnectionClosedException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/exceptions/ConnectionFailedException.java b/src/main/java/com/hivemq/client2/mqtt/exceptions/ConnectionFailedException.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/exceptions/ConnectionFailedException.java
rename to src/main/java/com/hivemq/client2/mqtt/exceptions/ConnectionFailedException.java
index 3c2e0ee3b..f37d94259 100644
--- a/src/main/java/com/hivemq/client/mqtt/exceptions/ConnectionFailedException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/exceptions/ConnectionFailedException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/exceptions/MqttClientStateException.java b/src/main/java/com/hivemq/client2/mqtt/exceptions/MqttClientStateException.java
similarity index 88%
rename from src/main/java/com/hivemq/client/mqtt/exceptions/MqttClientStateException.java
rename to src/main/java/com/hivemq/client2/mqtt/exceptions/MqttClientStateException.java
index fe4b71a86..a7a9519fd 100644
--- a/src/main/java/com/hivemq/client/mqtt/exceptions/MqttClientStateException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/exceptions/MqttClientStateException.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * Exception that is used if an operation is called on an {@link com.hivemq.client.mqtt.MqttClient MqttClient} that is
+ * Exception that is used if an operation is called on an {@link com.hivemq.client2.mqtt.MqttClient MqttClient} that is
  * not possible in its current state, e.g. a client can not publish if it is not connected.
  *
  * @author Silvio Giebl
diff --git a/src/main/java/com/hivemq/client/mqtt/exceptions/MqttDecodeException.java b/src/main/java/com/hivemq/client2/mqtt/exceptions/MqttDecodeException.java
similarity index 91%
rename from src/main/java/com/hivemq/client/mqtt/exceptions/MqttDecodeException.java
rename to src/main/java/com/hivemq/client2/mqtt/exceptions/MqttDecodeException.java
index 2903b934b..fad255b62 100644
--- a/src/main/java/com/hivemq/client/mqtt/exceptions/MqttDecodeException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/exceptions/MqttDecodeException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/exceptions/MqttEncodeException.java b/src/main/java/com/hivemq/client2/mqtt/exceptions/MqttEncodeException.java
similarity index 91%
rename from src/main/java/com/hivemq/client/mqtt/exceptions/MqttEncodeException.java
rename to src/main/java/com/hivemq/client2/mqtt/exceptions/MqttEncodeException.java
index dc47b0401..56eed0d28 100644
--- a/src/main/java/com/hivemq/client/mqtt/exceptions/MqttEncodeException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/exceptions/MqttEncodeException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/exceptions/MqttSessionExpiredException.java b/src/main/java/com/hivemq/client2/mqtt/exceptions/MqttSessionExpiredException.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/exceptions/MqttSessionExpiredException.java
rename to src/main/java/com/hivemq/client2/mqtt/exceptions/MqttSessionExpiredException.java
index 61c3be34f..a3d992323 100644
--- a/src/main/java/com/hivemq/client/mqtt/exceptions/MqttSessionExpiredException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/exceptions/MqttSessionExpiredException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientAutoReconnect.java b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttAutoReconnect.java
similarity index 77%
rename from src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientAutoReconnect.java
rename to src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttAutoReconnect.java
index baf73dff4..acb654549 100644
--- a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientAutoReconnect.java
+++ b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttAutoReconnect.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.lifecycle;
+package com.hivemq.client2.mqtt.lifecycle;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.lifecycle.MqttClientAutoReconnectImplBuilder;
+import com.hivemq.client2.internal.mqtt.lifecycle.MqttAutoReconnectImplBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.util.concurrent.TimeUnit;
 
@@ -31,8 +32,8 @@
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface MqttClientAutoReconnect extends MqttClientDisconnectedListener {
+@ApiStatus.NonExtendable
+public interface MqttAutoReconnect extends MqttDisconnectedListener {
 
     /**
      * The default initial delay in seconds the client will wait before it tries to reconnect.
@@ -49,8 +50,8 @@ public interface MqttClientAutoReconnect extends MqttClientDisconnectedListener
      *
      * @return the created builder for an automatic reconnect strategy.
      */
-    static @NotNull MqttClientAutoReconnectBuilder builder() {
-        return new MqttClientAutoReconnectImplBuilder.Default();
+    static @NotNull MqttAutoReconnectBuilder builder() {
+        return new MqttAutoReconnectImplBuilder.Default();
     }
 
     /**
@@ -61,7 +62,7 @@ public interface MqttClientAutoReconnect extends MqttClientDisconnectedListener
      * @param timeUnit the time unit of the returned initial delay.
      * @return the start delay in the given time unit.
      */
-    long getInitialDelay(@NotNull TimeUnit timeUnit);
+    @Range(from = 1, to = Long.MAX_VALUE) long getInitialDelay(@NotNull TimeUnit timeUnit);
 
     /**
      * Returns the maximum delay the client will wait before it tries to reconnect.
@@ -69,12 +70,12 @@ public interface MqttClientAutoReconnect extends MqttClientDisconnectedListener
      * @param timeUnit the time unit of the returned maximum delay.
      * @return the maximum delay in the given time unit.
      */
-    long getMaxDelay(@NotNull TimeUnit timeUnit);
+    @Range(from = 0, to = Long.MAX_VALUE) long getMaxDelay(@NotNull TimeUnit timeUnit);
 
     /**
      * Creates a builder for extending this automatic reconnect strategy.
      *
      * @return the created builder.
      */
-    @NotNull MqttClientAutoReconnectBuilder extend();
+    @NotNull MqttAutoReconnectBuilder extend();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientAutoReconnectBuilder.java b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttAutoReconnectBuilder.java
similarity index 50%
rename from src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientAutoReconnectBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttAutoReconnectBuilder.java
index 14796aa56..ce46e135f 100644
--- a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientAutoReconnectBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttAutoReconnectBuilder.java
@@ -14,42 +14,41 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.lifecycle;
+package com.hivemq.client2.mqtt.lifecycle;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * Builder for a {@link MqttClientAutoReconnect}.
+ * Builder for a {@link MqttAutoReconnect}.
  *
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface MqttClientAutoReconnectBuilder
-        extends MqttClientAutoReconnectBuilderBase<MqttClientAutoReconnectBuilder> {
+@ApiStatus.NonExtendable
+public interface MqttAutoReconnectBuilder extends MqttAutoReconnectBuilderBase<MqttAutoReconnectBuilder> {
 
     /**
-     * Builds the {@link MqttClientAutoReconnect}.
+     * Builds the {@link MqttAutoReconnect}.
      *
-     * @return the built {@link MqttClientAutoReconnect}.
+     * @return the built {@link MqttAutoReconnect}.
      */
     @CheckReturnValue
-    @NotNull MqttClientAutoReconnect build();
+    @NotNull MqttAutoReconnect build();
 
     /**
-     * Builder for a {@link MqttClientAutoReconnect} that is applied to a parent.
+     * Builder for a {@link MqttAutoReconnect} that is applied to a parent.
      *
-     * @param <P> the type of the result when the built {@link MqttClientAutoReconnect} is applied to the parent.
+     * @param <P> the type of the result when the built {@link MqttAutoReconnect} is applied to the parent.
      */
-    @DoNotImplement
-    interface Nested<P> extends MqttClientAutoReconnectBuilderBase<Nested<P>> {
+    @ApiStatus.NonExtendable
+    interface Nested<P> extends MqttAutoReconnectBuilderBase<Nested<P>> {
 
         /**
-         * Builds the {@link MqttClientAutoReconnect} and applies it to the parent.
+         * Builds the {@link MqttAutoReconnect} and applies it to the parent.
          *
-         * @return the result when the built {@link MqttClientAutoReconnect} is applied to the parent.
+         * @return the result when the built {@link MqttAutoReconnect} is applied to the parent.
          */
         @NotNull P applyAutomaticReconnect();
     }
diff --git a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientAutoReconnectBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttAutoReconnectBuilderBase.java
similarity index 70%
rename from src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientAutoReconnectBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttAutoReconnectBuilderBase.java
index 23e4ef3eb..07c263b5b 100644
--- a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientAutoReconnectBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttAutoReconnectBuilderBase.java
@@ -14,23 +14,24 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.lifecycle;
+package com.hivemq.client2.mqtt.lifecycle;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.util.concurrent.TimeUnit;
 
 /**
- * Builder base for a {@link MqttClientAutoReconnect}.
+ * Builder base for a {@link MqttAutoReconnect}.
  *
  * @param <B> the type of the builder.
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface MqttClientAutoReconnectBuilderBase<B extends MqttClientAutoReconnectBuilderBase<B>> {
+@ApiStatus.NonExtendable
+public interface MqttAutoReconnectBuilderBase<B extends MqttAutoReconnectBuilderBase<B>> {
 
     /**
      * Sets the initial delay the client will wait before it tries to reconnect.
@@ -42,7 +43,7 @@ public interface MqttClientAutoReconnectBuilderBase<B extends MqttClientAutoReco
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B initialDelay(final long initialDelay, @NotNull TimeUnit timeUnit);
+    @NotNull B initialDelay(final @Range(from = 1, to = Long.MAX_VALUE) long initialDelay, @NotNull TimeUnit timeUnit);
 
     /**
      * Sets the maximum delay the client will wait before it tries to reconnect.
@@ -54,5 +55,5 @@ public interface MqttClientAutoReconnectBuilderBase<B extends MqttClientAutoReco
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B maxDelay(final long maxDelay, @NotNull TimeUnit timeUnit);
+    @NotNull B maxDelay(final @Range(from = 0, to = Long.MAX_VALUE) long maxDelay, @NotNull TimeUnit timeUnit);
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientConnectedContext.java b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttConnectedContext.java
similarity index 81%
rename from src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientConnectedContext.java
rename to src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttConnectedContext.java
index a550021f5..f0b23b45e 100644
--- a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientConnectedContext.java
+++ b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttConnectedContext.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.lifecycle;
+package com.hivemq.client2.mqtt.lifecycle;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientConfig;
+import com.hivemq.client2.mqtt.MqttClientConfig;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,8 +26,8 @@
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface MqttClientConnectedContext {
+@ApiStatus.NonExtendable
+public interface MqttConnectedContext {
 
     /**
      * @return the config of the client that is now connected.
diff --git a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientConnectedListener.java b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttConnectedListener.java
similarity index 83%
rename from src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientConnectedListener.java
rename to src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttConnectedListener.java
index 3a79f8793..af5cf3ac5 100644
--- a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientConnectedListener.java
+++ b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttConnectedListener.java
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.lifecycle;
+package com.hivemq.client2.mqtt.lifecycle;
 
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -24,8 +25,9 @@
  * @author Silvio Giebl
  * @since 1.1
  */
+@ApiStatus.OverrideOnly
 @FunctionalInterface
-public interface MqttClientConnectedListener {
+public interface MqttConnectedListener {
 
     /**
      * Listener method which is notified when a client is connected (a successful ConnAck message is received).
@@ -34,5 +36,5 @@ public interface MqttClientConnectedListener {
      *
      * @param context provides context about the client that is now connected.
      */
-    void onConnected(@NotNull MqttClientConnectedContext context);
+    void onConnected(@NotNull MqttConnectedContext context);
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttDisconnectSource.java b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttDisconnectSource.java
similarity index 97%
rename from src/main/java/com/hivemq/client/mqtt/lifecycle/MqttDisconnectSource.java
rename to src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttDisconnectSource.java
index e1f4eece5..df4f95334 100644
--- a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttDisconnectSource.java
+++ b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttDisconnectSource.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.lifecycle;
+package com.hivemq.client2.mqtt.lifecycle;
 
 /**
  * Source which triggers disconnection.
diff --git a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientDisconnectedContext.java b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttDisconnectedContext.java
similarity index 71%
rename from src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientDisconnectedContext.java
rename to src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttDisconnectedContext.java
index cc0a46190..25c47e4ca 100644
--- a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientDisconnectedContext.java
+++ b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttDisconnectedContext.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.lifecycle;
+package com.hivemq.client2.mqtt.lifecycle;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientConfig;
+import com.hivemq.client2.mqtt.MqttClientConfig;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,8 +26,8 @@
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface MqttClientDisconnectedContext {
+@ApiStatus.NonExtendable
+public interface MqttDisconnectedContext {
 
     /**
      * @return the config of the client that is now disconnected.
@@ -44,17 +44,17 @@ public interface MqttClientDisconnectedContext {
      * <p>
      * This can be:
      * <ul>
-     *   <li>{@link com.hivemq.client.mqtt.exceptions.ConnectionFailedException ConnectionFailedException} if a connect
+     *   <li>{@link com.hivemq.client2.mqtt.exceptions.ConnectionFailedException ConnectionFailedException} if a connect
      *     attempt failed
-     *   <li>{@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3ConnAckException Mqtt3ConnAckException} or {@link
-     *     com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException Mqtt5ConnAckException} (depending on the MQTT
+     *   <li>{@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3ConnAckException Mqtt3ConnAckException} or {@link
+     *     com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5ConnAckException Mqtt5ConnAckException} (depending on the MQTT
      *     version of the client) if the ConnAck message contained an error code, which means that the connect was
      *     rejected
-     *   <li>{@link com.hivemq.client.mqtt.exceptions.ConnectionClosedException ConnectionClosedException} if the
+     *   <li>{@link com.hivemq.client2.mqtt.exceptions.ConnectionClosedException ConnectionClosedException} if the
      *     connection was closed without sending a Disconnect message (use {@link #getSource()} to determine if the
      *     server or the client closed the connection)
-     *   <li>{@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3DisconnectException Mqtt3DisconnectException} or {@link
-     *     com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5DisconnectException Mqtt5DisconnectException} (depending on the
+     *   <li>{@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3DisconnectException Mqtt3DisconnectException} or {@link
+     *     com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5DisconnectException Mqtt5DisconnectException} (depending on the
      *     MQTT version of the client) if the connection was closed with a Disconnect message (use {@link #getSource()}
      *     to determine if the server, the user or the client sent the Disconnect message)
      * </ul>
@@ -75,5 +75,5 @@ public interface MqttClientDisconnectedContext {
     /**
      * @return the reconnector which can be used for reconnecting.
      */
-    @NotNull MqttClientReconnector getReconnector();
+    @NotNull MqttReconnector getReconnector();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientDisconnectedListener.java b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttDisconnectedListener.java
similarity index 64%
rename from src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientDisconnectedListener.java
rename to src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttDisconnectedListener.java
index a1c0a5ed1..c944a763f 100644
--- a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientDisconnectedListener.java
+++ b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttDisconnectedListener.java
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.lifecycle;
+package com.hivemq.client2.mqtt.lifecycle;
 
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -25,34 +26,35 @@
  * @author Silvio Giebl
  * @since 1.1
  */
+@ApiStatus.OverrideOnly
 @FunctionalInterface
-public interface MqttClientDisconnectedListener {
+public interface MqttDisconnectedListener {
 
     /**
      * Listener method which is notified in the following cases:
      * <ul>
      *   <li>A client was disconnected (with or without a Disconnect message, by the server, client or user) or the
-     *     connection failed. The client state will still be {@link com.hivemq.client.mqtt.MqttClientState#CONNECTED
-     *     CONNECTED} and the {@link com.hivemq.client.mqtt.MqttClientConnectionConfig MqttClientConnectionConfig} will
+     *     connection failed. The client state will still be {@link com.hivemq.client2.mqtt.MqttClientState#CONNECTED
+     *     CONNECTED} and the {@link com.hivemq.client2.mqtt.MqttClientConnectionConfig MqttClientConnectionConfig} will
      *     still be present.
      *   <li>A connect attempt by the user failed. The client state will still be
-     *     {@link com.hivemq.client.mqtt.MqttClientState#CONNECTING CONNECTING}.
+     *     {@link com.hivemq.client2.mqtt.MqttClientState#CONNECTING CONNECTING}.
      *   <li>A reconnect attempt by the client failed. The client state will still be
-     *     {@link com.hivemq.client.mqtt.MqttClientState#CONNECTING_RECONNECT CONNECTING_RECONNECT}.
+     *     {@link com.hivemq.client2.mqtt.MqttClientState#CONNECTING_RECONNECT CONNECTING_RECONNECT}.
      * </ul>
-     * The client state will be updated after all {@link MqttClientDisconnectedListener MqttClientDisconnectedListeners}
+     * The client state will be updated after all {@link MqttDisconnectedListener}s
      * are called to
      * <ul>
-     *   <li>{@link com.hivemq.client.mqtt.MqttClientState#DISCONNECTED DISCONNECTED} or
-     *   <li>{@link com.hivemq.client.mqtt.MqttClientState#DISCONNECTED_RECONNECT DISCONNECTED_RECONNECT} if the client
+     *   <li>{@link com.hivemq.client2.mqtt.MqttClientState#DISCONNECTED DISCONNECTED} or
+     *   <li>{@link com.hivemq.client2.mqtt.MqttClientState#DISCONNECTED_RECONNECT DISCONNECTED_RECONNECT} if the client
      *     is instructed to reconnect.
      * </ul>
      * <p>
      * This method must not block. If you want to reconnect you have to use the supplied {@link
-     * MqttClientDisconnectedContext#getReconnector()}.
+     * MqttDisconnectedContext#getReconnector()}.
      *
      * @param context provides context about the client that is now disconnected, the cause for disconnection and allows
      *                reconnecting.
      */
-    void onDisconnected(@NotNull MqttClientDisconnectedContext context);
+    void onDisconnected(@NotNull MqttDisconnectedContext context);
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientReconnector.java b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttReconnector.java
similarity index 65%
rename from src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientReconnector.java
rename to src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttReconnector.java
index 584471935..f2944e871 100644
--- a/src/main/java/com/hivemq/client/mqtt/lifecycle/MqttClientReconnector.java
+++ b/src/main/java/com/hivemq/client2/mqtt/lifecycle/MqttReconnector.java
@@ -14,33 +14,34 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.lifecycle;
+package com.hivemq.client2.mqtt.lifecycle;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientTransportConfig;
-import com.hivemq.client.mqtt.MqttClientTransportConfigBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttTransportConfig;
+import com.hivemq.client2.mqtt.MqttTransportConfigBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.function.BiConsumer;
 
 /**
- * A reconnector is supplied by a {@link MqttClientDisconnectedContext} and can be used for reconnecting.
+ * A reconnector is supplied by a {@link MqttDisconnectedContext} and can be used for reconnecting.
  * <p>
  * The client will reconnect only if at least one of the methods {@link #reconnect(boolean)} or {@link
  * #reconnectWhen(CompletableFuture, BiConsumer)} is called.
  * <p>
- * All methods must only be called in {@link MqttClientDisconnectedListener#onDisconnected(MqttClientDisconnectedContext)}.
- * Some methods can also be called in the callback supplied to {@link #reconnectWhen(CompletableFuture, BiConsumer)}.
+ * All methods must only be called in {@link MqttDisconnectedListener#onDisconnected(MqttDisconnectedContext)}. Some
+ * methods can also be called in the callback supplied to {@link #reconnectWhen(CompletableFuture, BiConsumer)}.
  *
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface MqttClientReconnector {
+@ApiStatus.NonExtendable
+public interface MqttReconnector {
 
     /**
      * If reconnect is enabled by default.
@@ -70,7 +71,7 @@ public interface MqttClientReconnector {
     /**
      * @return the number of failed connection attempts.
      */
-    int getAttempts();
+    @Range(from = 0, to = Integer.MAX_VALUE) int getAttempts();
 
     /**
      * Instructs the client to reconnect or not.
@@ -78,7 +79,7 @@ public interface MqttClientReconnector {
      * @param reconnect whether to reconnect.
      * @return this reconnector.
      */
-    @NotNull MqttClientReconnector reconnect(boolean reconnect);
+    @NotNull MqttReconnector reconnect(boolean reconnect);
 
     /**
      * Instructs the client to reconnect after a future completes.
@@ -86,17 +87,17 @@ public interface MqttClientReconnector {
      * If additionally a {@link #delay(long, TimeUnit) delay} is supplied, the client will reconnect after both are
      * complete.
      * <p>
-     * This method must only be called in {@link MqttClientDisconnectedListener#onDisconnected(MqttClientDisconnectedContext)}
-     * and not in the supplied callback.
+     * This method must only be called in {@link MqttDisconnectedListener#onDisconnected(MqttDisconnectedContext)} and
+     * not in the supplied callback.
      *
      * @param future   the client will reconnect only after the future completes.
      * @param callback the callback that will be called after the future completes and before the client will reconnect.
      *                 It can be used to set new connect properties (e.g. credentials).
      * @param <T>      the result type of the future.
      * @return this reconnector.
-     * @throws UnsupportedOperationException if called outside of {@link MqttClientDisconnectedListener#onDisconnected(MqttClientDisconnectedContext)}.
+     * @throws UnsupportedOperationException if called outside of {@link MqttDisconnectedListener#onDisconnected(MqttDisconnectedContext)}.
      */
-    <T> @NotNull MqttClientReconnector reconnectWhen(
+    <T> @NotNull MqttReconnector reconnectWhen(
             @NotNull CompletableFuture<T> future, @Nullable BiConsumer<? super T, ? super Throwable> callback);
 
     /**
@@ -114,15 +115,15 @@ public interface MqttClientReconnector {
      * This setting only has effect if the client will reconnect (at least one of the methods {@link
      * #reconnect(boolean)} or {@link #reconnectWhen(CompletableFuture, BiConsumer)} is called).
      * <p>
-     * This method must only be called in {@link MqttClientDisconnectedListener#onDisconnected(MqttClientDisconnectedContext)}
-     * and not in the callback supplied to {@link #reconnectWhen(CompletableFuture, BiConsumer)}.
+     * This method must only be called in {@link MqttDisconnectedListener#onDisconnected(MqttDisconnectedContext)} and
+     * not in the callback supplied to {@link #reconnectWhen(CompletableFuture, BiConsumer)}.
      *
      * @param resubscribe whether to resubscribe when the session expired before the client reconnected successfully.
      * @return this reconnector.
-     * @throws UnsupportedOperationException if called outside of {@link MqttClientDisconnectedListener#onDisconnected(MqttClientDisconnectedContext)}.
+     * @throws UnsupportedOperationException if called outside of {@link MqttDisconnectedListener#onDisconnected(MqttDisconnectedContext)}.
      * @since 1.2
      */
-    @NotNull MqttClientReconnector resubscribeIfSessionExpired(boolean resubscribe);
+    @NotNull MqttReconnector resubscribeIfSessionExpired(boolean resubscribe);
 
     /**
      * @return whether the client will resubscribe when the session expired before it reconnected successfully.
@@ -140,15 +141,15 @@ public interface MqttClientReconnector {
      * This setting only has effect if the client will reconnect (at least one of the methods {@link
      * #reconnect(boolean)} or {@link #reconnectWhen(CompletableFuture, BiConsumer)} is called).
      * <p>
-     * This method must only be called in {@link MqttClientDisconnectedListener#onDisconnected(MqttClientDisconnectedContext)}
-     * and not in the callback supplied to {@link #reconnectWhen(CompletableFuture, BiConsumer)}.
+     * This method must only be called in {@link MqttDisconnectedListener#onDisconnected(MqttDisconnectedContext)} and
+     * not in the callback supplied to {@link #reconnectWhen(CompletableFuture, BiConsumer)}.
      *
      * @param republish whether to republish when the session expired before the client reconnected successfully.
      * @return this reconnector.
-     * @throws UnsupportedOperationException if called outside of {@link MqttClientDisconnectedListener#onDisconnected(MqttClientDisconnectedContext)}.
+     * @throws UnsupportedOperationException if called outside of {@link MqttDisconnectedListener#onDisconnected(MqttDisconnectedContext)}.
      * @since 1.2
      */
-    @NotNull MqttClientReconnector republishIfSessionExpired(boolean republish);
+    @NotNull MqttReconnector republishIfSessionExpired(boolean republish);
 
     /**
      * @return whether the client will republish when the session expired before it reconnected successfully.
@@ -165,21 +166,21 @@ public interface MqttClientReconnector {
      * If additionally a {@link #reconnectWhen(CompletableFuture, BiConsumer) future} is supplied, the client will
      * reconnect after both are complete.
      * <p>
-     * This method must only be called in {@link MqttClientDisconnectedListener#onDisconnected(MqttClientDisconnectedContext)}
-     * and not in the callback supplied to {@link #reconnectWhen(CompletableFuture, BiConsumer)}.
+     * This method must only be called in {@link MqttDisconnectedListener#onDisconnected(MqttDisconnectedContext)} and
+     * not in the callback supplied to {@link #reconnectWhen(CompletableFuture, BiConsumer)}.
      *
      * @param delay    delay which the client will wait before trying to reconnect.
      * @param timeUnit the time unit of the delay.
      * @return this reconnector.
-     * @throws UnsupportedOperationException if called outside of {@link MqttClientDisconnectedListener#onDisconnected(MqttClientDisconnectedContext)}.
+     * @throws UnsupportedOperationException if called outside of {@link MqttDisconnectedListener#onDisconnected(MqttDisconnectedContext)}.
      */
-    @NotNull MqttClientReconnector delay(long delay, @NotNull TimeUnit timeUnit);
+    @NotNull MqttReconnector delay(long delay, @NotNull TimeUnit timeUnit);
 
     /**
      * Returns the currently set delay the client will wait for before trying to reconnect.
      * <p>
      * If the {@link #delay(long, TimeUnit)} method has not been called before (including previous {@link
-     * MqttClientDisconnectedListener MqttClientDisconnectedListeners}) it will be {@link #DEFAULT_DELAY_MS}.
+     * MqttDisconnectedListener}s) it will be {@link #DEFAULT_DELAY_MS}.
      *
      * @param timeUnit the time unit of the returned delay.
      * @return the delay in the given time unit.
@@ -192,29 +193,29 @@ public interface MqttClientReconnector {
      * @param transportConfig the transport configuration the client will try to reconnect with.
      * @return this reconnector.
      */
-    @NotNull MqttClientReconnector transportConfig(@NotNull MqttClientTransportConfig transportConfig);
+    @NotNull MqttReconnector transportConfig(@NotNull MqttTransportConfig transportConfig);
 
     /**
-     * Fluent counterpart of {@link #transportConfig(MqttClientTransportConfig)}.
+     * Fluent counterpart of {@link #transportConfig(MqttTransportConfig)}.
      * <p>
-     * Calling {@link MqttClientTransportConfigBuilder.Nested#applyTransportConfig()} on the returned builder has the
-     * effect of extending the current transport configuration.
+     * Calling {@link MqttTransportConfigBuilder.Nested#applyTransportConfig()} on the returned builder has the effect
+     * of extending the current transport configuration.
      *
      * @return the fluent builder for the transport configuration.
-     * @see #transportConfig(MqttClientTransportConfig)
+     * @see #transportConfig(MqttTransportConfig)
      */
     @CheckReturnValue
-    MqttClientTransportConfigBuilder.@NotNull Nested<? extends MqttClientReconnector> transportConfig();
+    MqttTransportConfigBuilder.@NotNull Nested<? extends MqttReconnector> transportConfigWith();
 
     /**
      * Returns the currently set transport configuration the client will try to reconnect with.
      * <p>
-     * If the {@link #transportConfig(MqttClientTransportConfig)} method has not been called before (including previous
-     * {@link MqttClientDisconnectedListener MqttClientDisconnectedListeners}) it will be the transport configuration
-     * the client was connected with or the {@link com.hivemq.client.mqtt.MqttClientConfig#getTransportConfig() default
-     * transport configuration} if it has not been connected yet.
+     * If the {@link #transportConfig(MqttTransportConfig)} method has not been called before (including previous {@link
+     * MqttDisconnectedListener}s) it will be the transport configuration the client was connected with or the {@link
+     * com.hivemq.client2.mqtt.MqttClientConfig#getTransportConfig() default transport configuration} if it has not been
+     * connected yet.
      *
      * @return the transport configuration.
      */
-    @NotNull MqttClientTransportConfig getTransportConfig();
+    @NotNull MqttTransportConfig getTransportConfig();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3AsyncClient.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3AsyncClient.java
similarity index 78%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3AsyncClient.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3AsyncClient.java
index 28b12ef90..1887bf8d7 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3AsyncClient.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3AsyncClient.java
@@ -14,21 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3;
-
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilderBase;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubscribeBuilder;
+package com.hivemq.client2.mqtt.mqtt3;
+
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilderBase;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubscribeBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.concurrent.CompletableFuture;
@@ -41,7 +43,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3AsyncClient extends Mqtt3Client {
 
     /**
@@ -60,7 +62,7 @@ public interface Mqtt3AsyncClient extends Mqtt3Client {
      *         <ul>
      *           <li>completes normally with the ConnAck message if it does not contain an Error Code (connected
      *             successfully),
-     *           <li>completes exceptionally with a {@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3ConnAckException
+     *           <li>completes exceptionally with a {@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3ConnAckException
      *             Mqtt3ConnAckException} wrapping the ConnAck message if it contains an Error Code or
      *           <li>completes exceptionally with a different exception if an error occurred before the Connect message
      *             was sent or before the ConnAck message was received.
@@ -93,7 +95,7 @@ public interface Mqtt3AsyncClient extends Mqtt3Client {
      *         <ul>
      *           <li>completes normally with the SubAck message if all subscriptions of the Subscribe message were
      *             successful (the SubAck message contains no Error Codes),
-     *           <li>completes exceptionally with a {@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3SubAckException
+     *           <li>completes exceptionally with a {@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3SubAckException
      *             Mqtt3SubAckException} wrapping the SubAck message if it contains at least one Error Code or
      *           <li>completes exceptionally with a different exception if an error occurred before the Subscribe
      *             message was sent or before a SubAck message was received.
@@ -182,8 +184,8 @@ public interface Mqtt3AsyncClient extends Mqtt3Client {
      * Fluent counterpart of {@link #subscribe(Mqtt3Subscribe)}, {@link #subscribe(Mqtt3Subscribe, Consumer, boolean)}
      * and {@link #subscribe(Mqtt3Subscribe, Consumer, Executor, boolean)}.
      * <p>
-     * Calling {@link Mqtt3SubscribeAndCallbackBuilder.Complete#send()} on the returned builder has the same effect as
-     * calling one of the following methods:
+     * Calling {@link SubscribeBuilder.Complete#send()} on the returned builder has the same effect as calling one of
+     * the following methods:
      * <ul>
      *   <li>{@link #subscribe(Mqtt3Subscribe)} if no callback has been supplied to the builder
      *   <li>{@link #subscribe(Mqtt3Subscribe, Consumer)} if only a callback has been supplied to the builder
@@ -197,7 +199,7 @@ public interface Mqtt3AsyncClient extends Mqtt3Client {
      * @see #subscribe(Mqtt3Subscribe, Consumer, Executor, boolean)
      */
     @CheckReturnValue
-    Mqtt3SubscribeAndCallbackBuilder.@NotNull Start subscribeWith();
+    SubscribeBuilder.@NotNull Start subscribeWith();
 
     /**
      * Globally consumes all incoming Publish messages matching the given filter.
@@ -265,12 +267,12 @@ void publishes(
      * @param unsubscribe the Unsubscribe message sent to the broker.
      * @return a {@link CompletableFuture} which
      *         <ul>
-     *           <li>completes normally when the corresponding UnsubAck message was received or
+     *           <li>completes normally with the UnsubAck message or
      *           <li>completes exceptionally if an error occurred before the Unsubscribe message was sent or before a
      *             UnsubAck message was received.
      *         </ul>
      */
-    @NotNull CompletableFuture<Void> unsubscribe(@NotNull Mqtt3Unsubscribe unsubscribe);
+    @NotNull CompletableFuture<Mqtt3UnsubAck> unsubscribe(@NotNull Mqtt3Unsubscribe unsubscribe);
 
     /**
      * Fluent counterpart of {@link #unsubscribe(Mqtt3Unsubscribe)}.
@@ -282,7 +284,7 @@ void publishes(
      * @see #unsubscribe(Mqtt3Unsubscribe)
      */
     @CheckReturnValue
-    Mqtt3UnsubscribeBuilder.Send.@NotNull Start<CompletableFuture<Void>> unsubscribeWith();
+    Mqtt3UnsubscribeBuilder.Send.@NotNull Start<CompletableFuture<Mqtt3UnsubAck>> unsubscribeWith();
 
     /**
      * Publishes the given Publish message.
@@ -290,13 +292,13 @@ void publishes(
      * @param publish the Publish message sent to the broker.
      * @return a {@link CompletableFuture} which
      *         <ul>
-     *           <li>completes normally with the same Publish message (for context) if the Publish message was
-     *             successfully published or
+     *           <li>completes normally with the {@link Mqtt3PublishResult} if the Publish message was successfully
+     *             published ({@link Mqtt3PublishResult#getError()} will always be absent) or
      *           <li>completes exceptionally if an error occurred before the Publish message was sent or before an
      *             acknowledgement message was received.
      *         </ul>
      */
-    @NotNull CompletableFuture<@NotNull Mqtt3Publish> publish(@NotNull Mqtt3Publish publish);
+    @NotNull CompletableFuture<@NotNull Mqtt3PublishResult> publish(@NotNull Mqtt3Publish publish);
 
     /**
      * Fluent counterpart of {@link #publish(Mqtt3Publish)}.
@@ -308,7 +310,7 @@ void publishes(
      * @see #publish(Mqtt3Publish)
      */
     @CheckReturnValue
-    Mqtt3PublishBuilder.@NotNull Send<CompletableFuture<Mqtt3Publish>> publishWith();
+    Mqtt3PublishBuilder.@NotNull Send<CompletableFuture<Mqtt3PublishResult>> publishWith();
 
     /**
      * Disconnects this client.
@@ -332,38 +334,31 @@ void publishes(
      * #subscribe(Mqtt3Subscribe)}, {@link #subscribe(Mqtt3Subscribe, Consumer, boolean)} or {@link
      * #subscribe(Mqtt3Subscribe, Consumer, Executor, boolean)} call.
      */
-    @DoNotImplement
-    interface Mqtt3SubscribeAndCallbackBuilder
-            extends Mqtt3SubscribeBuilderBase<Mqtt3SubscribeAndCallbackBuilder.Complete> {
+    @ApiStatus.NonExtendable
+    interface SubscribeBuilder extends Mqtt3SubscribeBuilderBase<SubscribeBuilder.Complete> {
 
         /**
-         * {@link Mqtt3SubscribeAndCallbackBuilder} that is complete which means all mandatory fields are set.
+         * {@link SubscribeBuilder} that is complete which means all mandatory fields are set.
          */
-        @DoNotImplement
-        interface Complete extends Mqtt3SubscribeAndCallbackBuilder, Mqtt3SubscribeAndCallbackBuilder.Call,
-                Mqtt3SubscribeBuilderBase<Mqtt3SubscribeAndCallbackBuilder.Complete> {}
+        @ApiStatus.NonExtendable
+        interface Complete extends SubscribeBuilder, AfterComplete,
+                Mqtt3SubscribeBuilderBase.Complete<SubscribeBuilder.Complete> {}
 
         /**
-         * {@link Mqtt3SubscribeAndCallbackBuilder} that provides additional methods for the first subscription.
+         * {@link SubscribeBuilder} that provides additional methods for the first subscription.
          */
-        // @formatter:off
-        @DoNotImplement
-        interface Start extends Mqtt3SubscribeAndCallbackBuilder,
-                Mqtt3SubscribeBuilderBase.Start<
-                        Mqtt3SubscribeAndCallbackBuilder.Complete, Mqtt3SubscribeAndCallbackBuilder.Start.Complete> {
-        // @formatter:on
+        @ApiStatus.NonExtendable
+        interface Start extends SubscribeBuilder,
+                Mqtt3SubscribeBuilderBase.Start<SubscribeBuilder.Complete, SubscribeBuilder.Start.Complete> {
 
             /**
-             * {@link Mqtt3SubscribeAndCallbackBuilder.Start} that is complete which means all mandatory fields are
-             * set.
+             * {@link SubscribeBuilder.Start} that is complete which means all mandatory fields are set.
              */
             // @formatter:off
-            @DoNotImplement
-            interface Complete extends
-                    Mqtt3SubscribeAndCallbackBuilder.Start, Mqtt3SubscribeAndCallbackBuilder.Complete,
+            @ApiStatus.NonExtendable
+            interface Complete extends SubscribeBuilder.Start, SubscribeBuilder.Complete,
                     Mqtt3SubscribeBuilderBase.Start.Complete<
-                            Mqtt3SubscribeAndCallbackBuilder.Complete,
-                            Mqtt3SubscribeAndCallbackBuilder.Start.Complete> {}
+                            SubscribeBuilder.Complete, SubscribeBuilder.Start.Complete> {}
             // @formatter:on
         }
 
@@ -372,8 +367,8 @@ interface Complete extends
          * #subscribe(Mqtt3Subscribe, Consumer, boolean)} or {@link #subscribe(Mqtt3Subscribe, Consumer, Executor,
          * boolean)} call.
          */
-        @DoNotImplement
-        interface Call {
+        @ApiStatus.NonExtendable
+        interface AfterComplete {
 
             /**
              * Sets a callback for the matching Publish messages consumed via the subscriptions.
@@ -382,7 +377,7 @@ interface Call {
              * @return the builder.
              */
             @CheckReturnValue
-            @NotNull Ex callback(@NotNull Consumer<Mqtt3Publish> callback);
+            @NotNull AfterCallback callback(@NotNull Consumer<Mqtt3Publish> callback);
 
             /**
              * Builds the {@link Mqtt3Subscribe} and applies it and additional arguments to a {@link
@@ -393,34 +388,34 @@ interface Call {
              *         {@link #subscribe(Mqtt3Subscribe, Consumer, Executor, boolean)}.
              */
             @NotNull CompletableFuture<Mqtt3SubAck> send();
+        }
+
+        /**
+         * Builder for additional arguments alongside the {@link Mqtt3Subscribe} that are applied to a {@link
+         * #subscribe(Mqtt3Subscribe, Consumer, Executor, boolean)} call.
+         */
+        @ApiStatus.NonExtendable
+        interface AfterCallback extends AfterComplete {
+
+            /**
+             * Sets an executor to execute the callback for the matching Publish messages consumed via the
+             * subscriptions.
+             *
+             * @param executor the executor to execute the callback for the matching Publish messages.
+             * @return the builder.
+             */
+            @CheckReturnValue
+            @NotNull AfterCallback executor(@NotNull Executor executor);
 
             /**
-             * Builder for additional arguments alongside the {@link Mqtt3Subscribe} that are applied to a {@link
-             * #subscribe(Mqtt3Subscribe, Consumer, Executor, boolean)} call.
+             * Sets whether the matching Publish messages consumed via the subscriptions are acknowledged manually.
+             *
+             * @param manualAcknowledgement whether the matching Publish messages are acknowledged manually.
+             * @return the builder.
+             * @since 1.2
              */
-            @DoNotImplement
-            interface Ex extends Call {
-
-                /**
-                 * Sets an executor to execute the callback for the matching Publish messages consumed via the
-                 * subscriptions.
-                 *
-                 * @param executor the executor to execute the callback for the matching Publish messages.
-                 * @return the builder.
-                 */
-                @CheckReturnValue
-                @NotNull Ex executor(@NotNull Executor executor);
-
-                /**
-                 * Sets whether the matching Publish messages consumed via the subscriptions are acknowledged manually.
-                 *
-                 * @param manualAcknowledgement whether the matching Publish messages are acknowledged manually.
-                 * @return the builder.
-                 * @since 1.2
-                 */
-                @CheckReturnValue
-                @NotNull Ex manualAcknowledgement(boolean manualAcknowledgement);
-            }
+            @CheckReturnValue
+            @NotNull AfterCallback manualAcknowledgement(boolean manualAcknowledgement);
         }
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3BlockingClient.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3BlockingClient.java
similarity index 70%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3BlockingClient.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3BlockingClient.java
index 3dd6ddc81..97951b0ed 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3BlockingClient.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3BlockingClient.java
@@ -14,21 +14,23 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3;
-
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubscribeBuilder;
+package com.hivemq.client2.mqtt.mqtt3;
+
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubscribeBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -40,7 +42,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3BlockingClient extends Mqtt3Client {
 
     /**
@@ -56,8 +58,8 @@ public interface Mqtt3BlockingClient extends Mqtt3Client {
      *
      * @param connect the Connect message sent to the broker.
      * @return the ConnAck message if it does not contain an Error Code (connected successfully).
-     * @throws com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3ConnAckException wrapping the ConnAck message if it contains
-     *                                                                       an Error Code.
+     * @throws com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3ConnAckException wrapping the ConnAck message if it
+     *                                                                        contains an Error Code.
      */
     @NotNull Mqtt3ConnAck connect(@NotNull Mqtt3Connect connect);
 
@@ -81,8 +83,8 @@ public interface Mqtt3BlockingClient extends Mqtt3Client {
      * @param subscribe the Subscribe messages sent to the broker.
      * @return the SubAck message if all subscriptions of the Subscribe message were successful (the SubAck message
      *         contains no Error Codes).
-     * @throws com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3SubAckException wrapping the SubAck message if it contains
-     *                                                                      at least one Error Code.
+     * @throws com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3SubAckException wrapping the SubAck message if it contains
+     *                                                                       at least one Error Code.
      */
     @NotNull Mqtt3SubAck subscribe(@NotNull Mqtt3Subscribe subscribe);
 
@@ -102,61 +104,62 @@ public interface Mqtt3BlockingClient extends Mqtt3Client {
      * Globally consumes all incoming Publish messages matching the given filter.
      *
      * @param filter the filter with which all incoming Publish messages are filtered.
-     * @return a {@link Mqtt3Publishes} instance that can be used to receive the Publish messages on the calling
-     *         thread.
+     * @return a {@link Publishes} instance that can be used to receive the Publish messages on the calling thread.
      * @see #publishes(MqttGlobalPublishFilter, boolean)
      */
-    @NotNull Mqtt3Publishes publishes(final @NotNull MqttGlobalPublishFilter filter);
+    @NotNull Publishes publishes(final @NotNull MqttGlobalPublishFilter filter);
 
     /**
      * Globally consumes all incoming Publish messages matching the given filter.
      *
      * @param filter                the filter with which all incoming Publish messages are filtered.
      * @param manualAcknowledgement whether the Publish messages are acknowledged manually.
-     * @return a {@link Mqtt3Publishes} instance that can be used to receive the Publish messages on the calling
-     *         thread.
+     * @return a {@link Publishes} instance that can be used to receive the Publish messages on the calling thread.
      * @see #publishes(MqttGlobalPublishFilter)
      * @since 1.2
      */
-    @NotNull Mqtt3Publishes publishes(@NotNull MqttGlobalPublishFilter filter, boolean manualAcknowledgement);
+    @NotNull Publishes publishes(@NotNull MqttGlobalPublishFilter filter, boolean manualAcknowledgement);
 
     /**
      * Unsubscribes this client with the given Unsubscribe message.
      *
      * @param unsubscribe the Unsubscribe message sent to the broker.
+     * @return the UnsubAck message.
      */
-    void unsubscribe(@NotNull Mqtt3Unsubscribe unsubscribe);
+    @NotNull Mqtt3UnsubAck unsubscribe(@NotNull Mqtt3Unsubscribe unsubscribe);
 
     /**
      * Fluent counterpart of {@link #unsubscribe(Mqtt3Unsubscribe)}.
      * <p>
-     * Calling {@link Mqtt3UnsubscribeBuilder.SendVoid.Complete#send()} on the returned builder has the same effect as
+     * Calling {@link Mqtt3UnsubscribeBuilder.Send.Complete#send()} on the returned builder has the same effect as
      * calling {@link #unsubscribe(Mqtt3Unsubscribe)} with the result of {@link Mqtt3UnsubscribeBuilder.Complete#build()}.
      *
      * @return the fluent builder for the Unsubscribe message.
      * @see #unsubscribe(Mqtt3Unsubscribe)
      */
     @CheckReturnValue
-    Mqtt3UnsubscribeBuilder.SendVoid.@NotNull Start unsubscribeWith();
+    Mqtt3UnsubscribeBuilder.Send.@NotNull Start<Mqtt3UnsubAck> unsubscribeWith();
 
     /**
      * Publishes the given Publish message.
      *
      * @param publish the Publish message sent to the broker.
+     * @return the {@link Mqtt3PublishResult} if the Publish message was successfully published ({@link
+     *         Mqtt3PublishResult#getError()} will always be absent).
      */
-    void publish(@NotNull Mqtt3Publish publish);
+    @NotNull Mqtt3PublishResult publish(@NotNull Mqtt3Publish publish);
 
     /**
      * Fluent counterpart of {@link #publish(Mqtt3Publish)}.
      * <p>
-     * Calling {@link Mqtt3PublishBuilder.SendVoid.Complete#send()} on the returned builder has the same effect as
-     * calling {@link #publish(Mqtt3Publish)} with the result of {@link Mqtt3PublishBuilder.Complete#build()}.
+     * Calling {@link Mqtt3PublishBuilder.Send.Complete#send()} on the returned builder has the same effect as calling
+     * {@link #publish(Mqtt3Publish)} with the result of {@link Mqtt3PublishBuilder.Complete#build()}.
      *
      * @return the fluent builder for the Unsubscribe message.
      * @see #publish(Mqtt3Publish)
      */
     @CheckReturnValue
-    Mqtt3PublishBuilder.@NotNull SendVoid publishWith();
+    Mqtt3PublishBuilder.@NotNull Send<Mqtt3PublishResult> publishWith();
 
     /**
      * Disconnects this client with the given Disconnect message.
@@ -172,13 +175,13 @@ public interface Mqtt3BlockingClient extends Mqtt3Client {
     /**
      * Resource which queues incoming Publish messages until they are received.
      */
-    @DoNotImplement
-    interface Mqtt3Publishes extends AutoCloseable {
+    @ApiStatus.NonExtendable
+    interface Publishes extends AutoCloseable {
 
         /**
          * Receives the next incoming Publish message.
          * <ul>
-         *   <li>Might return immediately if there is already a Publish message queued in this {@link Mqtt3Publishes}
+         *   <li>Might return immediately if there is already a Publish message queued in this {@link Publishes}
          *     instance.
          *   <li>Otherwise blocks the calling thread until a Publish message is received.
          * </ul>
@@ -192,7 +195,7 @@ interface Mqtt3Publishes extends AutoCloseable {
         /**
          * Receives the next incoming Publish message.
          * <ul>
-         *   <li>Might return immediately if there is already a Publish message queued in this {@link Mqtt3Publishes}
+         *   <li>Might return immediately if there is already a Publish message queued in this {@link Publishes}
          *     instance.
          *   <li>Otherwise blocks the calling thread until a Publish message is received or the given timeout applies.
          * </ul>
@@ -208,7 +211,7 @@ interface Mqtt3Publishes extends AutoCloseable {
                 throws InterruptedException;
 
         /**
-         * Receives the next incoming Publish message if it is already queued in this {@link Mqtt3Publishes} instance.
+         * Receives the next incoming Publish message if it is already queued in this {@link Publishes} instance.
          *
          * @return an {@link Optional} containing the already queued Publish message, or empty if no Publish message was
          *         already queued.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3Client.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3Client.java
similarity index 87%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3Client.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3Client.java
index 7fd7e2935..0a7d08d3d 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3Client.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3Client.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3;
+package com.hivemq.client2.mqtt.mqtt3;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.mqtt3.Mqtt3RxClientViewBuilder;
-import com.hivemq.client.mqtt.MqttClient;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.mqtt.mqtt3.Mqtt3RxClientViewBuilder;
+import com.hivemq.client2.mqtt.MqttClient;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3Client extends MqttClient {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3ClientBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3ClientBuilder.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3ClientBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3ClientBuilder.java
index c7d5607cb..5e7d5fe4c 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3ClientBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3ClientBuilder.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3;
+package com.hivemq.client2.mqtt.mqtt3;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientBuilderBase;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuthBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3WillPublishBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttClientBuilderBase;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuthBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3WillPublishBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -32,7 +32,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3ClientBuilder extends MqttClientBuilderBase<Mqtt3ClientBuilder> {
 
     /**
@@ -59,7 +59,7 @@ public interface Mqtt3ClientBuilder extends MqttClientBuilderBase<Mqtt3ClientBui
      * @since 1.1
      */
     @CheckReturnValue
-    Mqtt3SimpleAuthBuilder.@NotNull Nested<? extends Mqtt3ClientBuilder> simpleAuth();
+    Mqtt3SimpleAuthBuilder.@NotNull Nested<? extends Mqtt3ClientBuilder> simpleAuthWith();
 
     /**
      * Sets the optional {@link Mqtt3ClientConfig#getWillPublish() Will Publish}.
@@ -83,7 +83,7 @@ public interface Mqtt3ClientBuilder extends MqttClientBuilderBase<Mqtt3ClientBui
      * @since 1.1
      */
     @CheckReturnValue
-    Mqtt3WillPublishBuilder.@NotNull Nested<? extends Mqtt3ClientBuilder> willPublish();
+    Mqtt3WillPublishBuilder.@NotNull Nested<? extends Mqtt3ClientBuilder> willPublishWith();
 
     /**
      * Builds the {@link Mqtt3Client}.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3ClientConfig.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3ClientConfig.java
similarity index 73%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3ClientConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3ClientConfig.java
index c0ff11d0a..a3bbe3a53 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3ClientConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3ClientConfig.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3;
+package com.hivemq.client2.mqtt.mqtt3;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientConfig;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.MqttClientConfig;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -30,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3ClientConfig extends MqttClientConfig {
 
     @Override
@@ -39,11 +39,11 @@ public interface Mqtt3ClientConfig extends MqttClientConfig {
     /**
      * Returns the optional simple authentication and/or authorization related data of the client.
      * <p>
-     * It is used as default if {@link com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect#getSimpleAuth()
+     * It is used as default if {@link com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect#getSimpleAuth()
      * Mqtt3Connect.simpleAuth} is not set during connect.
      * <p>
      * Keep in mind that the data is stored with the client in memory. If you want to use it only during connect or if
-     * you use a different token for each connection please set {@link com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect#getSimpleAuth()
+     * you use a different token for each connection please set {@link com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect#getSimpleAuth()
      * Mqtt3Connect.simpleAuth} instead.
      *
      * @return the optional simple authentication and/or authorization related data of the client.
@@ -54,11 +54,11 @@ public interface Mqtt3ClientConfig extends MqttClientConfig {
     /**
      * Returns the optional Will Publish of the client.
      * <p>
-     * It is used as default if {@link com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect#getWillPublish()
+     * It is used as default if {@link com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect#getWillPublish()
      * Mqtt3Connect.willPublish} is not set during connect.
      * <p>
      * Keep in mind that the Will Publish is stored with the client in memory. If you use a different Will Publish for
-     * each connection please set {@link com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect#getWillPublish()
+     * each connection please set {@link com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect#getWillPublish()
      * Mqtt3Connect.willPublish} instead.
      *
      * @return the optional Will Publish of the client.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3ClientConnectionConfig.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3ClientConnectionConfig.java
similarity index 78%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3ClientConnectionConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3ClientConnectionConfig.java
index 42949102d..89f37337c 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3ClientConnectionConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3ClientConnectionConfig.java
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3;
+package com.hivemq.client2.mqtt.mqtt3;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.MqttClientConnectionConfig;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 /**
  * Connection configuration of an {@link Mqtt3Client}.
@@ -26,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3ClientConnectionConfig extends MqttClientConnectionConfig {
 
     /**
@@ -37,7 +39,7 @@ public interface Mqtt3ClientConnectionConfig extends MqttClientConnectionConfig
     /**
      * Restrictions for messages a {@link Mqtt3Client} sends.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface RestrictionsForClient {
 
         /**
@@ -47,6 +49,6 @@ interface RestrictionsForClient {
          * @return the maximum amount of not acknowledged publishes with QoS 1 or 2 the client sends to the server
          *         concurrently.
          */
-        int getSendMaximum();
+        @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getSendMaximum();
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3RxClient.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3RxClient.java
similarity index 82%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3RxClient.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3RxClient.java
index 380bbd564..d0ef944e4 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/Mqtt3RxClient.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/Mqtt3RxClient.java
@@ -14,26 +14,28 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3;
+package com.hivemq.client2.mqtt.mqtt3;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubscribeBuilder;
-import com.hivemq.client.rx.FlowableWithSingle;
-import io.reactivex.Completable;
-import io.reactivex.Flowable;
-import io.reactivex.Single;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubscribeBuilder;
+import com.hivemq.client2.rx.FlowableWithSingle;
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.Single;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.reactivestreams.Publisher;
 
 /**
  * Reactive API of an {@link Mqtt3Client}.
@@ -41,7 +43,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3RxClient extends Mqtt3Client {
 
     /**
@@ -64,7 +66,7 @@ public interface Mqtt3RxClient extends Mqtt3Client {
      * @return the {@link Single} which
      *         <ul>
      *           <li>succeeds with the ConnAck message if it does not contain an Error Code (connected successfully),
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3ConnAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3ConnAckException
      *             Mqtt3ConnAckException} wrapping the ConnAck message if it contains an Error Code or
      *           <li>errors with a different exception if an error occurred before the Connect message was sent or
      *             before the ConnAck message was received.
@@ -101,7 +103,7 @@ public interface Mqtt3RxClient extends Mqtt3Client {
      *         <ul>
      *           <li>succeeds with the SubAck message if at least one subscription of the Subscribe message was
      *             successful (the SubAck message contains at least one Return Code that is not an Error Code),
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3SubAckException
      *             Mqtt3SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent or
      *             before a SubAck message was received.
@@ -123,25 +125,6 @@ public interface Mqtt3RxClient extends Mqtt3Client {
     @CheckReturnValue
     Mqtt3SubscribeBuilder.Nested.@NotNull Start<Single<Mqtt3SubAck>> subscribeWith();
 
-    /**
-     * Use {@link #subscribePublishes(Mqtt3Subscribe)}.
-     *
-     * @param subscribe use {@link #subscribePublishes(Mqtt3Subscribe)}.
-     * @return use {@link #subscribePublishes(Mqtt3Subscribe)}.
-     * @deprecated use {@link #subscribePublishes(Mqtt3Subscribe)}.
-     */
-    @Deprecated
-    @NotNull FlowableWithSingle<Mqtt3Publish, Mqtt3SubAck> subscribeStream(@NotNull Mqtt3Subscribe subscribe);
-
-    /**
-     * Use {@link #subscribePublishesWith()}.
-     *
-     * @return use {@link #subscribePublishesWith()}.
-     * @deprecated use {@link #subscribePublishesWith()}.
-     */
-    @Deprecated
-    Mqtt3SubscribeBuilder.Nested.@NotNull Start<FlowableWithSingle<Mqtt3Publish, Mqtt3SubAck>> subscribeStreamWith();
-
     /**
      * Creates a {@link FlowableWithSingle} for subscribing this client with the given Subscribe message.
      * <p>
@@ -158,11 +141,11 @@ public interface Mqtt3RxClient extends Mqtt3Client {
      *             Error Code) and then emits the Publish messages matching the successful subscriptions of the
      *             Subscribe message,
      *           <li>completes when all subscriptions of the Subscribe message were unsubscribed,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3SubAckException
      *             Mqtt3SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent,
      *             before a SubAck message was received or when a error occurs before all subscriptions of the Subscribe
-     *             message were unsubscribed (e.g. {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *             message were unsubscribed (e.g. {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException}).
      *         </ul>
      * @see #subscribePublishes(Mqtt3Subscribe, boolean)
@@ -188,11 +171,11 @@ public interface Mqtt3RxClient extends Mqtt3Client {
      *             Error Code) and then emits the Publish messages matching the successful subscriptions of the
      *             Subscribe message,
      *           <li>completes when all subscriptions of the Subscribe message were unsubscribed,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3SubAckException
      *             Mqtt3SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent,
      *             before a SubAck message was received or when a error occurs before all subscriptions of the Subscribe
-     *             message were unsubscribed (e.g. {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *             message were unsubscribed (e.g. {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException}).
      *         </ul>
      * @see #subscribePublishes(Mqtt3Subscribe)
@@ -228,7 +211,7 @@ public interface Mqtt3RxClient extends Mqtt3Client {
      *         <ul>
      *           <li>emits the incoming Publish messages matching the given filter,
      *           <li>never completes but
-     *           <li>errors with a {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException} when the MQTT session expires.
      *         </ul>
      * @see #publishes(MqttGlobalPublishFilter, boolean)
@@ -249,7 +232,7 @@ public interface Mqtt3RxClient extends Mqtt3Client {
      *         <ul>
      *           <li>emits the incoming Publish messages matching the given filter,
      *           <li>never completes but
-     *           <li>errors with a {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException} when the MQTT session expires.
      *         </ul>
      * @see #publishes(MqttGlobalPublishFilter)
@@ -266,15 +249,15 @@ public interface Mqtt3RxClient extends Mqtt3Client {
      * asynchronous when subscribing (in terms of Reactive Streams) to the returned {@link Completable}.
      *
      * @param unsubscribe the Unsubscribe message sent to the broker during unsubscribe.
-     * @return the {@link Completable} which
+     * @return the {@link Single} which
      *         <ul>
-     *           <li>succeeds when the corresponding UnsubAck message was received or
+     *           <li>succeeds with the UnsubAck message or
      *           <li>errors if an error occurred before the Unsubscribe message was sent or before a UnsubAck message
      *             was received.
      *         </ul>
      */
     @CheckReturnValue
-    @NotNull Completable unsubscribe(@NotNull Mqtt3Unsubscribe unsubscribe);
+    @NotNull Single<Mqtt3UnsubAck> unsubscribe(@NotNull Mqtt3Unsubscribe unsubscribe);
 
     /**
      * Fluent counterpart of {@link #unsubscribe(Mqtt3Unsubscribe)}.
@@ -287,7 +270,7 @@ public interface Mqtt3RxClient extends Mqtt3Client {
      * @see #unsubscribe(Mqtt3Unsubscribe)
      */
     @CheckReturnValue
-    Mqtt3UnsubscribeBuilder.Nested.@NotNull Start<Completable> unsubscribeWith();
+    Mqtt3UnsubscribeBuilder.Nested.@NotNull Start<Single<Mqtt3UnsubAck>> unsubscribeWith();
 
     /**
      * Creates a {@link Flowable} for publishing the Publish messages emitted by the given {@link Flowable}.
@@ -297,7 +280,7 @@ public interface Mqtt3RxClient extends Mqtt3Client {
      * Publishing is performed lazy and asynchronous. When subscribing (in terms of Reactive Streams) to the returned
      * {@link Flowable} the client subscribes (in terms of Reactive Streams) to the given {@link Flowable}.
      *
-     * @param publishFlowable the source of the Publish messages to publish.
+     * @param publisher the source of the Publish messages to publish.
      * @return the {@link Flowable} which
      *         <ul>
      *           <li>emits {@link Mqtt3PublishResult}s each corresponding to a Publish message,
@@ -308,7 +291,7 @@ public interface Mqtt3RxClient extends Mqtt3Client {
      *         </ul>
      */
     @CheckReturnValue
-    @NotNull Flowable<Mqtt3PublishResult> publish(@NotNull Flowable<Mqtt3Publish> publishFlowable);
+    @NotNull Flowable<Mqtt3PublishResult> publish(@NotNull Publisher<Mqtt3Publish> publisher);
 
     /**
      * Creates a {@link Completable} for disconnecting this client.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3ConnAckException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3ConnAckException.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3ConnAckException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3ConnAckException.java
index 3f6369c8c..9fc7a9488 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3ConnAckException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3ConnAckException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3DisconnectException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3DisconnectException.java
similarity index 71%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3DisconnectException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3DisconnectException.java
index 14a8bdaf1..ce7657664 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3DisconnectException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3DisconnectException.java
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.mqtt.message.disconnect.mqtt3.Mqtt3DisconnectView;
-import com.hivemq.client.mqtt.mqtt3.message.disconnect.Mqtt3Disconnect;
+import com.hivemq.client2.mqtt.mqtt3.message.disconnect.Mqtt3Disconnect;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -27,12 +26,20 @@
  */
 public class Mqtt3DisconnectException extends Mqtt3MessageException {
 
-    public Mqtt3DisconnectException(final @Nullable String message, final @Nullable Throwable cause) {
+    private final @NotNull Mqtt3Disconnect disconnect;
+
+    public Mqtt3DisconnectException(
+            final @NotNull Mqtt3Disconnect disconnect,
+            final @Nullable String message,
+            final @Nullable Throwable cause) {
+
         super(message, cause);
+        this.disconnect = disconnect;
     }
 
     private Mqtt3DisconnectException(final @NotNull Mqtt3DisconnectException e) {
         super(e);
+        disconnect = e.disconnect;
     }
 
     @Override
@@ -42,6 +49,6 @@ private Mqtt3DisconnectException(final @NotNull Mqtt3DisconnectException e) {
 
     @Override
     public @NotNull Mqtt3Disconnect getMqttMessage() {
-        return Mqtt3DisconnectView.INSTANCE;
+        return disconnect;
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3MessageException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3MessageException.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3MessageException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3MessageException.java
index 263b4fa13..a5178eb82 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3MessageException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3MessageException.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubAckException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubAckException.java
similarity index 74%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubAckException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubAckException.java
index bab9d68d1..7923424a4 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubAckException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubAckException.java
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.mqtt.message.publish.puback.mqtt3.Mqtt3PubAckView;
-import com.hivemq.client.mqtt.mqtt3.message.publish.puback.Mqtt3PubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PubAck;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -27,12 +26,18 @@
  */
 public class Mqtt3PubAckException extends Mqtt3MessageException {
 
-    public Mqtt3PubAckException(final @Nullable String message, final @Nullable Throwable cause) {
+    private final @NotNull Mqtt3PubAck pubAck;
+
+    public Mqtt3PubAckException(
+            final @NotNull Mqtt3PubAck pubAck, final @Nullable String message, final @Nullable Throwable cause) {
+
         super(message, cause);
+        this.pubAck = pubAck;
     }
 
     private Mqtt3PubAckException(final @NotNull Mqtt3PubAckException e) {
         super(e);
+        pubAck = e.pubAck;
     }
 
     @Override
@@ -42,6 +47,6 @@ private Mqtt3PubAckException(final @NotNull Mqtt3PubAckException e) {
 
     @Override
     public @NotNull Mqtt3PubAck getMqttMessage() {
-        return Mqtt3PubAckView.INSTANCE;
+        return pubAck;
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubRecException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubRecException.java
similarity index 74%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubRecException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubRecException.java
index 22e5e3682..e23660ccc 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubRecException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubRecException.java
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.mqtt3.Mqtt3PubRecView;
-import com.hivemq.client.mqtt.mqtt3.message.publish.pubrec.Mqtt3PubRec;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PubRec;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -27,12 +26,18 @@
  */
 public class Mqtt3PubRecException extends Mqtt3MessageException {
 
-    public Mqtt3PubRecException(final @Nullable String message, final @Nullable Throwable cause) {
+    private final @NotNull Mqtt3PubRec pubRec;
+
+    public Mqtt3PubRecException(
+            final @NotNull Mqtt3PubRec pubRec, final @Nullable String message, final @Nullable Throwable cause) {
+
         super(message, cause);
+        this.pubRec = pubRec;
     }
 
     private Mqtt3PubRecException(final @NotNull Mqtt3PubRecException e) {
         super(e);
+        pubRec = e.pubRec;
     }
 
     @Override
@@ -42,6 +47,6 @@ private Mqtt3PubRecException(final @NotNull Mqtt3PubRecException e) {
 
     @Override
     public @NotNull Mqtt3PubRec getMqttMessage() {
-        return Mqtt3PubRecView.INSTANCE;
+        return pubRec;
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3SubAckException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3SubAckException.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3SubAckException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3SubAckException.java
index 1bb953576..d8fd4cd89 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3SubAckException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3SubAckException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3UnsubAckException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3UnsubAckException.java
similarity index 73%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3UnsubAckException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3UnsubAckException.java
index c3bc162bd..8abe1d291 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3UnsubAckException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3UnsubAckException.java
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.mqtt3.Mqtt3UnsubAckView;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.unsuback.Mqtt3UnsubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3UnsubAck;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -27,12 +26,18 @@
  */
 public class Mqtt3UnsubAckException extends Mqtt3MessageException {
 
-    public Mqtt3UnsubAckException(final @Nullable String message, final @Nullable Throwable cause) {
+    private final @NotNull Mqtt3UnsubAck unsubAck;
+
+    public Mqtt3UnsubAckException(
+            final @NotNull Mqtt3UnsubAck unsubAck, final @Nullable String message, final @Nullable Throwable cause) {
+
         super(message, cause);
+        this.unsubAck = unsubAck;
     }
 
     private Mqtt3UnsubAckException(final @NotNull Mqtt3UnsubAckException e) {
         super(e);
+        unsubAck = e.unsubAck;
     }
 
     @Override
@@ -42,6 +47,6 @@ private Mqtt3UnsubAckException(final @NotNull Mqtt3UnsubAckException e) {
 
     @Override
     public @NotNull Mqtt3UnsubAck getMqttMessage() {
-        return Mqtt3UnsubAckView.INSTANCE;
+        return unsubAck;
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/lifecycle/Mqtt3ClientConnectedContext.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/lifecycle/Mqtt3ConnectedContext.java
similarity index 64%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/lifecycle/Mqtt3ClientConnectedContext.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/lifecycle/Mqtt3ConnectedContext.java
index e5aa65a46..f007cdae4 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/lifecycle/Mqtt3ClientConnectedContext.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/lifecycle/Mqtt3ConnectedContext.java
@@ -14,24 +14,24 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.lifecycle;
+package com.hivemq.client2.mqtt.mqtt3.lifecycle;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedContext;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientConfig;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedContext;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientConfig;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * A {@link MqttClientConnectedContext} with methods specific to an {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client
+ * A {@link MqttConnectedContext} with methods specific to an {@link com.hivemq.client2.mqtt.mqtt3.Mqtt3Client
  * Mqtt3Client}.
  *
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface Mqtt3ClientConnectedContext extends MqttClientConnectedContext {
+@ApiStatus.NonExtendable
+public interface Mqtt3ConnectedContext extends MqttConnectedContext {
 
     @Override
     @NotNull Mqtt3ClientConfig getClientConfig();
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/lifecycle/Mqtt3ClientDisconnectedContext.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/lifecycle/Mqtt3DisconnectedContext.java
similarity index 61%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/lifecycle/Mqtt3ClientDisconnectedContext.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/lifecycle/Mqtt3DisconnectedContext.java
index 1b8901af8..97c798c53 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/lifecycle/Mqtt3ClientDisconnectedContext.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/lifecycle/Mqtt3DisconnectedContext.java
@@ -14,26 +14,26 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.lifecycle;
+package com.hivemq.client2.mqtt.mqtt3.lifecycle;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedContext;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientConfig;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedContext;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientConfig;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * A {@link MqttClientDisconnectedContext} with methods specific to an {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client
+ * A {@link MqttDisconnectedContext} with methods specific to an {@link com.hivemq.client2.mqtt.mqtt3.Mqtt3Client
  * Mqtt3Client}.
  *
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface Mqtt3ClientDisconnectedContext extends MqttClientDisconnectedContext {
+@ApiStatus.NonExtendable
+public interface Mqtt3DisconnectedContext extends MqttDisconnectedContext {
 
     @Override
     @NotNull Mqtt3ClientConfig getClientConfig();
 
     @Override
-    @NotNull Mqtt3ClientReconnector getReconnector();
+    @NotNull Mqtt3Reconnector getReconnector();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/lifecycle/Mqtt3ClientReconnector.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/lifecycle/Mqtt3Reconnector.java
similarity index 55%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/lifecycle/Mqtt3ClientReconnector.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/lifecycle/Mqtt3Reconnector.java
index 13dd93324..b02ea1539 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/lifecycle/Mqtt3ClientReconnector.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/lifecycle/Mqtt3Reconnector.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.lifecycle;
+package com.hivemq.client2.mqtt.mqtt3.lifecycle;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientTransportConfig;
-import com.hivemq.client.mqtt.MqttClientTransportConfigBuilder;
-import com.hivemq.client.mqtt.lifecycle.MqttClientReconnector;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttTransportConfig;
+import com.hivemq.client2.mqtt.MqttTransportConfigBuilder;
+import com.hivemq.client2.mqtt.lifecycle.MqttReconnector;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnectBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -31,37 +31,36 @@
 import java.util.function.BiConsumer;
 
 /**
- * A {@link MqttClientReconnector} with methods specific to an {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client
- * Mqtt3Client}.
+ * A {@link MqttReconnector} with methods specific to an {@link com.hivemq.client2.mqtt.mqtt3.Mqtt3Client Mqtt3Client}.
  *
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface Mqtt3ClientReconnector extends MqttClientReconnector {
+@ApiStatus.NonExtendable
+public interface Mqtt3Reconnector extends MqttReconnector {
 
     @Override
-    @NotNull Mqtt3ClientReconnector reconnect(boolean reconnect);
+    @NotNull Mqtt3Reconnector reconnect(boolean reconnect);
 
     @Override
-    <T> @NotNull Mqtt3ClientReconnector reconnectWhen(
+    <T> @NotNull Mqtt3Reconnector reconnectWhen(
             @NotNull CompletableFuture<T> future, @Nullable BiConsumer<? super T, ? super Throwable> callback);
 
     @Override
-    @NotNull Mqtt3ClientReconnector resubscribeIfSessionExpired(boolean resubscribe);
+    @NotNull Mqtt3Reconnector resubscribeIfSessionExpired(boolean resubscribe);
 
     @Override
-    @NotNull Mqtt3ClientReconnector republishIfSessionExpired(boolean republish);
+    @NotNull Mqtt3Reconnector republishIfSessionExpired(boolean republish);
 
     @Override
-    @NotNull Mqtt3ClientReconnector delay(long delay, @NotNull TimeUnit timeUnit);
+    @NotNull Mqtt3Reconnector delay(long delay, @NotNull TimeUnit timeUnit);
 
     @Override
-    @NotNull Mqtt3ClientReconnector transportConfig(@NotNull MqttClientTransportConfig transportConfig);
+    @NotNull Mqtt3Reconnector transportConfig(@NotNull MqttTransportConfig transportConfig);
 
     @Override
     @CheckReturnValue
-    MqttClientTransportConfigBuilder.@NotNull Nested<? extends Mqtt3ClientReconnector> transportConfig();
+    MqttTransportConfigBuilder.@NotNull Nested<? extends Mqtt3Reconnector> transportConfigWith();
 
     /**
      * Sets a different Connect message the client will try to reconnect with.
@@ -69,7 +68,7 @@ public interface Mqtt3ClientReconnector extends MqttClientReconnector {
      * @param connect the Connect message.
      * @return this reconnector.
      */
-    @NotNull Mqtt3ClientReconnector connect(@NotNull Mqtt3Connect connect);
+    @NotNull Mqtt3Reconnector connect(@NotNull Mqtt3Connect connect);
 
     /**
      * Fluent counterpart of {@link #connect(Mqtt3Connect)}.
@@ -81,14 +80,14 @@ public interface Mqtt3ClientReconnector extends MqttClientReconnector {
      * @see #connect(Mqtt3Connect)
      */
     @CheckReturnValue
-    Mqtt3ConnectBuilder.@NotNull Nested<? extends Mqtt3ClientReconnector> connectWith();
+    Mqtt3ConnectBuilder.@NotNull Nested<? extends Mqtt3Reconnector> connectWith();
 
     /**
-     * Returns the currently set Connect message the client will try to reconnect with.
+     * Returns the currently set Connect message the client will try to reconnect with.@
      * <p>
      * If the {@link #connect(Mqtt3Connect)} method has not been called before (including previous {@link
-     * com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener MqttClientDisconnectedListeners}) it will be the
-     * Connect message that is reconstructed from the {@link com.hivemq.client.mqtt.mqtt3.Mqtt3ClientConnectionConfig
+     * com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedListener MqttDisconnectedListener}s) it will be the Connect
+     * message that is reconstructed from the {@link com.hivemq.client2.mqtt.mqtt3.Mqtt3ClientConnectionConfig
      * Mqtt3ClientConnectionConfig} or the Connect message of the previous connect try if it has not been successfully
      * connected.
      *
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3Message.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3Message.java
similarity index 88%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3Message.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3Message.java
index 95ca6a5c1..a0ae82e16 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3Message.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3Message.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message;
+package com.hivemq.client2.mqtt.mqtt3.message;
 
-import com.hivemq.client.annotations.DoNotImplement;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -25,7 +25,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3Message {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3MessageType.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3MessageType.java
similarity index 97%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3MessageType.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3MessageType.java
index b28220de0..bc0a9d086 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3MessageType.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3MessageType.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message;
+package com.hivemq.client2.mqtt.mqtt3.message;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3ReturnCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3ReturnCode.java
similarity index 75%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3ReturnCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3ReturnCode.java
index 505a849f1..3c607f3bf 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3ReturnCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3ReturnCode.java
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message;
+package com.hivemq.client2.mqtt.mqtt3.message;
 
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Range;
 
 /**
  * Return Code according to the MQTT 3 specification.
@@ -24,13 +26,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3ReturnCode {
 
     /**
      * @return the byte code of this Return Code.
      */
-    int getCode();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_BYTE_MAX_VALUE) int getCode();
 
     /**
      * @return whether this Return Code is an Error Code.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/auth/Mqtt3SimpleAuth.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/auth/Mqtt3SimpleAuth.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/auth/Mqtt3SimpleAuth.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/auth/Mqtt3SimpleAuth.java
index 1ca47e1b1..4a67f31c7 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/auth/Mqtt3SimpleAuth.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/auth/Mqtt3SimpleAuth.java
@@ -14,24 +14,24 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.auth;
+package com.hivemq.client2.mqtt.mqtt3.message.auth;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthViewBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.internal.mqtt.message.auth.mqtt3.Mqtt3SimpleAuthViewBuilder;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.nio.ByteBuffer;
 import java.util.Optional;
 
 /**
- * Simple authentication and/or authorization related data in an {@link com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect
+ * Simple authentication and/or authorization related data in an {@link com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect
  * MQTT 3 Connect message}.
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3SimpleAuth {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilder.java
index 989e5f8aa..139bd1fff 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.auth;
+package com.hivemq.client2.mqtt.mqtt3.message.auth;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,13 +26,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3SimpleAuthBuilder extends Mqtt3SimpleAuthBuilderBase<Mqtt3SimpleAuthBuilder.Complete> {
 
     /**
      * {@link Mqtt3SimpleAuthBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete
             extends Mqtt3SimpleAuthBuilder, Mqtt3SimpleAuthBuilderBase.Complete<Mqtt3SimpleAuthBuilder.Complete> {
 
@@ -50,7 +50,7 @@ interface Complete
      *
      * @param <P> the type of the result when the built {@link Mqtt3SimpleAuth} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt3SimpleAuthBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -58,7 +58,7 @@ interface Nested<P> extends Mqtt3SimpleAuthBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt3SimpleAuth} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Mqtt3SimpleAuthBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilderBase.java
similarity index 90%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilderBase.java
index b0ea14835..66dc985b5 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/auth/Mqtt3SimpleAuthBuilderBase.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.auth;
+package com.hivemq.client2.mqtt.mqtt3.message.auth;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.nio.ByteBuffer;
@@ -30,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3SimpleAuthBuilderBase<C extends Mqtt3SimpleAuthBuilderBase.Complete<C>> {
 
     /**
@@ -56,7 +56,7 @@ public interface Mqtt3SimpleAuthBuilderBase<C extends Mqtt3SimpleAuthBuilderBase
      *
      * @param <C> the type of the complete builder.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete<C extends Mqtt3SimpleAuthBuilderBase.Complete<C>> extends Mqtt3SimpleAuthBuilderBase<C> {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/connack/Mqtt3ConnAck.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnAck.java
similarity index 83%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/connack/Mqtt3ConnAck.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnAck.java
index 531d09624..2f46f8c05 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/connack/Mqtt3ConnAck.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnAck.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.connect.connack;
+package com.hivemq.client2.mqtt.mqtt3.message.connect;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3ConnAck extends Mqtt3Message {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/connack/Mqtt3ConnAckReturnCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnAckReturnCode.java
similarity index 94%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/connack/Mqtt3ConnAckReturnCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnAckReturnCode.java
index dca1ef5f7..687edf20c 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/connack/Mqtt3ConnAckReturnCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnAckReturnCode.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.connect.connack;
+package com.hivemq.client2.mqtt.mqtt3.message.connect;
 
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3ReturnCode;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3ReturnCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/Mqtt3Connect.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3Connect.java
similarity index 77%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/Mqtt3Connect.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3Connect.java
index 2ec330c77..3dfe75f87 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/Mqtt3Connect.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3Connect.java
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.connect;
+package com.hivemq.client2.mqtt.mqtt3.message.connect;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.util.Optional;
 
@@ -32,7 +34,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3Connect extends Mqtt3Message {
 
     /**
@@ -60,7 +62,7 @@ public interface Mqtt3Connect extends Mqtt3Message {
     /**
      * @return the keep alive in seconds the client wants to use.
      */
-    int getKeepAlive();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getKeepAlive();
 
     /**
      * @return whether the client wants a clean session. If <code>true</code> an existing session is cleared.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilder.java
similarity index 87%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilder.java
index 5f7a9c6cc..7f1a9e86e 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.connect;
+package com.hivemq.client2.mqtt.mqtt3.message.connect;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,7 +26,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3ConnectBuilder extends Mqtt3ConnectBuilderBase<Mqtt3ConnectBuilder> {
 
     /**
@@ -42,7 +42,7 @@ public interface Mqtt3ConnectBuilder extends Mqtt3ConnectBuilderBase<Mqtt3Connec
      *
      * @param <P> the type of the result when the built {@link Mqtt3Connect} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt3ConnectBuilderBase<Nested<P>> {
 
         /**
@@ -54,12 +54,12 @@ interface Nested<P> extends Mqtt3ConnectBuilderBase<Nested<P>> {
     }
 
     /**
-     * Builder for a {@link Mqtt3Connect} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client}
+     * Builder for a {@link Mqtt3Connect} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt3.Mqtt3Client}
      * which then sends the Connect message.
      *
      * @param <P> the type of the result when the built {@link Mqtt3Connect} is sent by the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Send<P> extends Mqtt3ConnectBuilderBase<Send<P>> {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilderBase.java
similarity index 83%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilderBase.java
index 4d8cfffb9..15884717f 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnectBuilderBase.java
@@ -14,16 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.connect;
+package com.hivemq.client2.mqtt.mqtt3.message.connect;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
-import com.hivemq.client.mqtt.mqtt3.message.auth.Mqtt3SimpleAuthBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3WillPublishBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt3.message.auth.Mqtt3SimpleAuthBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3WillPublishBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 /**
  * Builder base for a {@link Mqtt3Connect}.
@@ -32,7 +34,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3ConnectBuilderBase<B extends Mqtt3ConnectBuilderBase<B>> {
 
     /**
@@ -44,7 +46,7 @@ public interface Mqtt3ConnectBuilderBase<B extends Mqtt3ConnectBuilderBase<B>> {
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B keepAlive(int keepAlive);
+    @NotNull B keepAlive(@Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int keepAlive);
 
     /**
      * Disables the {@link Mqtt3Connect#getKeepAlive() keep alive} by setting it to {@link Mqtt3Connect#NO_KEEP_ALIVE}.
@@ -84,7 +86,7 @@ public interface Mqtt3ConnectBuilderBase<B extends Mqtt3ConnectBuilderBase<B>> {
      * @see #simpleAuth(Mqtt3SimpleAuth)
      */
     @CheckReturnValue
-    Mqtt3SimpleAuthBuilder.@NotNull Nested<? extends B> simpleAuth();
+    Mqtt3SimpleAuthBuilder.@NotNull Nested<? extends B> simpleAuthWith();
 
     /**
      * Sets the optional {@link Mqtt3Connect#getWillPublish() Will Publish}.
@@ -106,5 +108,5 @@ public interface Mqtt3ConnectBuilderBase<B extends Mqtt3ConnectBuilderBase<B>> {
      * @see #willPublish(Mqtt3Publish)
      */
     @CheckReturnValue
-    Mqtt3WillPublishBuilder.@NotNull Nested<? extends B> willPublish();
+    Mqtt3WillPublishBuilder.@NotNull Nested<? extends B> willPublishWith();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/disconnect/Mqtt3Disconnect.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/disconnect/Mqtt3Disconnect.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/disconnect/Mqtt3Disconnect.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/disconnect/Mqtt3Disconnect.java
index 0ffdf3564..ee588bbd6 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/disconnect/Mqtt3Disconnect.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/disconnect/Mqtt3Disconnect.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.disconnect;
+package com.hivemq.client2.mqtt.mqtt3.message.disconnect;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -27,7 +27,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3Disconnect extends Mqtt3Message {
 
     @Override
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/ping/Mqtt3PingReq.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/ping/Mqtt3PingReq.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/ping/Mqtt3PingReq.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/ping/Mqtt3PingReq.java
index e7e5a46f2..cbe7d52f8 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/ping/Mqtt3PingReq.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/ping/Mqtt3PingReq.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.ping;
+package com.hivemq.client2.mqtt.mqtt3.message.ping;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -27,7 +27,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3PingReq extends Mqtt3Message {
 
     @Override
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/ping/Mqtt3PingResp.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/ping/Mqtt3PingResp.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/ping/Mqtt3PingResp.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/ping/Mqtt3PingResp.java
index de1cf12d1..9116a4cc9 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/ping/Mqtt3PingResp.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/ping/Mqtt3PingResp.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.ping;
+package com.hivemq.client2.mqtt.mqtt3.message.ping;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -27,7 +27,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3PingResp extends Mqtt3Message {
 
     @Override
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/puback/Mqtt3PubAck.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubAck.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/puback/Mqtt3PubAck.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubAck.java
index 11b538b6b..f909a9d7d 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/puback/Mqtt3PubAck.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubAck.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.publish.puback;
+package com.hivemq.client2.mqtt.mqtt3.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3PubAck extends Mqtt3Message {
 
     @Override
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/pubcomp/Mqtt3PubComp.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubComp.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/pubcomp/Mqtt3PubComp.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubComp.java
index d6333d76c..ae593dd21 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/pubcomp/Mqtt3PubComp.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubComp.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.publish.pubcomp;
+package com.hivemq.client2.mqtt.mqtt3.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3PubComp extends Mqtt3Message {
 
     @Override
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/pubrec/Mqtt3PubRec.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubRec.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/pubrec/Mqtt3PubRec.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubRec.java
index d0e6ffcb1..c7552d69a 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/pubrec/Mqtt3PubRec.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubRec.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.publish.pubrec;
+package com.hivemq.client2.mqtt.mqtt3.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3PubRec extends Mqtt3Message {
 
     @Override
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/pubrel/Mqtt3PubRel.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubRel.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/pubrel/Mqtt3PubRel.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubRel.java
index 611568151..0e440cb0f 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/pubrel/Mqtt3PubRel.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PubRel.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.publish.pubrel;
+package com.hivemq.client2.mqtt.mqtt3.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3PubRel extends Mqtt3Message {
 
     @Override
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3Publish.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3Publish.java
similarity index 85%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3Publish.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3Publish.java
index be7b4bb39..04314b35b 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3Publish.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3Publish.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.publish;
+package com.hivemq.client2.mqtt.mqtt3.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.message.publish.mqtt3.Mqtt3PublishViewBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PublishViewBuilder;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.nio.ByteBuffer;
@@ -34,7 +34,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3Publish extends Mqtt3Message {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3PublishBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PublishBuilder.java
similarity index 73%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3PublishBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PublishBuilder.java
index 2a78bcf1f..35a664596 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3PublishBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PublishBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.publish;
+package com.hivemq.client2.mqtt.mqtt3.message.publish;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,13 +26,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3PublishBuilder extends Mqtt3PublishBuilderBase<Mqtt3PublishBuilder.Complete> {
 
     /**
      * {@link Mqtt3PublishBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete extends Mqtt3PublishBuilder, Mqtt3PublishBuilderBase.Complete<Mqtt3PublishBuilder.Complete> {
 
         /**
@@ -49,7 +49,7 @@ interface Complete extends Mqtt3PublishBuilder, Mqtt3PublishBuilderBase.Complete
      *
      * @param <P> the type of the result when the built {@link Mqtt3Publish} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt3PublishBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -57,7 +57,7 @@ interface Nested<P> extends Mqtt3PublishBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt3Publish} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Mqtt3PublishBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
@@ -70,12 +70,12 @@ interface Complete<P> extends Nested<P>, Mqtt3PublishBuilderBase.Complete<Nested
     }
 
     /**
-     * Builder for a {@link Mqtt3Publish} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client}
+     * Builder for a {@link Mqtt3Publish} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt3.Mqtt3Client}
      * which then sends the Publish message.
      *
      * @param <P> the type of the result when the built {@link Mqtt3Publish} is sent by the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Send<P> extends Mqtt3PublishBuilderBase<Send.Complete<P>> {
 
         /**
@@ -83,7 +83,7 @@ interface Send<P> extends Mqtt3PublishBuilderBase<Send.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt3Publish} is sent by the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Send<P>, Mqtt3PublishBuilderBase.Complete<Send.Complete<P>> {
 
             /**
@@ -94,25 +94,4 @@ interface Complete<P> extends Send<P>, Mqtt3PublishBuilderBase.Complete<Send.Com
             @NotNull P send();
         }
     }
-
-    /**
-     * Builder for a {@link Mqtt3Publish} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client}
-     * which then sends the Publish message without returning a result.
-     */
-    @DoNotImplement
-    interface SendVoid extends Mqtt3PublishBuilderBase<SendVoid.Complete> {
-
-        /**
-         * {@link SendVoid} that is complete which means all mandatory fields are set.
-         */
-        @DoNotImplement
-        interface Complete extends SendVoid, Mqtt3PublishBuilderBase.Complete<SendVoid.Complete> {
-
-            /**
-             * Builds the {@link Mqtt3Publish} and applies it to the parent which then sends the Publish message without
-             * returning a result.
-             */
-            void send();
-        }
-    }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3PublishBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PublishBuilderBase.java
similarity index 88%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3PublishBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PublishBuilderBase.java
index 2db90bbbb..a82a47d17 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3PublishBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PublishBuilderBase.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.publish;
+package com.hivemq.client2.mqtt.mqtt3.message.publish;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
-import com.hivemq.client.mqtt.datatypes.MqttTopicBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -33,7 +33,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3PublishBuilderBase<C extends Mqtt3PublishBuilderBase.Complete<C>> {
 
     /**
@@ -64,14 +64,14 @@ public interface Mqtt3PublishBuilderBase<C extends Mqtt3PublishBuilderBase.Compl
      * @see #topic(MqttTopic)
      */
     @CheckReturnValue
-    MqttTopicBuilder.@NotNull Nested<? extends C> topic();
+    MqttTopicBuilder.@NotNull Nested<? extends C> topicWith();
 
     /**
      * {@link Mqtt3PublishBuilderBase} that is complete which means all mandatory fields are set.
      *
      * @param <C> the type of the complete builder.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete<C extends Mqtt3PublishBuilderBase.Complete<C>> extends Mqtt3PublishBuilderBase<C> {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3PublishResult.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PublishResult.java
similarity index 87%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3PublishResult.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PublishResult.java
index 0ccaaf31f..37896daa5 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3PublishResult.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3PublishResult.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.publish;
+package com.hivemq.client2.mqtt.mqtt3.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -25,12 +25,12 @@
  * Result for an {@link Mqtt3Publish MQTT 3 Publish message} sent by the client.
  * <p>
  * The result is provided if a Publish message is successfully delivered (sent or acknowledged respectively to its
- * {@link com.hivemq.client.mqtt.datatypes.MqttQos QoS} level).
+ * {@link com.hivemq.client2.mqtt.datatypes.MqttQos QoS} level).
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3PublishResult {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3WillPublishBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3WillPublishBuilder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3WillPublishBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3WillPublishBuilder.java
index a6cbe71fb..6cb092ce6 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/publish/Mqtt3WillPublishBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/publish/Mqtt3WillPublishBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.publish;
+package com.hivemq.client2.mqtt.mqtt3.message.publish;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,13 +26,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3WillPublishBuilder extends Mqtt3PublishBuilderBase<Mqtt3WillPublishBuilder.Complete> {
 
     /**
      * {@link Mqtt3WillPublishBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete
             extends Mqtt3WillPublishBuilder, Mqtt3PublishBuilderBase.Complete<Mqtt3WillPublishBuilder.Complete> {
 
@@ -50,7 +50,7 @@ interface Complete
      *
      * @param <P> the type of the result when the built {@link Mqtt3Publish} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt3PublishBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -58,7 +58,7 @@ interface Nested<P> extends Mqtt3PublishBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt3Publish} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Mqtt3PublishBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/suback/Mqtt3SubAck.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubAck.java
similarity index 70%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/suback/Mqtt3SubAck.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubAck.java
index 9637b53ce..359b438be 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/suback/Mqtt3SubAck.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubAck.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.subscribe.suback;
+package com.hivemq.client2.mqtt.mqtt3.message.subscribe;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.List;
 
@@ -31,15 +31,15 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3SubAck extends Mqtt3Message {
 
     /**
-     * @return the Return Codes of this SubAck message, each belonging to a {@link com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscription
-     *         Subscription} in the corresponding {@link com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe
+     * @return the Return Codes of this SubAck message, each belonging to a {@link com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscription
+     *         Subscription} in the corresponding {@link com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe
      *         Subscribe message} in the same order.
      */
-    @Immutable @NotNull List<@NotNull Mqtt3SubAckReturnCode> getReturnCodes();
+    @Unmodifiable @NotNull List<@NotNull Mqtt3SubAckReturnCode> getReturnCodes();
 
     @Override
     default @NotNull Mqtt3MessageType getType() {
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/suback/Mqtt3SubAckReturnCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubAckReturnCode.java
similarity index 95%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/suback/Mqtt3SubAckReturnCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubAckReturnCode.java
index a7f97f7ad..be51fd594 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/suback/Mqtt3SubAckReturnCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubAckReturnCode.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.subscribe.suback;
+package com.hivemq.client2.mqtt.mqtt3.message.subscribe;
 
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3ReturnCode;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3ReturnCode;
 import org.jetbrains.annotations.Nullable;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3Subscribe.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3Subscribe.java
similarity index 76%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3Subscribe.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3Subscribe.java
index 6a7ec9da5..6ad1580c3 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3Subscribe.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3Subscribe.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt3.message.subscribe;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeViewBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscribeViewBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.List;
 
@@ -31,7 +31,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3Subscribe extends Mqtt3Message {
 
     /**
@@ -47,7 +47,7 @@ public interface Mqtt3Subscribe extends Mqtt3Message {
      * @return the {@link Mqtt3Subscription Subscriptions} of this Subscribe message. The list contains at least one
      *         Subscription.
      */
-    @Immutable @NotNull List<@NotNull ? extends Mqtt3Subscription> getSubscriptions();
+    @Unmodifiable @NotNull List<@NotNull ? extends Mqtt3Subscription> getSubscriptions();
 
     @Override
     default @NotNull Mqtt3MessageType getType() {
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilder.java
similarity index 84%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilder.java
index fbc59ba1b..054f32773 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt3.message.subscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,14 +26,15 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3SubscribeBuilder extends Mqtt3SubscribeBuilderBase<Mqtt3SubscribeBuilder.Complete> {
 
     /**
      * {@link Mqtt3SubscribeBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
-    interface Complete extends Mqtt3SubscribeBuilder, Mqtt3SubscribeBuilderBase<Mqtt3SubscribeBuilder.Complete> {
+    @ApiStatus.NonExtendable
+    interface Complete
+            extends Mqtt3SubscribeBuilder, Mqtt3SubscribeBuilderBase.Complete<Mqtt3SubscribeBuilder.Complete> {
 
         /**
          * Builds the {@link Mqtt3Subscribe}.
@@ -47,7 +48,7 @@ interface Complete extends Mqtt3SubscribeBuilder, Mqtt3SubscribeBuilderBase<Mqtt
     /**
      * {@link Mqtt3SubscribeBuilder} that provides additional methods for the first subscription.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Start extends Mqtt3SubscribeBuilder,
             Mqtt3SubscribeBuilderBase.Start<Mqtt3SubscribeBuilder.Complete, Mqtt3SubscribeBuilder.Start.Complete> {
 
@@ -55,7 +56,7 @@ interface Start extends Mqtt3SubscribeBuilder,
          * {@link Mqtt3SubscribeBuilder.Start} that is complete which means all mandatory fields are set.
          */
         // @formatter:off
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete extends Mqtt3SubscribeBuilder.Start, Mqtt3SubscribeBuilder.Complete,
                 Mqtt3SubscribeBuilderBase.Start.Complete<
                         Mqtt3SubscribeBuilder.Complete, Mqtt3SubscribeBuilder.Start.Complete> {}
@@ -67,7 +68,7 @@ interface Complete extends Mqtt3SubscribeBuilder.Start, Mqtt3SubscribeBuilder.Co
      *
      * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt3SubscribeBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -75,8 +76,8 @@ interface Nested<P> extends Mqtt3SubscribeBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is applied to the parent.
          */
-        @DoNotImplement
-        interface Complete<P> extends Nested<P>, Mqtt3SubscribeBuilderBase<Nested.Complete<P>> {
+        @ApiStatus.NonExtendable
+        interface Complete<P> extends Nested<P>, Mqtt3SubscribeBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
              * Builds the {@link Mqtt3Subscribe} and applies it to the parent.
@@ -91,7 +92,7 @@ interface Complete<P> extends Nested<P>, Mqtt3SubscribeBuilderBase<Nested.Comple
          *
          * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Start<P>
                 extends Nested<P>, Mqtt3SubscribeBuilderBase.Start<Nested.Complete<P>, Nested.Start.Complete<P>> {
 
@@ -100,19 +101,19 @@ interface Start<P>
              *
              * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is applied to the parent.
              */
-            @DoNotImplement
+            @ApiStatus.NonExtendable
             interface Complete<P> extends Nested.Start<P>, Nested.Complete<P>,
                     Mqtt3SubscribeBuilderBase.Start.Complete<Nested.Complete<P>, Nested.Start.Complete<P>> {}
         }
     }
 
     /**
-     * Builder for a {@link Mqtt3Subscribe} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client
+     * Builder for a {@link Mqtt3Subscribe} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt3.Mqtt3Client
      * Mqtt3Client} which then sends the Subscribe message.
      *
      * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is sent by the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Send<P> extends Mqtt3SubscribeBuilderBase<Send.Complete<P>> {
 
         /**
@@ -120,8 +121,8 @@ interface Send<P> extends Mqtt3SubscribeBuilderBase<Send.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is sent by the parent.
          */
-        @DoNotImplement
-        interface Complete<P> extends Send<P>, Mqtt3SubscribeBuilderBase<Send.Complete<P>> {
+        @ApiStatus.NonExtendable
+        interface Complete<P> extends Send<P>, Mqtt3SubscribeBuilderBase.Complete<Send.Complete<P>> {
 
             /**
              * Builds the {@link Mqtt3Subscribe} and applies it to the parent which then sends the Subscribe message.
@@ -136,7 +137,7 @@ interface Complete<P> extends Send<P>, Mqtt3SubscribeBuilderBase<Send.Complete<P
          *
          * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is sent by the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Start<P> extends Send<P>, Mqtt3SubscribeBuilderBase.Start<Send.Complete<P>, Send.Start.Complete<P>> {
 
             /**
@@ -144,7 +145,7 @@ interface Start<P> extends Send<P>, Mqtt3SubscribeBuilderBase.Start<Send.Complet
              *
              * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is sent by the parent.
              */
-            @DoNotImplement
+            @ApiStatus.NonExtendable
             interface Complete<P> extends Send.Start<P>, Send.Complete<P>,
                     Mqtt3SubscribeBuilderBase.Start.Complete<Send.Complete<P>, Send.Start.Complete<P>> {}
         }
@@ -152,12 +153,12 @@ interface Complete<P> extends Send.Start<P>, Send.Complete<P>,
 
     /**
      * Builder for a {@link Mqtt3Subscribe} and additional arguments that are applied to a parent {@link
-     * com.hivemq.client.mqtt.mqtt3.Mqtt3Client Mqtt3Client} <code>subscribePublishes</code> call.
+     * com.hivemq.client2.mqtt.mqtt3.Mqtt3Client Mqtt3Client} <code>subscribePublishes</code> call.
      *
      * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is applied to the parent.
      * @since 1.2
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Publishes<P> extends Mqtt3SubscribeBuilderBase<Publishes.Complete<P>> {
 
         /**
@@ -165,16 +166,16 @@ interface Publishes<P> extends Mqtt3SubscribeBuilderBase<Publishes.Complete<P>>
          *
          * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P>
-                extends Publishes<P>, Publishes.Args<P>, Mqtt3SubscribeBuilderBase<Publishes.Complete<P>> {}
+                extends Publishes<P>, AfterComplete<P>, Mqtt3SubscribeBuilderBase.Complete<Publishes.Complete<P>> {}
 
         /**
          * {@link Publishes} that provides additional methods for the first subscription.
          *
          * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Start<P> extends Publishes<P>,
                 Mqtt3SubscribeBuilderBase.Start<Publishes.Complete<P>, Publishes.Start.Complete<P>> {
 
@@ -183,19 +184,19 @@ interface Start<P> extends Publishes<P>,
              *
              * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is applied to the parent.
              */
-            @DoNotImplement
+            @ApiStatus.NonExtendable
             interface Complete<P> extends Publishes.Start<P>, Publishes.Complete<P>,
                     Mqtt3SubscribeBuilderBase.Start.Complete<Publishes.Complete<P>, Publishes.Start.Complete<P>> {}
         }
 
         /**
          * Builder for additional arguments alongside the {@link Mqtt3Subscribe} that are applied to a parent {@link
-         * com.hivemq.client.mqtt.mqtt3.Mqtt3Client Mqtt3Client} <code>subscribePublishes</code> call.
+         * com.hivemq.client2.mqtt.mqtt3.Mqtt3Client Mqtt3Client} <code>subscribePublishes</code> call.
          *
          * @param <P> the type of the result when the built {@link Mqtt3Subscribe} is applied to the parent.
          */
-        @DoNotImplement
-        interface Args<P> {
+        @ApiStatus.NonExtendable
+        interface AfterComplete<P> {
 
             /**
              * Sets whether the matching Publish messages consumed via the subscriptions are acknowledged manually.
@@ -204,7 +205,7 @@ interface Args<P> {
              * @return the builder.
              */
             @CheckReturnValue
-            @NotNull Args<P> manualAcknowledgement(boolean manualAcknowledgement);
+            @NotNull AfterComplete<P> manualAcknowledgement(boolean manualAcknowledgement);
 
             /**
              * Builds the {@link Mqtt3Subscribe} and applies it and additional arguments to the parent.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilderBase.java
similarity index 83%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilderBase.java
index 224a9891f..827389765 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscribeBuilderBase.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt3.message.subscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
@@ -30,8 +30,8 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface Mqtt3SubscribeBuilderBase<C extends Mqtt3SubscribeBuilderBase<C>> {
+@ApiStatus.NonExtendable
+public interface Mqtt3SubscribeBuilderBase<C extends Mqtt3SubscribeBuilderBase.Complete<C>> {
 
     /**
      * Adds a {@link Mqtt3Subscription} to the {@link Mqtt3Subscribe#getSubscriptions() list of subscriptions}. At least
@@ -54,7 +54,7 @@ public interface Mqtt3SubscribeBuilderBase<C extends Mqtt3SubscribeBuilderBase<C
      * @see #addSubscription(Mqtt3Subscription)
      */
     @CheckReturnValue
-    Mqtt3SubscriptionBuilder.@NotNull Nested<? extends C> addSubscription();
+    Mqtt3SubscriptionBuilder.@NotNull Nested<? extends C> addSubscriptionWith();
 
     /**
      * Adds {@link Mqtt3Subscription}s to the {@link Mqtt3Subscribe#getSubscriptions() list of subscriptions}. At least
@@ -89,6 +89,14 @@ public interface Mqtt3SubscribeBuilderBase<C extends Mqtt3SubscribeBuilderBase<C
     @CheckReturnValue
     @NotNull C addSubscriptions(@NotNull Stream<@NotNull ? extends Mqtt3Subscription> subscriptions);
 
+    /**
+     * {@link Mqtt3SubscribeBuilderBase} that is complete which means all mandatory fields are set.
+     *
+     * @param <C> the type of the complete builder.
+     */
+    @ApiStatus.NonExtendable
+    interface Complete<C extends Mqtt3SubscribeBuilderBase.Complete<C>> extends Mqtt3SubscribeBuilderBase<C> {}
+
     /**
      * {@link Mqtt3SubscribeBuilderBase} that provides additional methods for the first subscription.
      *
@@ -96,9 +104,9 @@ public interface Mqtt3SubscribeBuilderBase<C extends Mqtt3SubscribeBuilderBase<C
      * @param <SC> the type of the complete start builder.
      */
     // @formatter:off
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Start<
-            C extends Mqtt3SubscribeBuilderBase<C>,
+            C extends Mqtt3SubscribeBuilderBase.Complete<C>,
             SC extends Mqtt3SubscribeBuilderBase.Start.Complete<C, SC>>
             extends Mqtt3SubscribeBuilderBase<C>, Mqtt3SubscriptionBuilderBase<SC> {
     // @formatter:on
@@ -110,11 +118,12 @@ interface Start<
          * @param <SC> the type of the complete start builder.
          */
         // @formatter:off
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<
-                C extends Mqtt3SubscribeBuilderBase<C>,
+                C extends Mqtt3SubscribeBuilderBase.Complete<C>,
                 SC extends Mqtt3SubscribeBuilderBase.Start.Complete<C, SC>>
-                extends Mqtt3SubscribeBuilderBase.Start<C, SC>, Mqtt3SubscriptionBuilderBase.Complete<SC> {}
+                extends Mqtt3SubscribeBuilderBase.Start<C, SC>, Mqtt3SubscribeBuilderBase.Complete<C>,
+                        Mqtt3SubscriptionBuilderBase.Complete<SC> {}
         // @formatter:on
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3Subscription.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3Subscription.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3Subscription.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3Subscription.java
index 279104057..5bd948180 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3Subscription.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3Subscription.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt3.message.subscribe;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscriptionViewBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3.Mqtt3SubscriptionViewBuilder;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3Subscription {
 
     /**
@@ -52,9 +52,9 @@ public interface Mqtt3Subscription {
     @NotNull MqttTopicFilter getTopicFilter();
 
     /**
-     * @return the QoS of this Subscription.
+     * @return the maximum QoS of this Subscription.
      */
-    @NotNull MqttQos getQos();
+    @NotNull MqttQos getMaxQos();
 
     /**
      * Creates a builder for extending this Subscription.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilder.java
index 0167e8bd3..d6fc076d5 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt3.message.subscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,13 +26,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3SubscriptionBuilder extends Mqtt3SubscriptionBuilderBase<Mqtt3SubscriptionBuilder.Complete> {
 
     /**
      * {@link Mqtt3SubscriptionBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete
             extends Mqtt3SubscriptionBuilder, Mqtt3SubscriptionBuilderBase.Complete<Mqtt3SubscriptionBuilder.Complete> {
 
@@ -50,7 +50,7 @@ interface Complete
      *
      * @param <P> the type of the result when the built {@link Mqtt3Subscription} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt3SubscriptionBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -58,7 +58,7 @@ interface Nested<P> extends Mqtt3SubscriptionBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt3Subscription} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Mqtt3SubscriptionBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilderBase.java
similarity index 81%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilderBase.java
index ed8172ded..98ab6c48b 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubscriptionBuilderBase.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt3.message.subscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilterBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilterBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -30,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3SubscriptionBuilderBase<C extends Mqtt3SubscriptionBuilderBase.Complete<C>> {
 
     /**
@@ -62,23 +62,23 @@ public interface Mqtt3SubscriptionBuilderBase<C extends Mqtt3SubscriptionBuilder
      * @see #topicFilter(MqttTopicFilter)
      */
     @CheckReturnValue
-    MqttTopicFilterBuilder.@NotNull Nested<? extends C> topicFilter();
+    MqttTopicFilterBuilder.@NotNull Nested<? extends C> topicFilterWith();
 
     /**
      * {@link Mqtt3SubscriptionBuilderBase} that is complete which means all mandatory fields are set.
      *
      * @param <C> the type of the complete builder.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete<C extends Mqtt3SubscriptionBuilderBase.Complete<C>> extends Mqtt3SubscriptionBuilderBase<C> {
 
         /**
-         * Sets the {@link Mqtt3Subscription#getQos() QoS}.
+         * Sets the {@link Mqtt3Subscription#getMaxQos() maximum QoS}.
          *
-         * @param qos the QoS.
+         * @param maxQos the maximum QoS.
          * @return the builder.
          */
         @CheckReturnValue
-        @NotNull C qos(@NotNull MqttQos qos);
+        @NotNull C maxQos(@NotNull MqttQos maxQos);
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/unsuback/Mqtt3UnsubAck.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubAck.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/unsuback/Mqtt3UnsubAck.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubAck.java
index aa6c1a04e..b29c84146 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/unsuback/Mqtt3UnsubAck.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubAck.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.unsubscribe.unsuback;
+package com.hivemq.client2.mqtt.mqtt3.message.unsubscribe;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3UnsubAck extends Mqtt3Message {
 
     @Override
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/Mqtt3Unsubscribe.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3Unsubscribe.java
similarity index 74%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/Mqtt3Unsubscribe.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3Unsubscribe.java
index 6f67054d0..34a63413b 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/Mqtt3Unsubscribe.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3Unsubscribe.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.unsubscribe;
+package com.hivemq.client2.mqtt.mqtt3.message.unsubscribe;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeViewBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3Message;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubscribeViewBuilder;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3Message;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.List;
 
@@ -33,7 +33,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3Unsubscribe extends Mqtt3Message {
 
     /**
@@ -48,7 +48,7 @@ public interface Mqtt3Unsubscribe extends Mqtt3Message {
     /**
      * @return the Topic Filters of this Unsubscribe message. The list contains at least one Topic Filter.
      */
-    @Immutable @NotNull List<@NotNull ? extends MqttTopicFilter> getTopicFilters();
+    @Unmodifiable @NotNull List<@NotNull ? extends MqttTopicFilter> getTopicFilters();
 
     @Override
     default @NotNull Mqtt3MessageType getType() {
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilder.java
similarity index 70%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilder.java
index 82bb9f01d..de2e24fb1 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.unsubscribe;
+package com.hivemq.client2.mqtt.mqtt3.message.unsubscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,14 +26,15 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt3UnsubscribeBuilder extends Mqtt3UnsubscribeBuilderBase<Mqtt3UnsubscribeBuilder.Complete> {
 
     /**
      * {@link Mqtt3UnsubscribeBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
-    interface Complete extends Mqtt3UnsubscribeBuilder, Mqtt3UnsubscribeBuilderBase<Mqtt3UnsubscribeBuilder.Complete> {
+    @ApiStatus.NonExtendable
+    interface Complete
+            extends Mqtt3UnsubscribeBuilder, Mqtt3UnsubscribeBuilderBase.Complete<Mqtt3UnsubscribeBuilder.Complete> {
 
         /**
          * Builds the {@link Mqtt3Unsubscribe}.
@@ -47,7 +48,7 @@ interface Complete extends Mqtt3UnsubscribeBuilder, Mqtt3UnsubscribeBuilderBase<
     /**
      * {@link Mqtt3UnsubscribeBuilder} that provides additional methods for the first Topic Filter.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Start
             extends Mqtt3UnsubscribeBuilder, Mqtt3UnsubscribeBuilderBase.Start<Mqtt3UnsubscribeBuilder.Complete> {}
 
@@ -56,7 +57,7 @@ interface Start
      *
      * @param <P> the type of the result when the built {@link Mqtt3Unsubscribe} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt3UnsubscribeBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -64,8 +65,8 @@ interface Nested<P> extends Mqtt3UnsubscribeBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt3Unsubscribe} is applied to the parent.
          */
-        @DoNotImplement
-        interface Complete<P> extends Nested<P>, Mqtt3UnsubscribeBuilderBase<Nested.Complete<P>> {
+        @ApiStatus.NonExtendable
+        interface Complete<P> extends Nested<P>, Mqtt3UnsubscribeBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
              * Builds the {@link Mqtt3Unsubscribe} and applies it to the parent.
@@ -80,17 +81,17 @@ interface Complete<P> extends Nested<P>, Mqtt3UnsubscribeBuilderBase<Nested.Comp
          *
          * @param <P> the type of the result when the built {@link Mqtt3Unsubscribe} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Start<P> extends Nested<P>, Mqtt3UnsubscribeBuilderBase.Start<Nested.Complete<P>> {}
     }
 
     /**
-     * Builder for a {@link Mqtt3Unsubscribe} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client}
+     * Builder for a {@link Mqtt3Unsubscribe} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt3.Mqtt3Client}
      * which then sends the Unsubscribe message.
      *
      * @param <P> the type of the result when the built {@link Mqtt3Unsubscribe} is sent by the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Send<P> extends Mqtt3UnsubscribeBuilderBase<Send.Complete<P>> {
 
         /**
@@ -98,8 +99,8 @@ interface Send<P> extends Mqtt3UnsubscribeBuilderBase<Send.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt3Unsubscribe} is sent by the parent.
          */
-        @DoNotImplement
-        interface Complete<P> extends Send<P>, Mqtt3UnsubscribeBuilderBase<Send.Complete<P>> {
+        @ApiStatus.NonExtendable
+        interface Complete<P> extends Send<P>, Mqtt3UnsubscribeBuilderBase.Complete<Send.Complete<P>> {
 
             /**
              * Builds the {@link Mqtt3Unsubscribe} and applies it to the parent which then sends the Unsubscribe
@@ -115,34 +116,7 @@ interface Complete<P> extends Send<P>, Mqtt3UnsubscribeBuilderBase<Send.Complete
          *
          * @param <P> the type of the result when the built {@link Mqtt3Unsubscribe} is sent by the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Start<P> extends Send<P>, Mqtt3UnsubscribeBuilderBase.Start<Send.Complete<P>> {}
     }
-
-    /**
-     * Builder for a {@link Mqtt3Unsubscribe} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client}
-     * which then sends the Unsubscribe message without returning a result.
-     */
-    @DoNotImplement
-    interface SendVoid extends Mqtt3UnsubscribeBuilderBase<SendVoid.Complete> {
-
-        /**
-         * {@link SendVoid} that is complete which means all mandatory fields are set.
-         */
-        @DoNotImplement
-        interface Complete extends SendVoid, Mqtt3UnsubscribeBuilderBase<SendVoid.Complete> {
-
-            /**
-             * Builds the {@link Mqtt3Unsubscribe} and applies it to the parent which then sends the Unsubscribe message
-             * without returning a result.
-             */
-            void send();
-        }
-
-        /**
-         * {@link SendVoid} that provides additional methods for the first Topic Filter.
-         */
-        @DoNotImplement
-        interface Start extends SendVoid, Mqtt3UnsubscribeBuilderBase.Start<SendVoid.Complete> {}
-    }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilderBase.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilderBase.java
index 17f751dae..c9a24258f 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt3/message/unsubscribe/Mqtt3UnsubscribeBuilderBase.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.unsubscribe;
+package com.hivemq.client2.mqtt.mqtt3.message.unsubscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilterBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilterBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
@@ -33,8 +33,8 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface Mqtt3UnsubscribeBuilderBase<C extends Mqtt3UnsubscribeBuilderBase<C>> {
+@ApiStatus.NonExtendable
+public interface Mqtt3UnsubscribeBuilderBase<C extends Mqtt3UnsubscribeBuilderBase.Complete<C>> {
 
     /**
      * Adds a {@link MqttTopicFilter Topic Filter} to the {@link Mqtt3Unsubscribe#getTopicFilters() list of Topic
@@ -67,7 +67,7 @@ public interface Mqtt3UnsubscribeBuilderBase<C extends Mqtt3UnsubscribeBuilderBa
      * @see #addTopicFilter(MqttTopicFilter)
      */
     @CheckReturnValue
-    MqttTopicFilterBuilder.@NotNull Nested<? extends C> addTopicFilter();
+    MqttTopicFilterBuilder.@NotNull Nested<? extends C> addTopicFilterWith();
 
     /**
      * Adds {@link MqttTopicFilter Topic Filters} to the {@link Mqtt3Unsubscribe#getTopicFilters() list of Topic
@@ -111,13 +111,21 @@ public interface Mqtt3UnsubscribeBuilderBase<C extends Mqtt3UnsubscribeBuilderBa
     @CheckReturnValue
     @NotNull C reverse(@NotNull Mqtt3Subscribe subscribe);
 
+    /**
+     * {@link Mqtt3UnsubscribeBuilderBase} that is complete which means all mandatory fields are set.
+     *
+     * @param <C> the type of the complete builder.
+     */
+    @ApiStatus.NonExtendable
+    interface Complete<C extends Mqtt3UnsubscribeBuilderBase.Complete<C>> extends Mqtt3UnsubscribeBuilderBase<C> {}
+
     /**
      * {@link Mqtt3UnsubscribeBuilderBase} that provides additional methods for the first Topic Filter.
      *
      * @param <C> the type of the complete builder.
      */
-    @DoNotImplement
-    interface Start<C extends Mqtt3UnsubscribeBuilderBase<C>> extends Mqtt3UnsubscribeBuilderBase<C> {
+    @ApiStatus.NonExtendable
+    interface Start<C extends Mqtt3UnsubscribeBuilderBase.Complete<C>> extends Mqtt3UnsubscribeBuilderBase<C> {
 
         /**
          * Sets the mandatory {@link Mqtt3Unsubscribe#getTopicFilters() first Topic Filter}.
@@ -148,6 +156,6 @@ interface Start<C extends Mqtt3UnsubscribeBuilderBase<C>> extends Mqtt3Unsubscri
          * @see #addTopicFilter(MqttTopicFilter)
          */
         @CheckReturnValue
-        MqttTopicFilterBuilder.@NotNull Nested<? extends C> topicFilter();
+        MqttTopicFilterBuilder.@NotNull Nested<? extends C> topicFilterWith();
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5AsyncClient.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5AsyncClient.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5AsyncClient.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5AsyncClient.java
index 5e77444de..5bafc0950 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5AsyncClient.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5AsyncClient.java
@@ -14,25 +14,25 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5;
-
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilderBase;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
+package com.hivemq.client2.mqtt.mqtt5;
+
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilderBase;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.concurrent.CompletableFuture;
@@ -45,7 +45,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5AsyncClient extends Mqtt5Client {
 
     /**
@@ -64,7 +64,7 @@ public interface Mqtt5AsyncClient extends Mqtt5Client {
      *         <ul>
      *           <li>completes normally with the ConnAck message if it does not contain an Error Code (connected
      *             successfully),
-     *           <li>completes exceptionally with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException
+     *           <li>completes exceptionally with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5ConnAckException
      *             Mqtt5ConnAckException} wrapping the ConnAck message if it contains an Error Code or
      *           <li>completes exceptionally with a different exception if an error occurred before the Connect message
      *             was sent or before the ConnAck message was received.
@@ -97,7 +97,7 @@ public interface Mqtt5AsyncClient extends Mqtt5Client {
      *         <ul>
      *           <li>completes normally with the SubAck message if all subscriptions of the Subscribe message were
      *             successful (the SubAck message contains no Error Codes),
-     *           <li>completes exceptionally with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException
+     *           <li>completes exceptionally with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5SubAckException
      *             Mqtt5SubAckException} wrapping the SubAck message if it contains at least one Error Code or
      *           <li>completes exceptionally with a different exception if an error occurred before the Subscribe
      *             message was sent or before a SubAck message was received.
@@ -186,8 +186,8 @@ public interface Mqtt5AsyncClient extends Mqtt5Client {
      * Fluent counterpart of {@link #subscribe(Mqtt5Subscribe)}, {@link #subscribe(Mqtt5Subscribe, Consumer, boolean)}
      * and {@link #subscribe(Mqtt5Subscribe, Consumer, Executor, boolean)}.
      * <p>
-     * Calling {@link Mqtt5SubscribeAndCallbackBuilder.Complete#send()} on the returned builder has the same effect as
-     * calling one of the following methods:
+     * Calling {@link SubscribeBuilder.Complete#send()} on the returned builder has the same effect as calling one of
+     * the following methods:
      * <ul>
      *   <li>{@link #subscribe(Mqtt5Subscribe)} if no callback has been supplied to the builder
      *   <li>{@link #subscribe(Mqtt5Subscribe, Consumer)} if only a callback has been supplied to the builder
@@ -201,7 +201,7 @@ public interface Mqtt5AsyncClient extends Mqtt5Client {
      * @see #subscribe(Mqtt5Subscribe, Consumer, Executor, boolean)
      */
     @CheckReturnValue
-    Mqtt5SubscribeAndCallbackBuilder.@NotNull Start subscribeWith();
+    SubscribeBuilder.@NotNull Start subscribeWith();
 
     /**
      * Globally consumes all incoming Publish messages matching the given filter.
@@ -272,7 +272,7 @@ void publishes(
      *           <li>completes normally with the UnsubAck message if all Topic Filters of the Unsubscribe message were
      *             successfully unsubscribed (the UnsubAck message contains no Error Codes),
      *           <li>completes exceptionally with a
-     *             {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException Mqtt5UnsubAckException}
+     *             {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException Mqtt5UnsubAckException}
      *             wrapping the UnsubAck message if it contains at least one Error Code or
      *           <li>completes exceptionally with a different exception if an error occurred before the Unsubscribe
      *             message was sent or before a UnsubAck message was received.
@@ -301,8 +301,8 @@ void publishes(
      *           <li>completes normally with the {@link Mqtt5PublishResult} if the Publish message was successfully
      *             published (no acknowledgement message contains an Error Code, {@link Mqtt5PublishResult#getError()}
      *             will always be absent),
-     *           <li>completes exceptionally with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5PubAckException
-     *             Mqtt5PubAckException} or {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5PubRecException
+     *           <li>completes exceptionally with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5PubAckException
+     *             Mqtt5PubAckException} or {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5PubRecException
      *             Mqtt5PubRecException} wrapping the acknowledgement message if it contains an Error Code or
      *           <li>completes exceptionally with a different exception if an error occurred before the Publish message
      *             was sent or before an acknowledgement message was received.
@@ -328,7 +328,7 @@ void publishes(
      * @return a {@link CompletableFuture} which
      *         <ul>
      *           <li>completes normally when the client was successfully re-authenticated,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5AuthException Mqtt5AuthException}
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5AuthException Mqtt5AuthException}
      *             wrapping the Auth message with the Error Code if not re-authenticated successfully or
      *           <li>errors with a different exception if an error occurred before the first Auth message was sent or
      *             before the last Auth message was received.
@@ -379,38 +379,31 @@ void publishes(
      * #subscribe(Mqtt5Subscribe)}, {@link #subscribe(Mqtt5Subscribe, Consumer, boolean)} or {@link
      * #subscribe(Mqtt5Subscribe, Consumer, Executor, boolean)} call.
      */
-    @DoNotImplement
-    interface Mqtt5SubscribeAndCallbackBuilder
-            extends Mqtt5SubscribeBuilderBase<Mqtt5SubscribeAndCallbackBuilder.Complete> {
+    @ApiStatus.NonExtendable
+    interface SubscribeBuilder extends Mqtt5SubscribeBuilderBase<SubscribeBuilder.Complete> {
 
         /**
-         * {@link Mqtt5SubscribeAndCallbackBuilder} that is complete which means all mandatory fields are set.
+         * {@link SubscribeBuilder} that is complete which means all mandatory fields are set.
          */
-        @DoNotImplement
-        interface Complete extends Mqtt5SubscribeAndCallbackBuilder, Mqtt5SubscribeAndCallbackBuilder.Call,
-                Mqtt5SubscribeBuilderBase.Complete<Mqtt5SubscribeAndCallbackBuilder.Complete> {}
+        @ApiStatus.NonExtendable
+        interface Complete extends SubscribeBuilder, AfterComplete,
+                Mqtt5SubscribeBuilderBase.Complete<SubscribeBuilder.Complete> {}
 
         /**
-         * {@link Mqtt5SubscribeAndCallbackBuilder} that provides additional methods for the first subscription.
+         * {@link SubscribeBuilder} that provides additional methods for the first subscription.
          */
-        // @formatter:off
-        @DoNotImplement
-        interface Start extends Mqtt5SubscribeAndCallbackBuilder,
-                Mqtt5SubscribeBuilderBase.Start<
-                        Mqtt5SubscribeAndCallbackBuilder.Complete, Mqtt5SubscribeAndCallbackBuilder.Start.Complete> {
-        // @formatter:on
+        @ApiStatus.NonExtendable
+        interface Start extends SubscribeBuilder,
+                Mqtt5SubscribeBuilderBase.Start<SubscribeBuilder.Complete, SubscribeBuilder.Start.Complete> {
 
             /**
-             * {@link Mqtt5SubscribeAndCallbackBuilder.Start} that is complete which means all mandatory fields are
-             * set.
+             * {@link SubscribeBuilder.Start} that is complete which means all mandatory fields are set.
              */
             // @formatter:off
-            @DoNotImplement
-            interface Complete extends
-                    Mqtt5SubscribeAndCallbackBuilder.Start, Mqtt5SubscribeAndCallbackBuilder.Complete,
+            @ApiStatus.NonExtendable
+            interface Complete extends SubscribeBuilder.Start, SubscribeBuilder.Complete,
                     Mqtt5SubscribeBuilderBase.Start.Complete<
-                            Mqtt5SubscribeAndCallbackBuilder.Complete,
-                            Mqtt5SubscribeAndCallbackBuilder.Start.Complete> {}
+                            SubscribeBuilder.Complete, SubscribeBuilder.Start.Complete> {}
             // @formatter:on
         }
 
@@ -419,8 +412,8 @@ interface Complete extends
          * #subscribe(Mqtt5Subscribe, Consumer, boolean)} or {@link #subscribe(Mqtt5Subscribe, Consumer, Executor,
          * boolean)} call.
          */
-        @DoNotImplement
-        interface Call {
+        @ApiStatus.NonExtendable
+        interface AfterComplete {
 
             /**
              * Sets a callback for the matching Publish messages consumed via the subscriptions.
@@ -429,7 +422,7 @@ interface Call {
              * @return the builder.
              */
             @CheckReturnValue
-            @NotNull Ex callback(@NotNull Consumer<Mqtt5Publish> callback);
+            @NotNull AfterCallback callback(@NotNull Consumer<Mqtt5Publish> callback);
 
             /**
              * Builds the {@link Mqtt5Subscribe} and applies it and additional arguments to a {@link
@@ -440,34 +433,34 @@ interface Call {
              *         {@link #subscribe(Mqtt5Subscribe, Consumer, Executor, boolean)}.
              */
             @NotNull CompletableFuture<Mqtt5SubAck> send();
+        }
+
+        /**
+         * Builder for additional arguments alongside the {@link Mqtt5Subscribe} that are applied to a {@link
+         * #subscribe(Mqtt5Subscribe, Consumer, Executor, boolean)} call.
+         */
+        @ApiStatus.NonExtendable
+        interface AfterCallback extends AfterComplete {
+
+            /**
+             * Sets an executor to execute the callback for the matching Publish messages consumed via the
+             * subscriptions.
+             *
+             * @param executor the executor to execute the callback for the matching Publish messages.
+             * @return the builder.
+             */
+            @CheckReturnValue
+            @NotNull AfterCallback executor(@NotNull Executor executor);
 
             /**
-             * Builder for additional arguments alongside the {@link Mqtt5Subscribe} that are applied to a {@link
-             * #subscribe(Mqtt5Subscribe, Consumer, Executor, boolean)} call.
+             * Sets whether the matching Publish messages consumed via the subscriptions are acknowledged manually.
+             *
+             * @param manualAcknowledgement whether the matching Publish messages are acknowledged manually.
+             * @return the builder.
+             * @since 1.2
              */
-            @DoNotImplement
-            interface Ex extends Call {
-
-                /**
-                 * Sets an executor to execute the callback for the matching Publish messages consumed via the
-                 * subscriptions.
-                 *
-                 * @param executor the executor to execute the callback for the matching Publish messages.
-                 * @return the builder.
-                 */
-                @CheckReturnValue
-                @NotNull Ex executor(@NotNull Executor executor);
-
-                /**
-                 * Sets whether the matching Publish messages consumed via the subscriptions are acknowledged manually.
-                 *
-                 * @param manualAcknowledgement whether the matching Publish messages are acknowledged manually.
-                 * @return the builder.
-                 * @since 1.2
-                 */
-                @CheckReturnValue
-                @NotNull Ex manualAcknowledgement(boolean manualAcknowledgement);
-            }
+            @CheckReturnValue
+            @NotNull AfterCallback manualAcknowledgement(boolean manualAcknowledgement);
         }
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5BlockingClient.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5BlockingClient.java
similarity index 75%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5BlockingClient.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5BlockingClient.java
index 50e228347..9fce7773b 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5BlockingClient.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5BlockingClient.java
@@ -14,25 +14,25 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5;
+package com.hivemq.client2.mqtt.mqtt5;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -44,7 +44,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5BlockingClient extends Mqtt5Client {
 
     /**
@@ -60,8 +60,8 @@ public interface Mqtt5BlockingClient extends Mqtt5Client {
      *
      * @param connect the Connect message sent to the broker.
      * @return the ConnAck message if it does not contain an Error Code (connected successfully).
-     * @throws com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException wrapping the ConnAck message if it contains
-     *                                                                       an Error Code.
+     * @throws com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5ConnAckException wrapping the ConnAck message if it
+     *                                                                        contains an Error Code.
      */
     @NotNull Mqtt5ConnAck connect(@NotNull Mqtt5Connect connect);
 
@@ -85,8 +85,8 @@ public interface Mqtt5BlockingClient extends Mqtt5Client {
      * @param subscribe the Subscribe messages sent to the broker.
      * @return the SubAck message if all subscriptions of the Subscribe message were successful (the SubAck message
      *         contains no Error Codes).
-     * @throws com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException wrapping the SubAck message if it contains
-     *                                                                      at least one Error Code.
+     * @throws com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5SubAckException wrapping the SubAck message if it contains
+     *                                                                       at least one Error Code.
      */
     @NotNull Mqtt5SubAck subscribe(@NotNull Mqtt5Subscribe subscribe);
 
@@ -106,23 +106,21 @@ public interface Mqtt5BlockingClient extends Mqtt5Client {
      * Globally consumes all incoming Publish messages matching the given filter.
      *
      * @param filter the filter with which all incoming Publish messages are filtered.
-     * @return a {@link Mqtt5Publishes} instance that can be used to receive the Publish messages on the calling
-     *         thread.
+     * @return a {@link Publishes} instance that can be used to receive the Publish messages on the calling thread.
      * @see #publishes(MqttGlobalPublishFilter, boolean)
      */
-    @NotNull Mqtt5Publishes publishes(final @NotNull MqttGlobalPublishFilter filter);
+    @NotNull Publishes publishes(final @NotNull MqttGlobalPublishFilter filter);
 
     /**
      * Globally consumes all incoming Publish messages matching the given filter.
      *
      * @param filter                the filter with which all incoming Publish messages are filtered.
      * @param manualAcknowledgement whether the Publish messages are acknowledged manually.
-     * @return a {@link Mqtt5Publishes} instance that can be used to receive the Publish messages on the calling
-     *         thread.
+     * @return a {@link Publishes} instance that can be used to receive the Publish messages on the calling thread.
      * @see #publishes(MqttGlobalPublishFilter)
      * @since 1.2
      */
-    @NotNull Mqtt5Publishes publishes(@NotNull MqttGlobalPublishFilter filter, boolean manualAcknowledgement);
+    @NotNull Publishes publishes(@NotNull MqttGlobalPublishFilter filter, boolean manualAcknowledgement);
 
     /**
      * Unsubscribes this client with the given Unsubscribe message.
@@ -130,8 +128,8 @@ public interface Mqtt5BlockingClient extends Mqtt5Client {
      * @param unsubscribe the Unsubscribe message sent to the broker.
      * @return the UnsubAck message if all Topic Filters of the Unsubscribe message were successfully unsubscribed (the
      *         UnsubAck message contains no Error Codes).
-     * @throws com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException wrapping the UnsubAck message if it
-     *                                                                        contains at least one Error Code.
+     * @throws com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException wrapping the UnsubAck message if it
+     *                                                                         contains at least one Error Code.
      */
     @NotNull Mqtt5UnsubAck unsubscribe(@NotNull Mqtt5Unsubscribe unsubscribe);
 
@@ -153,10 +151,10 @@ public interface Mqtt5BlockingClient extends Mqtt5Client {
      * @param publish the Publish message sent to the broker.
      * @return the {@link Mqtt5PublishResult} if the Publish message was successfully published (no acknowledgement
      *         message contains an Error Code, {@link Mqtt5PublishResult#getError()} will always be absent).
-     * @throws com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5PubAckException wrapping the corresponding PubAck message if
-     *                                                                      it contains an Error Code.
-     * @throws com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5PubRecException wrapping the corresponding PubRec message if
-     *                                                                      it contains an Error Code.
+     * @throws com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5PubAckException wrapping the corresponding PubAck message
+     *                                                                       if it contains an Error Code.
+     * @throws com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5PubRecException wrapping the corresponding PubRec message
+     *                                                                       if it contains an Error Code.
      */
     @NotNull Mqtt5PublishResult publish(@NotNull Mqtt5Publish publish);
 
@@ -175,8 +173,8 @@ public interface Mqtt5BlockingClient extends Mqtt5Client {
     /**
      * Re-authenticates this client.
      *
-     * @throws com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5AuthException wrapping the Auth message with the Error Code
-     *                                                                    if not re-authenticated successfully.
+     * @throws com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5AuthException wrapping the Auth message with the Error Code
+     *                                                                     if not re-authenticated successfully.
      */
     void reauth();
 
@@ -215,13 +213,13 @@ public interface Mqtt5BlockingClient extends Mqtt5Client {
     /**
      * Resource which queues incoming Publish messages until they are received.
      */
-    @DoNotImplement
-    interface Mqtt5Publishes extends AutoCloseable {
+    @ApiStatus.NonExtendable
+    interface Publishes extends AutoCloseable {
 
         /**
          * Receives the next incoming Publish message.
          * <ul>
-         *   <li>Might return immediately if there is already a Publish message queued in this {@link Mqtt5Publishes}
+         *   <li>Might return immediately if there is already a Publish message queued in this {@link Publishes}
          *     instance.
          *   <li>Otherwise blocks the calling thread until a Publish message is received.
          * </ul>
@@ -235,7 +233,7 @@ interface Mqtt5Publishes extends AutoCloseable {
         /**
          * Receives the next incoming Publish message.
          * <ul>
-         *   <li>Might return immediately if there is already a Publish message queued in this {@link Mqtt5Publishes}
+         *   <li>Might return immediately if there is already a Publish message queued in this {@link Publishes}
          *     instance.
          *   <li>Otherwise blocks the calling thread until a Publish message is received or the given timeout applies.
          * </ul>
@@ -251,7 +249,7 @@ interface Mqtt5Publishes extends AutoCloseable {
                 throws InterruptedException;
 
         /**
-         * Receives the next incoming Publish message if it is already queued in this {@link Mqtt5Publishes} instance.
+         * Receives the next incoming Publish message if it is already queued in this {@link Publishes} instance.
          *
          * @return an {@link Optional} containing the already queued Publish message, or empty if no Publish message was
          *         already queued.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5Client.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5Client.java
similarity index 88%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5Client.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5Client.java
index bbfbb6cc3..b5f65eb8e 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5Client.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5Client.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5;
+package com.hivemq.client2.mqtt.mqtt5;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.MqttRxClientBuilder;
-import com.hivemq.client.mqtt.MqttClient;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.mqtt.MqttRxClientBuilder;
+import com.hivemq.client2.mqtt.MqttClient;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5Client extends MqttClient {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5ClientBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5ClientBuilder.java
similarity index 77%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5ClientBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5ClientBuilder.java
index d12533716..eac5b6057 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5ClientBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5ClientBuilder.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5;
+package com.hivemq.client2.mqtt.mqtt5;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientBuilderBase;
-import com.hivemq.client.mqtt.mqtt5.advanced.Mqtt5ClientAdvancedConfig;
-import com.hivemq.client.mqtt.mqtt5.advanced.Mqtt5ClientAdvancedConfigBuilder;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuthBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublishBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttClientBuilderBase;
+import com.hivemq.client2.mqtt.mqtt5.advanced.Mqtt5AdvancedConfig;
+import com.hivemq.client2.mqtt.mqtt5.advanced.Mqtt5AdvancedConfigBuilder;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuthBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5WillPublishBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -35,7 +35,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ClientBuilder extends MqttClientBuilderBase<Mqtt5ClientBuilder> {
 
     /**
@@ -45,19 +45,19 @@ public interface Mqtt5ClientBuilder extends MqttClientBuilderBase<Mqtt5ClientBui
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull Mqtt5ClientBuilder advancedConfig(@NotNull Mqtt5ClientAdvancedConfig advancedConfig);
+    @NotNull Mqtt5ClientBuilder advancedConfig(@NotNull Mqtt5AdvancedConfig advancedConfig);
 
     /**
-     * Fluent counterpart of {@link #advancedConfig(Mqtt5ClientAdvancedConfig)}.
+     * Fluent counterpart of {@link #advancedConfig(Mqtt5AdvancedConfig)}.
      * <p>
-     * Calling {@link Mqtt5ClientAdvancedConfigBuilder.Nested#applyAdvancedConfig()} on the returned builder has the
-     * effect of extending the current advanced configuration.
+     * Calling {@link Mqtt5AdvancedConfigBuilder.Nested#applyAdvancedConfig()} on the returned builder has the effect of
+     * extending the current advanced configuration.
      *
      * @return the fluent builder for the advanced configuration.
-     * @see #advancedConfig(Mqtt5ClientAdvancedConfig)
+     * @see #advancedConfig(Mqtt5AdvancedConfig)
      */
     @CheckReturnValue
-    Mqtt5ClientAdvancedConfigBuilder.@NotNull Nested<? extends Mqtt5ClientBuilder> advancedConfig();
+    Mqtt5AdvancedConfigBuilder.@NotNull Nested<? extends Mqtt5ClientBuilder> advancedConfigWith();
 
     /**
      * Sets the optional {@link Mqtt5ClientConfig#getSimpleAuth() simple authentication and/or authorization related
@@ -83,7 +83,7 @@ public interface Mqtt5ClientBuilder extends MqttClientBuilderBase<Mqtt5ClientBui
      * @since 1.1
      */
     @CheckReturnValue
-    Mqtt5SimpleAuthBuilder.@NotNull Nested<? extends Mqtt5ClientBuilder> simpleAuth();
+    Mqtt5SimpleAuthBuilder.@NotNull Nested<? extends Mqtt5ClientBuilder> simpleAuthWith();
 
     /**
      * Sets the {@link Mqtt5ClientConfig#getEnhancedAuthMechanism() enhanced authentication and/or authorization
@@ -119,7 +119,7 @@ public interface Mqtt5ClientBuilder extends MqttClientBuilderBase<Mqtt5ClientBui
      * @since 1.1
      */
     @CheckReturnValue
-    Mqtt5WillPublishBuilder.@NotNull Nested<? extends Mqtt5ClientBuilder> willPublish();
+    Mqtt5WillPublishBuilder.@NotNull Nested<? extends Mqtt5ClientBuilder> willPublishWith();
 
     /**
      * Builds the {@link Mqtt5Client}.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5ClientConfig.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5ClientConfig.java
similarity index 69%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5ClientConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5ClientConfig.java
index 3839aafe5..00edd643d 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5ClientConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5ClientConfig.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5;
+package com.hivemq.client2.mqtt.mqtt5;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientConfig;
-import com.hivemq.client.mqtt.mqtt5.advanced.Mqtt5ClientAdvancedConfig;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
+import com.hivemq.client2.mqtt.MqttClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.advanced.Mqtt5AdvancedConfig;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -32,7 +32,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ClientConfig extends MqttClientConfig {
 
     @Override
@@ -41,16 +41,16 @@ public interface Mqtt5ClientConfig extends MqttClientConfig {
     /**
      * @return the advanced configuration of the client.
      */
-    @NotNull Mqtt5ClientAdvancedConfig getAdvancedConfig();
+    @NotNull Mqtt5AdvancedConfig getAdvancedConfig();
 
     /**
      * Returns the optional simple authentication and/or authorization related data of the client.
      * <p>
-     * It is used as default if {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect#getSimpleAuth()
+     * It is used as default if {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect#getSimpleAuth()
      * Mqtt5Connect.simpleAuth} is not set during connect.
      * <p>
      * Keep in mind that the data is stored with the client in memory. If you want to use it only during connect or if
-     * you use a different token for each connection please set {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect#getSimpleAuth()
+     * you use a different token for each connection please set {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect#getSimpleAuth()
      * Mqtt5Connect.simpleAuth} instead.
      *
      * @return the optional simple authentication and/or authorization related data of the client.
@@ -61,11 +61,11 @@ public interface Mqtt5ClientConfig extends MqttClientConfig {
     /**
      * Returns the optional enhanced authentication and/or authorization mechanism of the client.
      * <p>
-     * It is used as default if {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect#getEnhancedAuthMechanism()
+     * It is used as default if {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect#getEnhancedAuthMechanism()
      * Mqtt5Connect.enhancedAuthMechanism} is not set during connect.
      * <p>
      * Keep in mind that the mechanism is stored with the client in memory. If you use a different mechanism for each
-     * connection please set {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect#getEnhancedAuthMechanism()
+     * connection please set {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect#getEnhancedAuthMechanism()
      * Mqtt5Connect.enhancedAuthMechanism} instead.
      *
      * @return the optional enhanced authentication and/or authorization mechanism of the client.
@@ -76,11 +76,11 @@ public interface Mqtt5ClientConfig extends MqttClientConfig {
     /**
      * Returns the optional Will Publish of the client.
      * <p>
-     * It is used as default if {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect#getWillPublish()
+     * It is used as default if {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect#getWillPublish()
      * Mqtt5Connect.willPublish} is not set during connect.
      * <p>
      * Keep in mind that the Will Publish is stored with the client in memory. If you use a different Will Publish for
-     * each connection please set {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect#getWillPublish()
+     * each connection please set {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect#getWillPublish()
      * Mqtt5Connect.willPublish} instead.
      *
      * @return the optional Will Publish of the client.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5ClientConnectionConfig.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5ClientConnectionConfig.java
similarity index 66%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5ClientConnectionConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5ClientConnectionConfig.java
index e9080c915..3f8979f90 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5ClientConnectionConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5ClientConnectionConfig.java
@@ -14,13 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5;
-
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+package com.hivemq.client2.mqtt.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.util.Optional;
 
@@ -30,13 +33,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ClientConnectionConfig extends MqttClientConnectionConfig {
 
     /**
      * @return the session expiry interval in seconds.
      */
-    long getSessionExpiryInterval();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long getSessionExpiryInterval();
 
     /**
      * @return the optional enhanced auth mechanism that is used for enhanced authentication and/or authorization.
@@ -56,45 +59,45 @@ public interface Mqtt5ClientConnectionConfig extends MqttClientConnectionConfig
     /**
      * Restrictions for messages a {@link Mqtt5Client} receives.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface RestrictionsForServer {
 
         /**
          * Returns the maximum amount of not acknowledged publishes with QoS 1 or 2 the client accepts from the server
          * concurrently.
          * <p>
-         * The value is determined by {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getReceiveMaximum
+         * The value is determined by {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getReceiveMaximum
          * Mqtt5ConnectRestrictions#getReceiveMaximum()}.
          *
          * @return the maximum amount of not acknowledged publishes with QoS 1 or 2 the client accepts from the server
          *         concurrently.
          */
-        int getReceiveMaximum();
+        @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getReceiveMaximum();
 
         /**
          * Returns the maximum packet size the client accepts from the server.
          * <p>
-         * The value is determined by {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getMaximumPacketSize
+         * The value is determined by {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getMaximumPacketSize
          * Mqtt5ConnectRestrictions#getMaximumPacketSize()}.
          *
          * @return the maximum packet size the client accepts from the server.
          */
-        int getMaximumPacketSize();
+        @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int getMaximumPacketSize();
 
         /**
          * Returns the maximum amount of topic aliases the client accepts from the server.
          * <p>
-         * The value is determined by {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getTopicAliasMaximum
+         * The value is determined by {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getTopicAliasMaximum
          * Mqtt5ConnectRestrictions#getTopicAliasMaximum()}.
          *
          * @return the maximum amount of topic aliases the client accepts from the server.
          */
-        int getTopicAliasMaximum();
+        @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getTopicAliasMaximum();
 
         /**
          * Returns whether the client requested problem information from the server.
          * <p>
-         * The value is determined by {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#isRequestProblemInformation
+         * The value is determined by {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#isRequestProblemInformation
          * Mqtt5ConnectRestrictions#isRequestProblemInformation()}.
          *
          * @return whether the client requested problem information from the server.
@@ -104,7 +107,7 @@ interface RestrictionsForServer {
         /**
          * Returns whether the client requested response information from the server.
          * <p>
-         * The value is determined by {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#isRequestResponseInformation
+         * The value is determined by {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#isRequestResponseInformation
          * Mqtt5ConnectRestrictions#isRequestResponseInformation()}.
          *
          * @return whether the client requested response information from the server.
@@ -115,48 +118,48 @@ interface RestrictionsForServer {
     /**
      * Restrictions for messages a {@link Mqtt5Client} sends.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface RestrictionsForClient {
 
         /**
          * Returns the maximum amount of not acknowledged publishes with QoS 1 or 2 the client sends to the server
          * concurrently.
          * <p>
-         * The value is determined by the minimum of {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getSendMaximum
-         * Mqtt5ConnectRestrictions#getSendMaximum()} and {@link com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#getReceiveMaximum()
+         * The value is determined by the minimum of {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getSendMaximum
+         * Mqtt5ConnectRestrictions#getSendMaximum()} and {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions#getReceiveMaximum()
          * MqttConnAckRestrictions#getReceiveMaximum()}.
          *
          * @return the maximum amount of not acknowledged publishes with QoS 1 or 2 the client sends to the server
          *         concurrently.
          */
-        int getSendMaximum();
+        @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getSendMaximum();
 
         /**
          * Returns the maximum packet size the client sends to the server.
          * <p>
-         * The value is determined by the minimum of {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getSendMaximumPacketSize
-         * Mqtt5ConnectRestrictions#getSendMaximumPacketSize()} and {@link com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#getMaximumPacketSize()
+         * The value is determined by the minimum of {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getSendMaximumPacketSize
+         * Mqtt5ConnectRestrictions#getSendMaximumPacketSize()} and {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions#getMaximumPacketSize()
          * MqttConnAckRestrictions#getMaximumPacketSize()}.
          *
          * @return the maximum packet size the client sends to the server.
          */
-        int getSendMaximumPacketSize();
+        @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int getSendMaximumPacketSize();
 
         /**
          * Returns the maximum amount of topic aliases the client sends to the server.
          * <p>
-         * The value is determined by the minimum of {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getSendTopicAliasMaximum
-         * Mqtt5ConnectRestrictions#getSendTopicAliasMaximum()} and {@link com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#getTopicAliasMaximum()
+         * The value is determined by the minimum of {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions#getSendTopicAliasMaximum
+         * Mqtt5ConnectRestrictions#getSendTopicAliasMaximum()} and {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions#getTopicAliasMaximum()
          * MqttConnAckRestrictions#getTopicAliasMaximum()}.
          *
          * @return the maximum amount of topic aliases the client sends to the server.
          */
-        int getSendTopicAliasMaximum();
+        @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getSendTopicAliasMaximum();
 
         /**
          * Returns the maximum {@link MqttQos QoS} the server accepts from the client.
          * <p>
-         * The value is determined by {@link com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#getMaximumQos()
+         * The value is determined by {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions#getMaximumQos()
          * MqttConnAckRestrictions#getMaximumQos()}.
          *
          * @return the maximum QoS the server accepts from the client.
@@ -166,7 +169,7 @@ interface RestrictionsForClient {
         /**
          * Returns whether the server accepts retained messages from the client.
          * <p>
-         * The value is determined by {@link com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#isRetainAvailable()
+         * The value is determined by {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions#isRetainAvailable()
          * MqttConnAckRestrictions#isRetainAvailable()}.
          *
          * @return whether the server accepts retained messages from the client.
@@ -176,7 +179,7 @@ interface RestrictionsForClient {
         /**
          * Returns whether the server accepts wildcard subscriptions from the client.
          * <p>
-         * The value is determined by {@link com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#isWildcardSubscriptionAvailable()
+         * The value is determined by {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions#isWildcardSubscriptionAvailable()
          * MqttConnAckRestrictions#isWildcardSubscriptionAvailable()}.
          *
          * @return whether the server accepts wildcard subscriptions.
@@ -186,7 +189,7 @@ interface RestrictionsForClient {
         /**
          * Returns whether the server accepts shared subscriptions from the client.
          * <p>
-         * The value is determined by {@link com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#isSharedSubscriptionAvailable()
+         * The value is determined by {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions#isSharedSubscriptionAvailable()
          * MqttConnAckRestrictions#isSharedSubscriptionAvailable()}.
          *
          * @return whether the server accepts shared subscriptions from the client.
@@ -196,7 +199,7 @@ interface RestrictionsForClient {
         /**
          * Returns whether the server accepts subscription identifiers from the client.
          * <p>
-         * The value is determined by {@link com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#areSubscriptionIdentifiersAvailable()
+         * The value is determined by {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions#areSubscriptionIdentifiersAvailable()
          * MqttConnAckRestrictions#areSubscriptionIdentifiersAvailable()}.
          *
          * @return whether the server accepts subscription identifiers from the client.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5RxClient.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5RxClient.java
similarity index 84%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5RxClient.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5RxClient.java
index 9fae6f419..465e6ccbd 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/Mqtt5RxClient.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/Mqtt5RxClient.java
@@ -14,29 +14,30 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5;
+package com.hivemq.client2.mqtt.mqtt5;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
-import com.hivemq.client.rx.FlowableWithSingle;
-import io.reactivex.Completable;
-import io.reactivex.Flowable;
-import io.reactivex.Single;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PublishResult;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder;
+import com.hivemq.client2.rx.FlowableWithSingle;
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.Single;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.reactivestreams.Publisher;
 
 /**
  * Reactive API of an {@link Mqtt5Client}.
@@ -44,7 +45,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5RxClient extends Mqtt5Client {
 
     /**
@@ -67,7 +68,7 @@ public interface Mqtt5RxClient extends Mqtt5Client {
      * @return the {@link Single} which
      *         <ul>
      *           <li>succeeds with the ConnAck message if it does not contain an Error Code (connected successfully),
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5ConnAckException
      *             Mqtt5ConnAckException} wrapping the ConnAck message if it contains an Error Code or
      *           <li>errors with a different exception if an error occurred before the Connect message was sent or
      *             before the ConnAck message was received.
@@ -104,7 +105,7 @@ public interface Mqtt5RxClient extends Mqtt5Client {
      *         <ul>
      *           <li>succeeds with the SubAck message if at least one subscription of the Subscribe message was
      *             successful (the SubAck message contains at least one Reason Code that is not an Error Code),
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5SubAckException
      *             Mqtt5SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent or
      *             before a SubAck message was received.
@@ -126,25 +127,6 @@ public interface Mqtt5RxClient extends Mqtt5Client {
     @CheckReturnValue
     Mqtt5SubscribeBuilder.Nested.@NotNull Start<Single<Mqtt5SubAck>> subscribeWith();
 
-    /**
-     * Use {@link #subscribePublishes(Mqtt5Subscribe)}.
-     *
-     * @param subscribe use {@link #subscribePublishes(Mqtt5Subscribe)}.
-     * @return use {@link #subscribePublishes(Mqtt5Subscribe)}.
-     * @deprecated use {@link #subscribePublishes(Mqtt5Subscribe)}.
-     */
-    @Deprecated
-    @NotNull FlowableWithSingle<Mqtt5Publish, Mqtt5SubAck> subscribeStream(@NotNull Mqtt5Subscribe subscribe);
-
-    /**
-     * Use {@link #subscribePublishesWith()}.
-     *
-     * @return use {@link #subscribePublishesWith()}.
-     * @deprecated use {@link #subscribePublishesWith()}.
-     */
-    @Deprecated
-    Mqtt5SubscribeBuilder.Nested.@NotNull Start<FlowableWithSingle<Mqtt5Publish, Mqtt5SubAck>> subscribeStreamWith();
-
     /**
      * Creates a {@link FlowableWithSingle} for subscribing this client with the given Subscribe message.
      * <p>
@@ -161,11 +143,11 @@ public interface Mqtt5RxClient extends Mqtt5Client {
      *             Error Code) and then emits the Publish messages matching the successful subscriptions of the
      *             Subscribe message,
      *           <li>completes when all subscriptions of the Subscribe message were unsubscribed,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5SubAckException
      *             Mqtt5SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent,
      *             before a SubAck message was received or when a error occurs before all subscriptions of the Subscribe
-     *             message were unsubscribed (e.g. {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *             message were unsubscribed (e.g. {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException}).
      *         </ul>
      * @see #subscribePublishes(Mqtt5Subscribe, boolean)
@@ -191,11 +173,11 @@ public interface Mqtt5RxClient extends Mqtt5Client {
      *             Error Code) and then emits the Publish messages matching the successful subscriptions of the
      *             Subscribe message,
      *           <li>completes when all subscriptions of the Subscribe message were unsubscribed,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5SubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5SubAckException
      *             Mqtt5SubAckException} wrapping the SubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Subscribe message was sent,
      *             before a SubAck message was received or when a error occurs before all subscriptions of the Subscribe
-     *             message were unsubscribed (e.g. {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *             message were unsubscribed (e.g. {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException}).
      *         </ul>
      * @see #subscribePublishes(Mqtt5Subscribe)
@@ -231,7 +213,7 @@ public interface Mqtt5RxClient extends Mqtt5Client {
      *         <ul>
      *           <li>emits the incoming Publish messages matching the given filter,
      *           <li>never completes but
-     *           <li>errors with a {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException} when the MQTT session expires.
      *         </ul>
      * @see #publishes(MqttGlobalPublishFilter, boolean)
@@ -252,7 +234,7 @@ public interface Mqtt5RxClient extends Mqtt5Client {
      *         <ul>
      *           <li>emits the incoming Publish messages matching the given filter,
      *           <li>never completes but
-     *           <li>errors with a {@link com.hivemq.client.mqtt.exceptions.MqttSessionExpiredException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.exceptions.MqttSessionExpiredException
      *             MqttSessionExpiredException} when the MQTT session expires.
      *         </ul>
      * @see #publishes(MqttGlobalPublishFilter)
@@ -274,7 +256,7 @@ public interface Mqtt5RxClient extends Mqtt5Client {
      *           <li>succeeds with the UnsubAck message if at least one Topic Filter of the Unsubscribe message was
      *             successfully unsubscribed (the UnsubAck message contains at least one Reason Code that is not an
      *             Error Code),
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5UnsubAckException
      *             Mqtt5UnsubAckException} wrapping the UnsubAck message if it only contains Error Codes or
      *           <li>errors with a different exception if an error occurred before the Unsubscribe message was sent or
      *             before a UnsubAck message was received.
@@ -304,7 +286,7 @@ public interface Mqtt5RxClient extends Mqtt5Client {
      * Publishing is performed lazy and asynchronous. When subscribing (in terms of Reactive Streams) to the returned
      * {@link Flowable} the client subscribes (in terms of Reactive Streams) to the given {@link Flowable}.
      *
-     * @param publishFlowable the source of the Publish messages to publish.
+     * @param publisher the source of the Publish messages to publish.
      * @return the {@link Flowable} which
      *         <ul>
      *           <li>emits {@link Mqtt5PublishResult}s each corresponding to a Publish message,
@@ -315,7 +297,7 @@ public interface Mqtt5RxClient extends Mqtt5Client {
      *         </ul>
      */
     @CheckReturnValue
-    @NotNull Flowable<Mqtt5PublishResult> publish(@NotNull Flowable<Mqtt5Publish> publishFlowable);
+    @NotNull Flowable<Mqtt5PublishResult> publish(@NotNull Publisher<Mqtt5Publish> publisher);
 
     /**
      * Creates a {@link Completable} for re-authenticating this client.
@@ -326,7 +308,7 @@ public interface Mqtt5RxClient extends Mqtt5Client {
      * @return the {@link Completable} which
      *         <ul>
      *           <li>completes when the client was successfully re-authenticated,
-     *           <li>errors with a {@link com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5AuthException Mqtt5AuthException}
+     *           <li>errors with a {@link com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5AuthException Mqtt5AuthException}
      *             wrapping the Auth message with the Error Code if not re-authenticated successfully or
      *           <li>errors with a different exception if an error occurred before the first Auth message was sent or
      *             before the last Auth message was received.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/Mqtt5ClientAdvancedConfig.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/Mqtt5AdvancedConfig.java
similarity index 64%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/Mqtt5ClientAdvancedConfig.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/Mqtt5AdvancedConfig.java
index 6e6260ddb..3e2c56771 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/Mqtt5ClientAdvancedConfig.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/Mqtt5AdvancedConfig.java
@@ -14,39 +14,34 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.advanced;
+package com.hivemq.client2.mqtt.mqtt5.advanced;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.advanced.MqttClientAdvancedConfigBuilder;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptors;
+import com.hivemq.client2.internal.mqtt.advanced.MqttAdvancedConfigBuilder;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptors;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
- * Advanced configuration of an {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client Mqtt5Client}.
+ * Advanced configuration of an {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client Mqtt5Client}.
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface Mqtt5ClientAdvancedConfig {
+@ApiStatus.NonExtendable
+public interface Mqtt5AdvancedConfig {
 
     /**
      * Creates a builder for an advanced configuration.
      *
      * @return the created builder for an advanced configuration.
      */
-    static @NotNull Mqtt5ClientAdvancedConfigBuilder builder() {
-        return new MqttClientAdvancedConfigBuilder.Default();
+    static @NotNull Mqtt5AdvancedConfigBuilder builder() {
+        return new MqttAdvancedConfigBuilder.Default();
     }
 
     /**
-     * @return whether server re-authentication is allowed.
-     */
-    boolean isAllowServerReAuth();
-
-    /**
-     * Returns whether the payload format is validated if {@link com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish#getPayloadFormatIndicator
+     * Returns whether the payload format is validated if {@link com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish#getPayloadFormatIndicator
      * Mqtt5Publish#getPayloadFormatIndicator()} is present.
      *
      * @return whether the payload format is validated.
@@ -64,5 +59,5 @@ public interface Mqtt5ClientAdvancedConfig {
      * @return the created builder.
      * @since 1.1
      */
-    @NotNull Mqtt5ClientAdvancedConfigBuilder extend();
+    @NotNull Mqtt5AdvancedConfigBuilder extend();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/MqttClientSslConfigBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/Mqtt5AdvancedConfigBuilder.java
similarity index 51%
rename from src/main/java/com/hivemq/client/mqtt/MqttClientSslConfigBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/Mqtt5AdvancedConfigBuilder.java
index 9507de510..6addfc126 100644
--- a/src/main/java/com/hivemq/client/mqtt/MqttClientSslConfigBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/Mqtt5AdvancedConfigBuilder.java
@@ -14,42 +14,42 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt.mqtt5.advanced;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * Builder for a {@link MqttClientSslConfig}.
+ * Builder for a {@link Mqtt5AdvancedConfig}.
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface MqttClientSslConfigBuilder extends MqttClientSslConfigBuilderBase<MqttClientSslConfigBuilder> {
+@ApiStatus.NonExtendable
+public interface Mqtt5AdvancedConfigBuilder extends Mqtt5AdvancedConfigBuilderBase<Mqtt5AdvancedConfigBuilder> {
 
     /**
-     * Builds the {@link MqttClientSslConfig}.
+     * Builds the {@link Mqtt5AdvancedConfig}.
      *
-     * @return the built {@link MqttClientSslConfig}.
+     * @return the built {@link Mqtt5AdvancedConfig}.
      */
     @CheckReturnValue
-    @NotNull MqttClientSslConfig build();
+    @NotNull Mqtt5AdvancedConfig build();
 
     /**
-     * Builder for a {@link MqttClientSslConfig} that is applied to a parent.
+     * Builder for a {@link Mqtt5AdvancedConfig} that is applied to a parent.
      *
-     * @param <P> the type of the result when the built {@link MqttClientSslConfig} is applied to the parent.
+     * @param <P> the type of the result when the built {@link Mqtt5AdvancedConfig} is applied to the parent.
      */
-    @DoNotImplement
-    interface Nested<P> extends MqttClientSslConfigBuilderBase<Nested<P>> {
+    @ApiStatus.NonExtendable
+    interface Nested<P> extends Mqtt5AdvancedConfigBuilderBase<Nested<P>> {
 
         /**
-         * Builds the {@link MqttClientSslConfig} and applies it to the parent.
+         * Builds the {@link Mqtt5AdvancedConfig} and applies it to the parent.
          *
-         * @return the result when the built {@link MqttClientSslConfig} is applied to the parent.
+         * @return the result when the built {@link Mqtt5AdvancedConfig} is applied to the parent.
          */
-        @NotNull P applySslConfig();
+        @NotNull P applyAdvancedConfig();
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/Mqtt5ClientAdvancedConfigBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/Mqtt5AdvancedConfigBuilderBase.java
similarity index 67%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/Mqtt5ClientAdvancedConfigBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/Mqtt5AdvancedConfigBuilderBase.java
index ce3718fa5..5d378ee9c 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/Mqtt5ClientAdvancedConfigBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/Mqtt5AdvancedConfigBuilderBase.java
@@ -14,36 +14,27 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.advanced;
+package com.hivemq.client2.mqtt.mqtt5.advanced;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptors;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptorsBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptors;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.Mqtt5ClientInterceptorsBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
- * Builder base for a {@link Mqtt5ClientAdvancedConfig}.
+ * Builder base for a {@link Mqtt5AdvancedConfig}.
  *
  * @param <B> the type of the builder.
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface Mqtt5ClientAdvancedConfigBuilderBase<B extends Mqtt5ClientAdvancedConfigBuilderBase<B>> {
+@ApiStatus.NonExtendable
+public interface Mqtt5AdvancedConfigBuilderBase<B extends Mqtt5AdvancedConfigBuilderBase<B>> {
 
     /**
-     * Sets whether {@link Mqtt5ClientAdvancedConfig#isAllowServerReAuth() server re-auth is allowed}.
-     *
-     * @param allowServerReAuth whether server re-auth is allowed.
-     * @return the builder.
-     */
-    @CheckReturnValue
-    @NotNull B allowServerReAuth(boolean allowServerReAuth);
-
-    /**
-     * Sets whether {@link Mqtt5ClientAdvancedConfig#isValidatePayloadFormat() the payload format is validated}.
+     * Sets whether {@link Mqtt5AdvancedConfig#isValidatePayloadFormat() the payload format is validated}.
      *
      * @param validatePayloadFormat whether the payload format is validated.
      * @return the builder.
@@ -71,5 +62,5 @@ public interface Mqtt5ClientAdvancedConfigBuilderBase<B extends Mqtt5ClientAdvan
      * @see #interceptors(Mqtt5ClientInterceptors)
      */
     @CheckReturnValue
-    Mqtt5ClientInterceptorsBuilder.@NotNull Nested<? extends B> interceptors();
+    Mqtt5ClientInterceptorsBuilder.@NotNull Nested<? extends B> interceptorsWith();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptors.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptors.java
similarity index 60%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptors.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptors.java
index 05d748b2d..b5f612c5d 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptors.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptors.java
@@ -14,25 +14,25 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.advanced.interceptor;
-
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.advanced.interceptor.MqttClientInterceptorsBuilder;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5IncomingQos1Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5OutgoingQos1Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5IncomingQos2Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5OutgoingQos2Interceptor;
+package com.hivemq.client2.mqtt.mqtt5.advanced.interceptor;
+
+import com.hivemq.client2.internal.mqtt.advanced.interceptor.MqttClientInterceptorsBuilder;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5InboundQos1Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5OutboundQos1Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5InboundQos2Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5OutboundQos2Interceptor;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
- * Collection of interceptors of MQTT messages received or sent by an {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client
+ * Collection of interceptors of MQTT messages received or sent by an {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client
  * MQTT5Client}.
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ClientInterceptors {
 
     /**
@@ -44,13 +44,13 @@ public interface Mqtt5ClientInterceptors {
         return new MqttClientInterceptorsBuilder.Default();
     }
 
-    @Nullable Mqtt5IncomingQos1Interceptor getIncomingQos1Interceptor();
+    @Nullable Mqtt5InboundQos1Interceptor getInboundQos1Interceptor();
 
-    @Nullable Mqtt5OutgoingQos1Interceptor getOutgoingQos1Interceptor();
+    @Nullable Mqtt5OutboundQos1Interceptor getOutboundQos1Interceptor();
 
-    @Nullable Mqtt5IncomingQos2Interceptor getIncomingQos2Interceptor();
+    @Nullable Mqtt5InboundQos2Interceptor getInboundQos2Interceptor();
 
-    @Nullable Mqtt5OutgoingQos2Interceptor getOutgoingQos2Interceptor();
+    @Nullable Mqtt5OutboundQos2Interceptor getOutboundQos2Interceptor();
 
     /**
      * Creates a builder for extending this collection of interceptors.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilder.java
similarity index 88%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilder.java
index 6665c6b8e..f0ad6e64f 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.advanced.interceptor;
+package com.hivemq.client2.mqtt.mqtt5.advanced.interceptor;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,7 +26,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ClientInterceptorsBuilder
         extends Mqtt5ClientInterceptorsBuilderBase<Mqtt5ClientInterceptorsBuilder> {
 
@@ -43,7 +43,7 @@ public interface Mqtt5ClientInterceptorsBuilder
      *
      * @param <P> the type of the result when the built {@link Mqtt5ClientInterceptors} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5ClientInterceptorsBuilderBase<Nested<P>> {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilderBase.java
similarity index 56%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilderBase.java
index b777e1b6d..40fb9f5bf 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/Mqtt5ClientInterceptorsBuilderBase.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.advanced.interceptor;
+package com.hivemq.client2.mqtt.mqtt5.advanced.interceptor;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5IncomingQos1Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5OutgoingQos1Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5IncomingQos2Interceptor;
-import com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5OutgoingQos2Interceptor;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5InboundQos1Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1.Mqtt5OutboundQos1Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5InboundQos2Interceptor;
+import com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2.Mqtt5OutboundQos2Interceptor;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -32,18 +32,18 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ClientInterceptorsBuilderBase<B extends Mqtt5ClientInterceptorsBuilderBase<B>> {
 
     @CheckReturnValue
-    @NotNull B incomingQos1Interceptor(@Nullable Mqtt5IncomingQos1Interceptor incomingQos1Interceptor);
+    @NotNull B inboundQos1Interceptor(@Nullable Mqtt5InboundQos1Interceptor incomingQos1Interceptor);
 
     @CheckReturnValue
-    @NotNull B outgoingQos1Interceptor(@Nullable Mqtt5OutgoingQos1Interceptor outgoingQos1Interceptor);
+    @NotNull B outboundQos1Interceptor(@Nullable Mqtt5OutboundQos1Interceptor outgoingQos1Interceptor);
 
     @CheckReturnValue
-    @NotNull B incomingQos2Interceptor(@Nullable Mqtt5IncomingQos2Interceptor incomingQos2Interceptor);
+    @NotNull B inboundQos2Interceptor(@Nullable Mqtt5InboundQos2Interceptor incomingQos2Interceptor);
 
     @CheckReturnValue
-    @NotNull B outgoingQos2Interceptor(@Nullable Mqtt5OutgoingQos2Interceptor outgoingQos2Interceptor);
+    @NotNull B outboundQos2Interceptor(@Nullable Mqtt5OutboundQos2Interceptor outgoingQos2Interceptor);
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5IncomingQos1Interceptor.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5InboundQos1Interceptor.java
similarity index 78%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5IncomingQos1Interceptor.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5InboundQos1Interceptor.java
index f1f1451b0..34952e856 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5IncomingQos1Interceptor.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5InboundQos1Interceptor.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1;
+package com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1;
 
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAckBuilder;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAckBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -27,7 +28,8 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-public interface Mqtt5IncomingQos1Interceptor {
+@ApiStatus.OverrideOnly
+public interface Mqtt5InboundQos1Interceptor {
 
     /**
      * Called when a server sent a Publish message with QoS 1.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5OutgoingQos1Interceptor.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5OutboundQos1Interceptor.java
similarity index 77%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5OutgoingQos1Interceptor.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5OutboundQos1Interceptor.java
index c1a03cb16..45d13c7a4 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5OutgoingQos1Interceptor.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos1/Mqtt5OutboundQos1Interceptor.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos1;
+package com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos1;
 
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAck;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -27,7 +28,8 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-public interface Mqtt5OutgoingQos1Interceptor {
+@ApiStatus.OverrideOnly
+public interface Mqtt5OutboundQos1Interceptor {
 
     /**
      * Called when a server sent a PubAck message for a Publish message with QoS 1.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5IncomingQos2Interceptor.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5InboundQos2Interceptor.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5IncomingQos2Interceptor.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5InboundQos2Interceptor.java
index f7a7e5ade..a8445b476 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5IncomingQos2Interceptor.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5InboundQos2Interceptor.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2;
+package com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2;
 
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRel;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRel;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -29,7 +30,8 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-public interface Mqtt5IncomingQos2Interceptor {
+@ApiStatus.OverrideOnly
+public interface Mqtt5InboundQos2Interceptor {
 
     /**
      * Called when a server sent a Publish message with QoS 2.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5OutgoingQos2Interceptor.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5OutboundQos2Interceptor.java
similarity index 82%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5OutgoingQos2Interceptor.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5OutboundQos2Interceptor.java
index c240563be..1592f2d5d 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5OutgoingQos2Interceptor.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/advanced/interceptor/qos2/Mqtt5OutboundQos2Interceptor.java
@@ -14,14 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.advanced.interceptor.qos2;
+package com.hivemq.client2.mqtt.mqtt5.advanced.interceptor.qos2;
 
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubComp;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRec;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRel;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelBuilder;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.*;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -30,7 +27,8 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-public interface Mqtt5OutgoingQos2Interceptor {
+@ApiStatus.OverrideOnly
+public interface Mqtt5OutboundQos2Interceptor {
 
     /**
      * Called when a server sent a PubRec message for a Publish message with QoS 2.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/auth/Mqtt5EnhancedAuthMechanism.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/auth/Mqtt5EnhancedAuthMechanism.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/auth/Mqtt5EnhancedAuthMechanism.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/auth/Mqtt5EnhancedAuthMechanism.java
index d8fc531b4..f15f16b6b 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/auth/Mqtt5EnhancedAuthMechanism.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/auth/Mqtt5EnhancedAuthMechanism.java
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.auth;
-
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5Auth;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuthBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+package com.hivemq.client2.mqtt.mqtt5.auth;
+
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5Auth;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuthBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.concurrent.CompletableFuture;
@@ -53,6 +54,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
+@ApiStatus.OverrideOnly
 public interface Mqtt5EnhancedAuthMechanism {
 
     /**
@@ -93,8 +95,7 @@ public interface Mqtt5EnhancedAuthMechanism {
      * Called when a server reauthenticates a client and the client used this enhanced auth mechanism during
      * connection.
      * <p>
-     * This is an addition to the MQTT 5 specification and so defaults to {@link #onReAuth(Mqtt5ClientConfig,
-     * Mqtt5AuthBuilder)}. The feature must be explicitly enabled during client creation.
+     * This is an addition to the MQTT 5 specification. The default denies the reauthentication.
      *
      * @param clientConfig the config of the client.
      * @param auth         the Auth message sent by the server.
@@ -107,7 +108,7 @@ public interface Mqtt5EnhancedAuthMechanism {
             final @NotNull Mqtt5Auth auth,
             final @NotNull Mqtt5AuthBuilder authBuilder) {
 
-        return onReAuth(clientConfig, authBuilder).thenApply(aVoid -> true);
+        return CompletableFuture.completedFuture(false);
     }
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserProperties.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserProperties.java
similarity index 83%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserProperties.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserProperties.java
index ec250aee0..1c7a8a9b8 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserProperties.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserProperties.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.datatypes;
+package com.hivemq.client2.mqtt.mqtt5.datatypes;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImplBuilder;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.Collection;
 import java.util.List;
@@ -32,7 +32,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5UserProperties {
 
     /**
@@ -74,7 +74,7 @@ public interface Mqtt5UserProperties {
     /**
      * @return the User Properties as an immutable list.
      */
-    @Immutable @NotNull List<@NotNull ? extends Mqtt5UserProperty> asList();
+    @Unmodifiable @NotNull List<@NotNull ? extends Mqtt5UserProperty> asList();
 
     /**
      * @return a builder for extending this collection of User Properties.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilder.java
similarity index 88%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilder.java
index 65852ed28..049cb22db 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.datatypes;
+package com.hivemq.client2.mqtt.mqtt5.datatypes;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,7 +26,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5UserPropertiesBuilder extends Mqtt5UserPropertiesBuilderBase<Mqtt5UserPropertiesBuilder> {
 
     /**
@@ -42,7 +42,7 @@ public interface Mqtt5UserPropertiesBuilder extends Mqtt5UserPropertiesBuilderBa
      *
      * @param <P> the type of the result when the built {@link Mqtt5UserProperties} are applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5UserPropertiesBuilderBase<Nested<P>> {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilderBase.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilderBase.java
index d146ac004..7ae9479ae 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserPropertiesBuilderBase.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.datatypes;
+package com.hivemq.client2.mqtt.mqtt5.datatypes;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
@@ -31,7 +31,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5UserPropertiesBuilderBase<B extends Mqtt5UserPropertiesBuilderBase<B>> {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserProperty.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserProperty.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserProperty.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserProperty.java
index 29f9861e8..98ad49837 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/datatypes/Mqtt5UserProperty.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/datatypes/Mqtt5UserProperty.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.datatypes;
+package com.hivemq.client2.mqtt.mqtt5.datatypes;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.util.MqttChecks;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.util.MqttChecks;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -30,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5UserProperty extends Comparable<Mqtt5UserProperty> {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5AuthException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5AuthException.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5AuthException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5AuthException.java
index e81c394e9..c2db3f388 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5AuthException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5AuthException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5Auth;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5Auth;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5ConnAckException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5ConnAckException.java
similarity index 91%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5ConnAckException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5ConnAckException.java
index 5e99c47b9..b3b79307d 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5ConnAckException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5ConnAckException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5DisconnectException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5DisconnectException.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5DisconnectException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5DisconnectException.java
index 19cf7bead..106e213df 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5DisconnectException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5DisconnectException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5MessageException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5MessageException.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5MessageException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5MessageException.java
index 779bf0612..b98acaf28 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5MessageException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5MessageException.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubAckException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubAckException.java
similarity index 91%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubAckException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubAckException.java
index ce168449f..bd137bb1d 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubAckException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubAckException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAck;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubRecException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubRecException.java
similarity index 91%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubRecException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubRecException.java
index 7c739a21e..79b31d969 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubRecException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubRecException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRec;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRec;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5SubAckException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5SubAckException.java
similarity index 91%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5SubAckException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5SubAckException.java
index 06d48c363..4d59a026d 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5SubAckException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5SubAckException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5UnsubAckException.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5UnsubAckException.java
similarity index 91%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5UnsubAckException.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5UnsubAckException.java
index fed3be97a..570b7fc6c 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5UnsubAckException.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5UnsubAckException.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/lifecycle/Mqtt5ClientConnectedContext.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/lifecycle/Mqtt5ConnectedContext.java
similarity index 64%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/lifecycle/Mqtt5ClientConnectedContext.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/lifecycle/Mqtt5ConnectedContext.java
index cb27d8dfc..f46466943 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/lifecycle/Mqtt5ClientConnectedContext.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/lifecycle/Mqtt5ConnectedContext.java
@@ -14,24 +14,24 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.lifecycle;
+package com.hivemq.client2.mqtt.mqtt5.lifecycle;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedContext;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.lifecycle.MqttConnectedContext;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * A {@link MqttClientConnectedContext} with methods specific to an {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client
+ * A {@link MqttConnectedContext} with methods specific to an {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client
  * Mqtt5Client}.
  *
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface Mqtt5ClientConnectedContext extends MqttClientConnectedContext {
+@ApiStatus.NonExtendable
+public interface Mqtt5ConnectedContext extends MqttConnectedContext {
 
     @Override
     @NotNull Mqtt5ClientConfig getClientConfig();
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/lifecycle/Mqtt5ClientDisconnectedContext.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/lifecycle/Mqtt5DisconnectedContext.java
similarity index 61%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/lifecycle/Mqtt5ClientDisconnectedContext.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/lifecycle/Mqtt5DisconnectedContext.java
index ff48ccbc4..cc0c4c0c7 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/lifecycle/Mqtt5ClientDisconnectedContext.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/lifecycle/Mqtt5DisconnectedContext.java
@@ -14,26 +14,26 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.lifecycle;
+package com.hivemq.client2.mqtt.mqtt5.lifecycle;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedContext;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedContext;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * A {@link MqttClientDisconnectedContext} with methods specific to an {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client
+ * A {@link MqttDisconnectedContext} with methods specific to an {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client
  * Mqtt5Client}.
  *
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface Mqtt5ClientDisconnectedContext extends MqttClientDisconnectedContext {
+@ApiStatus.NonExtendable
+public interface Mqtt5DisconnectedContext extends MqttDisconnectedContext {
 
     @Override
     @NotNull Mqtt5ClientConfig getClientConfig();
 
     @Override
-    @NotNull Mqtt5ClientReconnector getReconnector();
+    @NotNull Mqtt5Reconnector getReconnector();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/lifecycle/Mqtt5ClientReconnector.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/lifecycle/Mqtt5Reconnector.java
similarity index 56%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/lifecycle/Mqtt5ClientReconnector.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/lifecycle/Mqtt5Reconnector.java
index 46de2ac1b..bf9efe81e 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/lifecycle/Mqtt5ClientReconnector.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/lifecycle/Mqtt5Reconnector.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.lifecycle;
+package com.hivemq.client2.mqtt.mqtt5.lifecycle;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.MqttClientTransportConfig;
-import com.hivemq.client.mqtt.MqttClientTransportConfigBuilder;
-import com.hivemq.client.mqtt.lifecycle.MqttClientReconnector;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.MqttTransportConfig;
+import com.hivemq.client2.mqtt.MqttTransportConfigBuilder;
+import com.hivemq.client2.mqtt.lifecycle.MqttReconnector;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -31,37 +31,36 @@
 import java.util.function.BiConsumer;
 
 /**
- * A {@link MqttClientReconnector} with methods specific to an {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client
- * Mqtt5Client}.
+ * A {@link MqttReconnector} with methods specific to an {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client Mqtt5Client}.
  *
  * @author Silvio Giebl
  * @since 1.1
  */
-@DoNotImplement
-public interface Mqtt5ClientReconnector extends MqttClientReconnector {
+@ApiStatus.NonExtendable
+public interface Mqtt5Reconnector extends MqttReconnector {
 
     @Override
-    @NotNull Mqtt5ClientReconnector reconnect(boolean reconnect);
+    @NotNull Mqtt5Reconnector reconnect(boolean reconnect);
 
     @Override
-    <T> @NotNull Mqtt5ClientReconnector reconnectWhen(
+    <T> @NotNull Mqtt5Reconnector reconnectWhen(
             @NotNull CompletableFuture<T> future, @Nullable BiConsumer<? super T, ? super Throwable> callback);
 
     @Override
-    @NotNull Mqtt5ClientReconnector resubscribeIfSessionExpired(boolean resubscribe);
+    @NotNull Mqtt5Reconnector resubscribeIfSessionExpired(boolean resubscribe);
 
     @Override
-    @NotNull Mqtt5ClientReconnector republishIfSessionExpired(boolean republish);
+    @NotNull Mqtt5Reconnector republishIfSessionExpired(boolean republish);
 
     @Override
-    @NotNull Mqtt5ClientReconnector delay(long delay, @NotNull TimeUnit timeUnit);
+    @NotNull Mqtt5Reconnector delay(long delay, @NotNull TimeUnit timeUnit);
 
     @Override
-    @NotNull Mqtt5ClientReconnector transportConfig(@NotNull MqttClientTransportConfig transportConfig);
+    @NotNull Mqtt5Reconnector transportConfig(@NotNull MqttTransportConfig transportConfig);
 
     @Override
     @CheckReturnValue
-    MqttClientTransportConfigBuilder.@NotNull Nested<? extends Mqtt5ClientReconnector> transportConfig();
+    MqttTransportConfigBuilder.@NotNull Nested<? extends Mqtt5Reconnector> transportConfigWith();
 
     /**
      * Sets a different Connect message the client will try to reconnect with.
@@ -69,7 +68,7 @@ public interface Mqtt5ClientReconnector extends MqttClientReconnector {
      * @param connect the Connect message.
      * @return this reconnector.
      */
-    @NotNull Mqtt5ClientReconnector connect(@NotNull Mqtt5Connect connect);
+    @NotNull Mqtt5Reconnector connect(@NotNull Mqtt5Connect connect);
 
     /**
      * Fluent counterpart of {@link #connect(Mqtt5Connect)}.
@@ -81,14 +80,14 @@ public interface Mqtt5ClientReconnector extends MqttClientReconnector {
      * @see #connect(Mqtt5Connect)
      */
     @CheckReturnValue
-    Mqtt5ConnectBuilder.@NotNull Nested<? extends Mqtt5ClientReconnector> connectWith();
+    Mqtt5ConnectBuilder.@NotNull Nested<? extends Mqtt5Reconnector> connectWith();
 
     /**
      * Returns the currently set Connect message the client will try to reconnect with.
      * <p>
      * If the {@link #connect(Mqtt5Connect)} method has not been called before (including previous {@link
-     * com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener MqttClientDisconnectedListeners}) it will be the
-     * Connect message that is reconstructed from the {@link com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConnectionConfig
+     * com.hivemq.client2.mqtt.lifecycle.MqttDisconnectedListener MqttDisconnectedListener}s) it will be the Connect
+     * message that is reconstructed from the {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConnectionConfig
      * Mqtt5ClientConnectionConfig} or the Connect message of the previous connect try if it has not been successfully
      * connected.
      *
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5Message.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5Message.java
similarity index 88%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5Message.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5Message.java
index bc293bf25..d5d962d93 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5Message.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5Message.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message;
+package com.hivemq.client2.mqtt.mqtt5.message;
 
-import com.hivemq.client.annotations.DoNotImplement;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -25,7 +25,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5Message {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5MessageType.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5MessageType.java
similarity index 97%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5MessageType.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5MessageType.java
index 5eb259a75..f2d408b5d 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5MessageType.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5MessageType.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message;
+package com.hivemq.client2.mqtt.mqtt5.message;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5ReasonCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5ReasonCode.java
similarity index 83%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5ReasonCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5ReasonCode.java
index 3a00869ac..5b5741b32 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5ReasonCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5ReasonCode.java
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message;
+package com.hivemq.client2.mqtt.mqtt5.message;
 
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Range;
 
 /**
  * Reason Code according to the MQTT 5 specification.
@@ -24,13 +26,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ReasonCode {
 
     /**
      * @return the byte code of this Reason Code.
      */
-    int getCode();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_BYTE_MAX_VALUE) int getCode();
 
     /**
      * @return whether this Reason Code is an Error Code.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5Auth.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5Auth.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5Auth.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5Auth.java
index 90cd0623a..aa1dc8933 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5Auth.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5Auth.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.auth;
+package com.hivemq.client2.mqtt.mqtt5.message.auth;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -31,7 +31,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5Auth extends Mqtt5Message, Mqtt5EnhancedAuth {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5AuthBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5AuthBuilder.java
similarity index 85%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5AuthBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5AuthBuilder.java
index 988a29313..ce79834a5 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5AuthBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5AuthBuilder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.auth;
+package com.hivemq.client2.mqtt.mqtt5.message.auth;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -32,7 +32,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5AuthBuilder extends Mqtt5EnhancedAuthBuilder {
 
     @Override
@@ -75,5 +75,5 @@ public interface Mqtt5AuthBuilder extends Mqtt5EnhancedAuthBuilder {
      * @see #userProperties(Mqtt5UserProperties)
      */
     @CheckReturnValue
-    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends Mqtt5AuthBuilder> userProperties();
+    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends Mqtt5AuthBuilder> userPropertiesWith();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCode.java
similarity index 82%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCode.java
index f0ac07583..6809510b8 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCode.java
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.auth;
+package com.hivemq.client2.mqtt.mqtt5.message.auth;
 
-import com.hivemq.client.internal.mqtt.message.MqttCommonReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
-import org.jetbrains.annotations.NotNull;
+import com.hivemq.client2.internal.mqtt.message.MqttReasonCodes;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -32,15 +31,15 @@ public enum Mqtt5AuthReasonCode implements Mqtt5ReasonCode {
     /**
      * Authentication is successful.
      */
-    SUCCESS(MqttCommonReasonCode.SUCCESS),
+    SUCCESS(MqttReasonCodes.SUCCESS),
     /**
      * Continue the authentication with another step.
      */
-    CONTINUE_AUTHENTICATION(0x18),
+    CONTINUE_AUTHENTICATION(MqttReasonCodes.CONTINUE_AUTHENTICATION),
     /**
      * Initiate a re-authentication.
      */
-    REAUTHENTICATE(0x19);
+    REAUTHENTICATE(MqttReasonCodes.REAUTHENTICATE);
 
     private final int code;
 
@@ -48,10 +47,6 @@ public enum Mqtt5AuthReasonCode implements Mqtt5ReasonCode {
         this.code = code;
     }
 
-    Mqtt5AuthReasonCode(final @NotNull MqttCommonReasonCode reasonCode) {
-        this(reasonCode.getCode());
-    }
-
     @Override
     public int getCode() {
         return code;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuth.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuth.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuth.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuth.java
index e4744084a..e2df03cf9 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuth.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuth.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.auth;
+package com.hivemq.client2.mqtt.mqtt5.message.auth;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.nio.ByteBuffer;
@@ -29,7 +29,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5EnhancedAuth {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuthBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuthBuilder.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuthBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuthBuilder.java
index 7d4181c08..04fd03574 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuthBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5EnhancedAuthBuilder.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.auth;
+package com.hivemq.client2.mqtt.mqtt5.message.auth;
 
-import com.hivemq.client.annotations.DoNotImplement;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5EnhancedAuthBuilder {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5SimpleAuth.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5SimpleAuth.java
similarity index 81%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5SimpleAuth.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5SimpleAuth.java
index 3f5fbe6d8..c1cf14449 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5SimpleAuth.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5SimpleAuth.java
@@ -14,24 +14,24 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.auth;
+package com.hivemq.client2.mqtt.mqtt5.message.auth;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuthBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuthBuilder;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.nio.ByteBuffer;
 import java.util.Optional;
 
 /**
- * Simple authentication and/or authorization related data in an {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect
+ * Simple authentication and/or authorization related data in an {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect
  * MQTT 5 Connect message}.
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5SimpleAuth {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilder.java
similarity index 82%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilder.java
index dfdbabc86..ecf0ea461 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.auth;
+package com.hivemq.client2.mqtt.mqtt5.message.auth;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,14 +26,15 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5SimpleAuthBuilder extends Mqtt5SimpleAuthBuilderBase<Mqtt5SimpleAuthBuilder.Complete> {
 
     /**
      * {@link Mqtt5SimpleAuthBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
-    interface Complete extends Mqtt5SimpleAuthBuilder, Mqtt5SimpleAuthBuilderBase<Mqtt5SimpleAuthBuilder.Complete> {
+    @ApiStatus.NonExtendable
+    interface Complete
+            extends Mqtt5SimpleAuthBuilder, Mqtt5SimpleAuthBuilderBase.Complete<Mqtt5SimpleAuthBuilder.Complete> {
 
         /**
          * Builds the {@link Mqtt5SimpleAuth}.
@@ -49,7 +50,7 @@ interface Complete extends Mqtt5SimpleAuthBuilder, Mqtt5SimpleAuthBuilderBase<Mq
      *
      * @param <P> the type of the result when the built {@link Mqtt5SimpleAuth} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5SimpleAuthBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -57,8 +58,8 @@ interface Nested<P> extends Mqtt5SimpleAuthBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt5SimpleAuth} is applied to the parent.
          */
-        @DoNotImplement
-        interface Complete<P> extends Nested<P>, Mqtt5SimpleAuthBuilderBase<Nested.Complete<P>> {
+        @ApiStatus.NonExtendable
+        interface Complete<P> extends Nested<P>, Mqtt5SimpleAuthBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
              * Builds the {@link Mqtt5SimpleAuth} and applies it to the parent.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilderBase.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilderBase.java
index e4cdd5030..a5aa8fc9f 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5SimpleAuthBuilderBase.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.auth;
+package com.hivemq.client2.mqtt.mqtt5.message.auth;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.nio.ByteBuffer;
@@ -30,8 +30,8 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
-public interface Mqtt5SimpleAuthBuilderBase<C extends Mqtt5SimpleAuthBuilderBase<C>> {
+@ApiStatus.NonExtendable
+public interface Mqtt5SimpleAuthBuilderBase<C extends Mqtt5SimpleAuthBuilderBase.Complete<C>> {
 
     /**
      * Sets the {@link Mqtt5SimpleAuth#getUsername() username}. At least the username or the password is mandatory.
@@ -68,4 +68,12 @@ public interface Mqtt5SimpleAuthBuilderBase<C extends Mqtt5SimpleAuthBuilderBase
      */
     @CheckReturnValue
     @NotNull C password(@NotNull ByteBuffer password);
+
+    /**
+     * {@link Mqtt5SimpleAuthBuilderBase} that is complete which means all mandatory fields are set.
+     *
+     * @param <C> the type of the complete builder.
+     */
+    @ApiStatus.NonExtendable
+    interface Complete<C extends Mqtt5SimpleAuthBuilderBase.Complete<C>> extends Mqtt5SimpleAuthBuilderBase<C> {}
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAck.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAck.java
similarity index 76%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAck.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAck.java
index af537b401..44b23910c 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAck.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAck.java
@@ -14,16 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.connect.connack;
-
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttClientIdentifier;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuth;
+package com.hivemq.client2.mqtt.mqtt5.message.connect;
+
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttClientIdentifier;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuth;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.util.Optional;
 import java.util.OptionalInt;
@@ -35,7 +37,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ConnAck extends Mqtt5Message {
 
     /**
@@ -52,12 +54,12 @@ public interface Mqtt5ConnAck extends Mqtt5Message {
      * @return the optional session expiry interval set from the server. If absent, the session expiry interval from the
      *         Connect message is used.
      */
-    @NotNull OptionalLong getSessionExpiryInterval();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) @NotNull OptionalLong getSessionExpiryInterval();
 
     /**
      * @return the optional keep alive set from the server. If absent, the keep alive from the Connect message is used.
      */
-    @NotNull OptionalInt getServerKeepAlive();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) @NotNull OptionalInt getServerKeepAlive();
 
     /**
      * @return the optional client identifier assigned by the server. If absent, the client identifier from the Connect
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAckReasonCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAckReasonCode.java
similarity index 72%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAckReasonCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAckReasonCode.java
index 6cd4981d0..57098d647 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAckReasonCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAckReasonCode.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.connect.connack;
+package com.hivemq.client2.mqtt.mqtt5.message.connect;
 
-import com.hivemq.client.internal.mqtt.message.MqttCommonReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
+import com.hivemq.client2.internal.mqtt.message.MqttReasonCodes;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -32,91 +32,91 @@ public enum Mqtt5ConnAckReasonCode implements Mqtt5ReasonCode {
     /**
      * The connection is accepted.
      */
-    SUCCESS(MqttCommonReasonCode.SUCCESS),
+    SUCCESS(MqttReasonCodes.SUCCESS),
     /**
      * The server either does not want to reveal the reason for the failure or none of the other reason codes apply.
      */
-    UNSPECIFIED_ERROR(MqttCommonReasonCode.UNSPECIFIED_ERROR),
+    UNSPECIFIED_ERROR(MqttReasonCodes.UNSPECIFIED_ERROR),
     /**
      * The CONNECT packet could not be parsed correctly according to the MQTT specification.
      */
-    MALFORMED_PACKET(MqttCommonReasonCode.MALFORMED_PACKET),
+    MALFORMED_PACKET(MqttReasonCodes.MALFORMED_PACKET),
     /**
      * The CONNECT packet contained data that is not allowed by the MQTT protocol.
      */
-    PROTOCOL_ERROR(MqttCommonReasonCode.PROTOCOL_ERROR),
+    PROTOCOL_ERROR(MqttReasonCodes.PROTOCOL_ERROR),
     /**
      * The CONNECT packet is valid but is not accepted by the server.
      */
-    IMPLEMENTATION_SPECIFIC_ERROR(MqttCommonReasonCode.IMPLEMENTATION_SPECIFIC_ERROR),
+    IMPLEMENTATION_SPECIFIC_ERROR(MqttReasonCodes.IMPLEMENTATION_SPECIFIC_ERROR),
     /**
      * The server does not support the version of the MQTT protocol requested by the client.
      */
-    UNSUPPORTED_PROTOCOL_VERSION(0x84),
+    UNSUPPORTED_PROTOCOL_VERSION(MqttReasonCodes.UNSUPPORTED_PROTOCOL_VERSION),
     /**
      * The client identifier is formed correctly but is not accepted by the server.
      */
-    CLIENT_IDENTIFIER_NOT_VALID(0x85),
+    CLIENT_IDENTIFIER_NOT_VALID(MqttReasonCodes.CLIENT_IDENTIFIER_NOT_VALID),
     /**
      * The server does not accept the user name or password specified by the client.
      */
-    BAD_USER_NAME_OR_PASSWORD(0x86),
+    BAD_USER_NAME_OR_PASSWORD(MqttReasonCodes.BAD_USER_NAME_OR_PASSWORD),
     /**
      * The client is not authorized to connect.
      */
-    NOT_AUTHORIZED(MqttCommonReasonCode.NOT_AUTHORIZED),
+    NOT_AUTHORIZED(MqttReasonCodes.NOT_AUTHORIZED),
     /**
      * The MQTT service is not available.
      */
-    SERVER_UNAVAILABLE(0x88),
+    SERVER_UNAVAILABLE(MqttReasonCodes.SERVER_UNAVAILABLE),
     /**
      * The server is busy. Try again later.
      */
-    SERVER_BUSY(MqttCommonReasonCode.SERVER_BUSY),
+    SERVER_BUSY(MqttReasonCodes.SERVER_BUSY),
     /**
      * This client has been banned by administrative action. Contact the server administrator.
      */
-    BANNED(0x8A),
+    BANNED(MqttReasonCodes.BANNED),
     /**
      * The authentication method is not supported or does not match the authentication method currently in use.
      */
-    BAD_AUTHENTICATION_METHOD(MqttCommonReasonCode.BAD_AUTHENTICATION_METHOD),
+    BAD_AUTHENTICATION_METHOD(MqttReasonCodes.BAD_AUTHENTICATION_METHOD),
     /**
      * The Will topic name is formed correctly but is not accepted by the server.
      */
-    TOPIC_NAME_INVALID(MqttCommonReasonCode.TOPIC_NAME_INVALID),
+    TOPIC_NAME_INVALID(MqttReasonCodes.TOPIC_NAME_INVALID),
     /**
      * The CONNECT packet exceeded the maximum permissible size.
      */
-    PACKET_TOO_LARGE(MqttCommonReasonCode.PACKET_TOO_LARGE),
+    PACKET_TOO_LARGE(MqttReasonCodes.PACKET_TOO_LARGE),
     /**
      * An implementation or administrative imposed limit has been exceeded.
      */
-    QUOTA_EXCEEDED(MqttCommonReasonCode.QUOTA_EXCEEDED),
+    QUOTA_EXCEEDED(MqttReasonCodes.QUOTA_EXCEEDED),
     /**
      * The Will payload does not match the specified payload format indicator.
      */
-    PAYLOAD_FORMAT_INVALID(MqttCommonReasonCode.PAYLOAD_FORMAT_INVALID),
+    PAYLOAD_FORMAT_INVALID(MqttReasonCodes.PAYLOAD_FORMAT_INVALID),
     /**
      * The server does not support retained messages, but the Will retain flag was set.
      */
-    RETAIN_NOT_SUPPORTED(MqttCommonReasonCode.RETAIN_NOT_SUPPORTED),
+    RETAIN_NOT_SUPPORTED(MqttReasonCodes.RETAIN_NOT_SUPPORTED),
     /**
      * The server does not support the QoS of the Will.
      */
-    QOS_NOT_SUPPORTED(MqttCommonReasonCode.QOS_NOT_SUPPORTED),
+    QOS_NOT_SUPPORTED(MqttReasonCodes.QOS_NOT_SUPPORTED),
     /**
      * The client should temporarily use another server.
      */
-    USE_ANOTHER_SERVER(MqttCommonReasonCode.USE_ANOTHER_SERVER),
+    USE_ANOTHER_SERVER(MqttReasonCodes.USE_ANOTHER_SERVER),
     /**
      * The client should permanently use another server.
      */
-    SERVER_MOVED(MqttCommonReasonCode.SERVER_MOVED),
+    SERVER_MOVED(MqttReasonCodes.SERVER_MOVED),
     /**
      * The connection rate limit has been exceeded.
      */
-    CONNECTION_RATE_EXCEEDED(MqttCommonReasonCode.CONNECTION_RATE_EXCEEDED);
+    CONNECTION_RATE_EXCEEDED(MqttReasonCodes.CONNECTION_RATE_EXCEEDED);
 
     private final int code;
 
@@ -124,10 +124,6 @@ public enum Mqtt5ConnAckReasonCode implements Mqtt5ReasonCode {
         this.code = code;
     }
 
-    Mqtt5ConnAckReasonCode(final @NotNull MqttCommonReasonCode reasonCode) {
-        this(reasonCode.getCode());
-    }
-
     @Override
     public int getCode() {
         return code;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAckRestrictions.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAckRestrictions.java
similarity index 83%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAckRestrictions.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAckRestrictions.java
index 75ecb85e9..1fdf49ae0 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAckRestrictions.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAckRestrictions.java
@@ -14,25 +14,26 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.connect.connack;
+package com.hivemq.client2.mqtt.mqtt5.message.connect;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.util.UnsignedDataTypes;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 /**
  * Restrictions for the client set by the server in an {@link Mqtt5ConnAck MQTT 5 ConnAck message}.
  * <p>
- * These restrictions are used in conjunction with the {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions
- * Mqtt5ConnectRestrictions} to form the {@link com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConnectionConfig.RestrictionsForClient
+ * These restrictions are used in conjunction with the {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions
+ * Mqtt5ConnectRestrictions} to form the {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConnectionConfig.RestrictionsForClient
  * Mqtt5ClientConnectionConfig.RestrictionsForClient}.
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ConnAckRestrictions {
 
     /**
@@ -73,19 +74,19 @@ public interface Mqtt5ConnAckRestrictions {
      * @return the maximum amount of not acknowledged publishes with QoS 1 or 2 the server accepts concurrently. The
      *         default is {@link #DEFAULT_RECEIVE_MAXIMUM}.
      */
-    int getReceiveMaximum();
+    @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getReceiveMaximum();
 
     /**
      * @return the maximum packet size the server accepts from the client. The default is {@link
      *         #DEFAULT_MAXIMUM_PACKET_SIZE_NO_LIMIT}.
      */
-    int getMaximumPacketSize();
+    @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int getMaximumPacketSize();
 
     /**
      * @return the maximum amount of topic aliases the server accepts from the client. The default is {@link
      *         #DEFAULT_TOPIC_ALIAS_MAXIMUM}.
      */
-    int getTopicAliasMaximum();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getTopicAliasMaximum();
 
     /**
      * @return the maximum QoS the server accepts from the client. The default is {@link #DEFAULT_MAXIMUM_QOS}.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5Connect.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5Connect.java
similarity index 78%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5Connect.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5Connect.java
index d1572f2d8..118b49405 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5Connect.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5Connect.java
@@ -14,18 +14,19 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.connect;
-
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectBuilder;
-import com.hivemq.client.internal.util.UnsignedDataTypes;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
+package com.hivemq.client2.mqtt.mqtt5.message.connect;
+
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectBuilder;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5WillPublish;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.util.Optional;
 
@@ -35,7 +36,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5Connect extends Mqtt5Message {
 
     /**
@@ -71,7 +72,7 @@ public interface Mqtt5Connect extends Mqtt5Message {
     /**
      * @return the keep alive in seconds the client wants to use.
      */
-    int getKeepAlive();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getKeepAlive();
 
     /**
      * @return whether the client has no session present or wants to clear a present session.
@@ -82,7 +83,7 @@ public interface Mqtt5Connect extends Mqtt5Message {
      * @return the session expiry interval in seconds the client wants to use. The default is {@link
      *         #DEFAULT_SESSION_EXPIRY_INTERVAL}. If it is {@link #NO_SESSION_EXPIRY} the session does not expire.
      */
-    long getSessionExpiryInterval();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long getSessionExpiryInterval();
 
     /**
      * @return the restrictions set from the client.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilder.java
similarity index 87%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilder.java
index 42883eeaa..0bd8feab1 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.connect;
+package com.hivemq.client2.mqtt.mqtt5.message.connect;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,7 +26,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ConnectBuilder extends Mqtt5ConnectBuilderBase<Mqtt5ConnectBuilder> {
 
     /**
@@ -42,7 +42,7 @@ public interface Mqtt5ConnectBuilder extends Mqtt5ConnectBuilderBase<Mqtt5Connec
      *
      * @param <P> the type of the result when the built {@link Mqtt5Connect} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5ConnectBuilderBase<Nested<P>> {
 
         /**
@@ -54,12 +54,12 @@ interface Nested<P> extends Mqtt5ConnectBuilderBase<Nested<P>> {
     }
 
     /**
-     * Builder for a {@link Mqtt5Connect} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client}
+     * Builder for a {@link Mqtt5Connect} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client}
      * which then sends the Connect message.
      *
      * @param <P> the type of the result when the built {@link Mqtt5Connect} is sent by the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Send<P> extends Mqtt5ConnectBuilderBase<Send<P>> {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilderBase.java
similarity index 85%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilderBase.java
index 3de0ecc4e..7013a5fb9 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectBuilderBase.java
@@ -14,19 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.connect;
-
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuthBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublishBuilder;
+package com.hivemq.client2.mqtt.mqtt5.message.connect;
+
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5SimpleAuthBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5WillPublishBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 /**
  * Builder base for a {@link Mqtt5Connect}.
@@ -35,7 +37,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ConnectBuilderBase<B extends Mqtt5ConnectBuilderBase<B>> {
 
     /**
@@ -47,7 +49,7 @@ public interface Mqtt5ConnectBuilderBase<B extends Mqtt5ConnectBuilderBase<B>> {
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B keepAlive(int keepAlive);
+    @NotNull B keepAlive(@Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int keepAlive);
 
     /**
      * Disables the {@link Mqtt5Connect#getKeepAlive() keep alive} by setting it to {@link Mqtt5Connect#NO_KEEP_ALIVE}.
@@ -75,7 +77,8 @@ public interface Mqtt5ConnectBuilderBase<B extends Mqtt5ConnectBuilderBase<B>> {
      * @return teh builder.
      */
     @CheckReturnValue
-    @NotNull B sessionExpiryInterval(long sessionExpiryInterval);
+    @NotNull B sessionExpiryInterval(
+            @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval);
 
     /**
      * Disables the {@link Mqtt5Connect#getSessionExpiryInterval() session expiry} by setting it to {@link
@@ -105,7 +108,7 @@ public interface Mqtt5ConnectBuilderBase<B extends Mqtt5ConnectBuilderBase<B>> {
      * @see #restrictions(Mqtt5ConnectRestrictions)
      */
     @CheckReturnValue
-    Mqtt5ConnectRestrictionsBuilder.@NotNull Nested<? extends B> restrictions();
+    Mqtt5ConnectRestrictionsBuilder.@NotNull Nested<? extends B> restrictionsWith();
 
     /**
      * Sets the optional {@link Mqtt5Connect#getSimpleAuth() simple authentication and/or authorization related data}.
@@ -128,7 +131,7 @@ public interface Mqtt5ConnectBuilderBase<B extends Mqtt5ConnectBuilderBase<B>> {
      * @see #simpleAuth(Mqtt5SimpleAuth)
      */
     @CheckReturnValue
-    Mqtt5SimpleAuthBuilder.@NotNull Nested<? extends B> simpleAuth();
+    Mqtt5SimpleAuthBuilder.@NotNull Nested<? extends B> simpleAuthWith();
 
     /**
      * Sets the {@link Mqtt5Connect#getEnhancedAuthMechanism() enhanced authentication and/or authorization mechanism}.
@@ -160,7 +163,7 @@ public interface Mqtt5ConnectBuilderBase<B extends Mqtt5ConnectBuilderBase<B>> {
      * @see #willPublish(Mqtt5Publish)
      */
     @CheckReturnValue
-    Mqtt5WillPublishBuilder.@NotNull Nested<? extends B> willPublish();
+    Mqtt5WillPublishBuilder.@NotNull Nested<? extends B> willPublishWith();
 
     /**
      * Sets the {@link Mqtt5Connect#getUserProperties() User Properties}.
@@ -181,5 +184,5 @@ public interface Mqtt5ConnectBuilderBase<B extends Mqtt5ConnectBuilderBase<B>> {
      * @see #userProperties(Mqtt5UserProperties)
      */
     @CheckReturnValue
-    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends B> userProperties();
+    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends B> userPropertiesWith();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictions.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictions.java
similarity index 78%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictions.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictions.java
index 761cd85d3..21ea31190 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictions.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictions.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.connect;
+package com.hivemq.client2.mqtt.mqtt5.message.connect;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictionsBuilder;
-import com.hivemq.client.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectRestrictionsBuilder;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 /**
  * Restrictions set by the client in an {@link Mqtt5Connect MQTT 5 Connect message}.
@@ -29,20 +30,20 @@
  * <ul>
  *   <li>Restrictions for the server.
  * <p>
- *     These are used to form the {@link com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConnectionConfig.RestrictionsForServer
+ *     These are used to form the {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConnectionConfig.RestrictionsForServer
  *     Mqtt5ClientConnectionConfig.RestrictionsForServer}
  *   <li>Restrictions for the client set by the client itself.
  * <p>
  *     These restrictions are used in conjunction with the
- *     {@link com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions Mqtt5ConnAckRestrictions}
- *     to form the {@link com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConnectionConfig.RestrictionsForClient
+ *     {@link Mqtt5ConnAckRestrictions}
+ *     to form the {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConnectionConfig.RestrictionsForClient
  *     Mqtt5ClientConnectionConfig.RestrictionsForClient}.
  * </ul>
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ConnectRestrictions {
 
     /**
@@ -98,20 +99,19 @@ public interface Mqtt5ConnectRestrictions {
      * @return the maximum amount of not acknowledged publishes with QoS 1 or 2 the client accepts from the server
      *         concurrently.
      */
-    int getReceiveMaximum();
+    @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getReceiveMaximum();
 
     /**
      * Returns the maximum amount of not acknowledged publishes with QoS 1 or 2 the client sends to the server
      * concurrently. The default is {@link #DEFAULT_SEND_MAXIMUM}.
      * <p>
      * The actual amount a connected client will use is determined by the minimum of this value and {@link
-     * com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#getReceiveMaximum()
-     * MqttConnAckRestrictions#getReceiveMaximum()}.
+     * Mqtt5ConnAckRestrictions#getReceiveMaximum() MqttConnAckRestrictions#getReceiveMaximum()}.
      *
      * @return the maximum amount of not acknowledged publishes with QoS 1 or 2 the client sends to the server
      *         concurrently.
      */
-    int getSendMaximum();
+    @Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getSendMaximum();
 
     /**
      * Returns the maximum packet size the client accepts from the server. The default is {@link
@@ -119,19 +119,18 @@ public interface Mqtt5ConnectRestrictions {
      *
      * @return the maximum packet size the client accepts from the server.
      */
-    int getMaximumPacketSize();
+    @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int getMaximumPacketSize();
 
     /**
      * Returns the maximum packet size the client sends to the server. The default is {@link
      * #DEFAULT_SEND_MAXIMUM_PACKET_SIZE}.
      * <p>
      * The actual size a connected client will use is determined by the minimum of this value and {@link
-     * com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#getMaximumPacketSize()
-     * MqttConnAckRestrictions#getMaximumPacketSize()}.
+     * Mqtt5ConnAckRestrictions#getMaximumPacketSize() MqttConnAckRestrictions#getMaximumPacketSize()}.
      *
      * @return the maximum packet size the client sends to the server.
      */
-    int getSendMaximumPacketSize();
+    @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int getSendMaximumPacketSize();
 
     /**
      * Returns the maximum amount of topic aliases the client accepts from the server. The default is {@link
@@ -139,19 +138,18 @@ public interface Mqtt5ConnectRestrictions {
      *
      * @return the maximum amount of topic aliases the client accepts from the server.
      */
-    int getTopicAliasMaximum();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getTopicAliasMaximum();
 
     /**
      * Returns the maximum amount of topic aliases the client sends to the server. The default is {@link
      * #DEFAULT_SEND_TOPIC_ALIAS_MAXIMUM}.
      * <p>
      * The actual amount a connected client will use is determined by the minimum of this value and {@link
-     * com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions#getTopicAliasMaximum()
-     * MqttConnAckRestrictions#getTopicAliasMaximum()}.
+     * Mqtt5ConnAckRestrictions#getTopicAliasMaximum() MqttConnAckRestrictions#getTopicAliasMaximum()}.
      *
      * @return the maximum amount of topic aliases the client sends to the server.
      */
-    int getSendTopicAliasMaximum();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int getSendTopicAliasMaximum();
 
     /**
      * Returns whether the client requests problem information from the server. The default is {@link
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilder.java
similarity index 88%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilder.java
index 128de1ada..32236222f 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.connect;
+package com.hivemq.client2.mqtt.mqtt5.message.connect;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,7 +26,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ConnectRestrictionsBuilder
         extends Mqtt5ConnectRestrictionsBuilderBase<Mqtt5ConnectRestrictionsBuilder> {
 
@@ -43,7 +43,7 @@ public interface Mqtt5ConnectRestrictionsBuilder
      *
      * @param <P> the type of the result when the built {@link Mqtt5ConnectRestrictions} are applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5ConnectRestrictionsBuilderBase<Nested<P>> {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilderBase.java
similarity index 76%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilderBase.java
index 943e99dd9..fed328434 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnectRestrictionsBuilderBase.java
@@ -14,11 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.connect;
+package com.hivemq.client2.mqtt.mqtt5.message.connect;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 /**
  * Builder base for {@link Mqtt5ConnectRestrictions}.
@@ -27,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5ConnectRestrictionsBuilderBase<B extends Mqtt5ConnectRestrictionsBuilderBase<B>> {
 
     /**
@@ -39,7 +42,7 @@ public interface Mqtt5ConnectRestrictionsBuilderBase<B extends Mqtt5ConnectRestr
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B receiveMaximum(int receiveMaximum);
+    @NotNull B receiveMaximum(@Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int receiveMaximum);
 
     /**
      * Sets the {@link Mqtt5ConnectRestrictions#getSendMaximum() send maximum}.
@@ -52,7 +55,7 @@ public interface Mqtt5ConnectRestrictionsBuilderBase<B extends Mqtt5ConnectRestr
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B sendMaximum(int receiveMaximum);
+    @NotNull B sendMaximum(@Range(from = 1, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int receiveMaximum);
 
     /**
      * Sets the {@link Mqtt5ConnectRestrictions#getMaximumPacketSize() maximum packet size}.
@@ -63,7 +66,8 @@ public interface Mqtt5ConnectRestrictionsBuilderBase<B extends Mqtt5ConnectRestr
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B maximumPacketSize(int maximumPacketSize);
+    @NotNull B maximumPacketSize(
+            @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int maximumPacketSize);
 
     /**
      * Sets the {@link Mqtt5ConnectRestrictions#getSendMaximumPacketSize() maximum packet size for sending}.
@@ -76,7 +80,8 @@ public interface Mqtt5ConnectRestrictionsBuilderBase<B extends Mqtt5ConnectRestr
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B sendMaximumPacketSize(int maximumPacketSize);
+    @NotNull B sendMaximumPacketSize(
+            @Range(from = 1, to = MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT) int maximumPacketSize);
 
     /**
      * Sets the {@link Mqtt5ConnectRestrictions#getTopicAliasMaximum() topic alias maximum}.
@@ -87,7 +92,8 @@ public interface Mqtt5ConnectRestrictionsBuilderBase<B extends Mqtt5ConnectRestr
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B topicAliasMaximum(int topicAliasMaximum);
+    @NotNull B topicAliasMaximum(
+            @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int topicAliasMaximum);
 
     /**
      * Sets the {@link Mqtt5ConnectRestrictions#getSendTopicAliasMaximum() topic alias maximum for sending}.
@@ -100,7 +106,8 @@ public interface Mqtt5ConnectRestrictionsBuilderBase<B extends Mqtt5ConnectRestr
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B sendTopicAliasMaximum(int topicAliasMaximum);
+    @NotNull B sendTopicAliasMaximum(
+            @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_SHORT_MAX_VALUE) int topicAliasMaximum);
 
     /**
      * Sets whether {@link Mqtt5ConnectRestrictions#isRequestProblemInformation() problem information is requested}.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5Disconnect.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5Disconnect.java
similarity index 77%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5Disconnect.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5Disconnect.java
index 6afc5a82f..a37249296 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5Disconnect.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5Disconnect.java
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.disconnect;
+package com.hivemq.client2.mqtt.mqtt5.message.disconnect;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnectBuilder;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.util.Optional;
 import java.util.OptionalLong;
@@ -33,7 +35,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5Disconnect extends Mqtt5Message {
 
     /**
@@ -59,7 +61,7 @@ public interface Mqtt5Disconnect extends Mqtt5Message {
      * @return the optional session expiry interval in seconds, the client disconnects from with this Disconnect
      *         message.
      */
-    @NotNull OptionalLong getSessionExpiryInterval();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) @NotNull OptionalLong getSessionExpiryInterval();
 
     /**
      * @return the optional server reference, which can be used if the server sent this Disconnect message.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilder.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilder.java
index 1ae623936..1b2a36f44 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.disconnect;
+package com.hivemq.client2.mqtt.mqtt5.message.disconnect;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,7 +26,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5DisconnectBuilder extends Mqtt5DisconnectBuilderBase<Mqtt5DisconnectBuilder> {
 
     /**
@@ -42,7 +42,7 @@ public interface Mqtt5DisconnectBuilder extends Mqtt5DisconnectBuilderBase<Mqtt5
      *
      * @param <P> the type of the result when the built {@link Mqtt5Disconnect} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5DisconnectBuilderBase<Nested<P>> {
 
         /**
@@ -54,12 +54,12 @@ interface Nested<P> extends Mqtt5DisconnectBuilderBase<Nested<P>> {
     }
 
     /**
-     * Builder for a {@link Mqtt5Disconnect} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client}
+     * Builder for a {@link Mqtt5Disconnect} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client}
      * which then sends the Disconnect message.
      *
      * @param <P> the type of the result when the built {@link Mqtt5Disconnect} is sent by the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Send<P> extends Mqtt5DisconnectBuilderBase<Send<P>> {
 
         /**
@@ -71,10 +71,10 @@ interface Send<P> extends Mqtt5DisconnectBuilderBase<Send<P>> {
     }
 
     /**
-     * Builder for a {@link Mqtt5Disconnect} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client}
+     * Builder for a {@link Mqtt5Disconnect} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client}
      * which then sends the Disconnect message without returning a result.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface SendVoid extends Mqtt5DisconnectBuilderBase<SendVoid> {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilderBase.java
similarity index 82%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilderBase.java
index 4e6cfbef0..f2886a7c3 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectBuilderBase.java
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.disconnect;
+package com.hivemq.client2.mqtt.mqtt5.message.disconnect;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 /**
  * Builder base for a {@link Mqtt5Disconnect}.
@@ -31,7 +33,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5DisconnectBuilderBase<B extends Mqtt5DisconnectBuilderBase<B>> {
 
     /**
@@ -52,11 +54,12 @@ public interface Mqtt5DisconnectBuilderBase<B extends Mqtt5DisconnectBuilderBase
      * @return the builder.
      */
     @CheckReturnValue
-    @NotNull B sessionExpiryInterval(long sessionExpiryInterval);
+    @NotNull B sessionExpiryInterval(
+            @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long sessionExpiryInterval);
 
     /**
      * Disables the {@link Mqtt5Disconnect#getSessionExpiryInterval() session expiry} by setting it to {@link
-     * com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect#NO_SESSION_EXPIRY Mqtt5Connect.NO_SESSION_EXPIRY}.
+     * com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect#NO_SESSION_EXPIRY Mqtt5Connect.NO_SESSION_EXPIRY}.
      *
      * @return the builder.
      */
@@ -118,5 +121,5 @@ public interface Mqtt5DisconnectBuilderBase<B extends Mqtt5DisconnectBuilderBase
      * @see #userProperties(Mqtt5UserProperties)
      */
     @CheckReturnValue
-    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends B> userProperties();
+    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends B> userPropertiesWith();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCode.java
similarity index 76%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCode.java
index b0953ae59..86beca182 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCode.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.disconnect;
+package com.hivemq.client2.mqtt.mqtt5.message.disconnect;
 
-import com.hivemq.client.internal.mqtt.message.MqttCommonReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
+import com.hivemq.client2.internal.mqtt.message.MqttReasonCodes;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -34,127 +34,127 @@ public enum Mqtt5DisconnectReasonCode implements Mqtt5ReasonCode {
     /**
      * Disconnect normally. The server must not publish the Will message.
      */
-    NORMAL_DISCONNECTION(0x00),
+    NORMAL_DISCONNECTION(MqttReasonCodes.SUCCESS),
     /**
      * Disconnect normally. The server must also publish the Will message.
      */
-    DISCONNECT_WITH_WILL_MESSAGE(0x04),
+    DISCONNECT_WITH_WILL_MESSAGE(MqttReasonCodes.DISCONNECT_WITH_WILL_MESSAGE),
     /**
      * The sender either does not want to reveal the reason for the disconnect or none of the other reason codes apply.
      */
-    UNSPECIFIED_ERROR(MqttCommonReasonCode.UNSPECIFIED_ERROR),
+    UNSPECIFIED_ERROR(MqttReasonCodes.UNSPECIFIED_ERROR),
     /**
      * A packet could not be parsed correctly according to the MQTT specification.
      */
-    MALFORMED_PACKET(MqttCommonReasonCode.MALFORMED_PACKET),
+    MALFORMED_PACKET(MqttReasonCodes.MALFORMED_PACKET),
     /**
      * A packet contained data that is not allowed by the MQTT protocol or is inconsistent with the state of the
      * receiver.
      */
-    PROTOCOL_ERROR(MqttCommonReasonCode.PROTOCOL_ERROR),
+    PROTOCOL_ERROR(MqttReasonCodes.PROTOCOL_ERROR),
     /**
      * A packet is valid but can not be processed by the implementation of the receiver.
      */
-    IMPLEMENTATION_SPECIFIC_ERROR(MqttCommonReasonCode.IMPLEMENTATION_SPECIFIC_ERROR),
+    IMPLEMENTATION_SPECIFIC_ERROR(MqttReasonCodes.IMPLEMENTATION_SPECIFIC_ERROR),
     /**
      * The client is not authorized to perform a request.
      */
-    NOT_AUTHORIZED(MqttCommonReasonCode.NOT_AUTHORIZED),
+    NOT_AUTHORIZED(MqttReasonCodes.NOT_AUTHORIZED),
     /**
      * The server is busy and can not continue processing requests from the client.
      */
-    SERVER_BUSY(MqttCommonReasonCode.SERVER_BUSY),
+    SERVER_BUSY(MqttReasonCodes.SERVER_BUSY),
     /**
      * The server is shutting down.
      */
-    SERVER_SHUTTING_DOWN(0x8B),
+    SERVER_SHUTTING_DOWN(MqttReasonCodes.SERVER_SHUTTING_DOWN),
     /**
      * The authentication method is not supported or does not match the authentication method currently in use.
      */
-    BAD_AUTHENTICATION_METHOD(MqttCommonReasonCode.BAD_AUTHENTICATION_METHOD),
+    BAD_AUTHENTICATION_METHOD(MqttReasonCodes.BAD_AUTHENTICATION_METHOD),
     /**
      * The connection is closed because no packet has been received for 1.5 times the keep alive time.
      */
-    KEEP_ALIVE_TIMEOUT(0x8D),
+    KEEP_ALIVE_TIMEOUT(MqttReasonCodes.KEEP_ALIVE_TIMEOUT),
     /**
      * Another client using the same client identifier has connected.
      */
-    SESSION_TAKEN_OVER(0x8E),
+    SESSION_TAKEN_OVER(MqttReasonCodes.SESSION_TAKEN_OVER),
     /**
      * A packet contained a topic filter that is formed correctly but is not accepted by the server.
      */
-    TOPIC_FILTER_INVALID(MqttCommonReasonCode.TOPIC_FILTER_INVALID),
+    TOPIC_FILTER_INVALID(MqttReasonCodes.TOPIC_FILTER_INVALID),
     /**
      * A packet contained a topic name that is formed correctly but is not accepted by the receiver.
      */
-    TOPIC_NAME_INVALID(MqttCommonReasonCode.TOPIC_NAME_INVALID),
+    TOPIC_NAME_INVALID(MqttReasonCodes.TOPIC_NAME_INVALID),
     /**
      * The receiver has received more publications for which it has not sent PUBACK or PUBCOMP than allowed by the
      * receive maximum it sent in the CONNECT or CONNACK packet.
      */
-    RECEIVE_MAXIMUM_EXCEEDED(0x93),
+    RECEIVE_MAXIMUM_EXCEEDED(MqttReasonCodes.RECEIVE_MAXIMUM_EXCEEDED),
     /**
      * The receiver has received a PUBLISH packet containing a topic alias which is greater than the maximum topic alias
      * it sent in the CONNECT or CONNACK packet.
      */
-    TOPIC_ALIAS_INVALID(0x94),
+    TOPIC_ALIAS_INVALID(MqttReasonCodes.TOPIC_ALIAS_INVALID),
     /**
      * The receiver has received a packet with a greater size than allowed by the maximum packet size it sent in the
      * CONNECT or CONNACK packet.
      */
-    PACKET_TOO_LARGE(MqttCommonReasonCode.PACKET_TOO_LARGE),
+    PACKET_TOO_LARGE(MqttReasonCodes.PACKET_TOO_LARGE),
     /**
      * The received data rate is too high.
      */
-    MESSAGE_RATE_TOO_HIGH(0x96),
+    MESSAGE_RATE_TOO_HIGH(MqttReasonCodes.MESSAGE_RATE_TOO_HIGH),
     /**
      * An implementation or administrative imposed limit has been exceeded.
      */
-    QUOTA_EXCEEDED(MqttCommonReasonCode.QUOTA_EXCEEDED),
+    QUOTA_EXCEEDED(MqttReasonCodes.QUOTA_EXCEEDED),
     /**
      * The connection is closed due to an administrative action.
      */
-    ADMINISTRATIVE_ACTION(0x98),
+    ADMINISTRATIVE_ACTION(MqttReasonCodes.ADMINISTRATIVE_ACTION),
     /**
      * A payload does not match the specified payload format indicator.
      */
-    PAYLOAD_FORMAT_INVALID(MqttCommonReasonCode.PAYLOAD_FORMAT_INVALID),
+    PAYLOAD_FORMAT_INVALID(MqttReasonCodes.PAYLOAD_FORMAT_INVALID),
     /**
      * The server does not support retained messages.
      */
-    RETAIN_NOT_SUPPORTED(MqttCommonReasonCode.RETAIN_NOT_SUPPORTED),
+    RETAIN_NOT_SUPPORTED(MqttReasonCodes.RETAIN_NOT_SUPPORTED),
     /**
      * The client specified a QoS greater than the maximum QoS the server sent in the CONNACK packet.
      */
-    QOS_NOT_SUPPORTED(MqttCommonReasonCode.QOS_NOT_SUPPORTED),
+    QOS_NOT_SUPPORTED(MqttReasonCodes.QOS_NOT_SUPPORTED),
     /**
      * The client should temporarily use another server.
      */
-    USE_ANOTHER_SERVER(MqttCommonReasonCode.USE_ANOTHER_SERVER),
+    USE_ANOTHER_SERVER(MqttReasonCodes.USE_ANOTHER_SERVER),
     /**
      * The client should permanently use another server.
      */
-    SERVER_MOVED(MqttCommonReasonCode.SERVER_MOVED),
+    SERVER_MOVED(MqttReasonCodes.SERVER_MOVED),
     /**
      * The server does not support shared subscriptions.
      */
-    SHARED_SUBSCRIPTIONS_NOT_SUPPORTED(MqttCommonReasonCode.SHARED_SUBSCRIPTIONS_NOT_SUPPORTED),
+    SHARED_SUBSCRIPTIONS_NOT_SUPPORTED(MqttReasonCodes.SHARED_SUBSCRIPTIONS_NOT_SUPPORTED),
     /**
      * The connection is closed because the connection rate is too high.
      */
-    CONNECTION_RATE_EXCEEDED(MqttCommonReasonCode.CONNECTION_RATE_EXCEEDED),
+    CONNECTION_RATE_EXCEEDED(MqttReasonCodes.CONNECTION_RATE_EXCEEDED),
     /**
      * The maximum connection time authorized for this connection has been exceeded.
      */
-    MAXIMUM_CONNECT_TIME(0xA0),
+    MAXIMUM_CONNECT_TIME(MqttReasonCodes.MAXIMUM_CONNECT_TIME),
     /**
      * The server does not support subscription identifiers.
      */
-    SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED(MqttCommonReasonCode.SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED),
+    SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED(MqttReasonCodes.SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED),
     /**
      * The server does not support wildcard subscriptions.
      */
-    WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED(MqttCommonReasonCode.WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED);
+    WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED(MqttReasonCodes.WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED);
 
     private final int code;
 
@@ -162,10 +162,6 @@ public enum Mqtt5DisconnectReasonCode implements Mqtt5ReasonCode {
         this.code = code;
     }
 
-    Mqtt5DisconnectReasonCode(final @NotNull MqttCommonReasonCode reasonCode) {
-        this(reasonCode.getCode());
-    }
-
     @Override
     public int getCode() {
         return code;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/ping/Mqtt5PingReq.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/ping/Mqtt5PingReq.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/ping/Mqtt5PingReq.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/ping/Mqtt5PingReq.java
index 5c3055963..626921d5f 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/ping/Mqtt5PingReq.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/ping/Mqtt5PingReq.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.ping;
+package com.hivemq.client2.mqtt.mqtt5.message.ping;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -27,7 +27,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PingReq extends Mqtt5Message {
 
     @Override
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/ping/Mqtt5PingResp.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/ping/Mqtt5PingResp.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/ping/Mqtt5PingResp.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/ping/Mqtt5PingResp.java
index b578e53c3..90c9552d1 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/ping/Mqtt5PingResp.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/ping/Mqtt5PingResp.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.ping;
+package com.hivemq.client2.mqtt.mqtt5.message.ping;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -27,7 +27,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PingResp extends Mqtt5Message {
 
     @Override
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicator.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicator.java
similarity index 96%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicator.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicator.java
index 77e0b5e1a..4b8e34bbc 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicator.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicator.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
 import org.jetbrains.annotations.Nullable;
 
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAck.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAck.java
similarity index 78%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAck.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAck.java
index 2227ad0af..5425d326b 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAck.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAck.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.puback;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -31,7 +31,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PubAck extends Mqtt5Message {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAckBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAckBuilder.java
similarity index 85%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAckBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAckBuilder.java
index c11a3fd70..6ef0fc1ea 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAckBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAckBuilder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.puback;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -30,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PubAckBuilder {
 
     /**
@@ -75,5 +75,5 @@ public interface Mqtt5PubAckBuilder {
      * @see #userProperties(Mqtt5UserProperties)
      */
     @CheckReturnValue
-    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends Mqtt5PubAckBuilder> userProperties();
+    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends Mqtt5PubAckBuilder> userPropertiesWith();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAckReasonCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAckReasonCode.java
similarity index 77%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAckReasonCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAckReasonCode.java
index ddfa2cc7e..7085e7339 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAckReasonCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAckReasonCode.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.puback;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.MqttCommonReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
+import com.hivemq.client2.internal.mqtt.message.MqttReasonCodes;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -34,40 +34,40 @@ public enum Mqtt5PubAckReasonCode implements Mqtt5ReasonCode {
     /**
      * The message is accepted. Publication of the QoS 1 message proceeds.
      */
-    SUCCESS(MqttCommonReasonCode.SUCCESS),
+    SUCCESS(MqttReasonCodes.SUCCESS),
     /**
      * The message is accepted but there are no subscribers.
      */
-    NO_MATCHING_SUBSCRIBERS(MqttCommonReasonCode.NO_MATCHING_SUBSCRIBERS),
+    NO_MATCHING_SUBSCRIBERS(MqttReasonCodes.NO_MATCHING_SUBSCRIBERS),
     /**
      * The receiver either does not want to reveal the reason for the failure or none of the other reason codes apply.
      */
-    UNSPECIFIED_ERROR(MqttCommonReasonCode.UNSPECIFIED_ERROR),
+    UNSPECIFIED_ERROR(MqttReasonCodes.UNSPECIFIED_ERROR),
     /**
      * The PUBLISH packet is valid but is not accepted by the receiver.
      */
-    IMPLEMENTATION_SPECIFIC_ERROR(MqttCommonReasonCode.IMPLEMENTATION_SPECIFIC_ERROR),
+    IMPLEMENTATION_SPECIFIC_ERROR(MqttReasonCodes.IMPLEMENTATION_SPECIFIC_ERROR),
     /**
      * The sender is not authorized to make the publication.
      */
-    NOT_AUTHORIZED(MqttCommonReasonCode.NOT_AUTHORIZED),
+    NOT_AUTHORIZED(MqttReasonCodes.NOT_AUTHORIZED),
     /**
      * The topic name is formed correctly but is not accepted by the receiver.
      */
-    TOPIC_NAME_INVALID(MqttCommonReasonCode.TOPIC_NAME_INVALID),
+    TOPIC_NAME_INVALID(MqttReasonCodes.TOPIC_NAME_INVALID),
     /**
      * The packet identifier is already in use. This might indicate a mismatch between the session state on the client
      * and server.
      */
-    PACKET_IDENTIFIER_IN_USE(MqttCommonReasonCode.PACKET_IDENTIFIER_IN_USE),
+    PACKET_IDENTIFIER_IN_USE(MqttReasonCodes.PACKET_IDENTIFIER_IN_USE),
     /**
      * An implementation or administrative imposed limit has been exceeded.
      */
-    QUOTA_EXCEEDED(MqttCommonReasonCode.QUOTA_EXCEEDED),
+    QUOTA_EXCEEDED(MqttReasonCodes.QUOTA_EXCEEDED),
     /**
      * The payload does not match the specified payload format indicator.
      */
-    PAYLOAD_FORMAT_INVALID(MqttCommonReasonCode.PAYLOAD_FORMAT_INVALID);
+    PAYLOAD_FORMAT_INVALID(MqttReasonCodes.PAYLOAD_FORMAT_INVALID);
 
     private static final @NotNull Mqtt5PubAckReasonCode @NotNull [] VALUES = values();
 
@@ -77,10 +77,6 @@ public enum Mqtt5PubAckReasonCode implements Mqtt5ReasonCode {
         this.code = code;
     }
 
-    Mqtt5PubAckReasonCode(final @NotNull MqttCommonReasonCode reasonCode) {
-        this(reasonCode.getCode());
-    }
-
     @Override
     public int getCode() {
         return code;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubComp.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubComp.java
similarity index 79%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubComp.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubComp.java
index 1cef4f907..4e3499fb9 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubComp.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubComp.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -31,7 +31,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PubComp extends Mqtt5Message {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubCompBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubCompBuilder.java
similarity index 85%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubCompBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubCompBuilder.java
index f0a6039f8..5e949d1fb 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubCompBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubCompBuilder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -30,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PubCompBuilder {
 
     /**
@@ -67,7 +67,7 @@ public interface Mqtt5PubCompBuilder {
      * @see #userProperties(Mqtt5UserProperties)
      */
     @CheckReturnValue
-    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends Mqtt5PubCompBuilder> userProperties();
+    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends Mqtt5PubCompBuilder> userPropertiesWith();
 
     /**
      * @return the Reason Code of the PubComp message.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubCompReasonCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubCompReasonCode.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubCompReasonCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubCompReasonCode.java
index 276997e8a..54ba986f6 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubCompReasonCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubCompReasonCode.java
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.MqttCommonReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
-import org.jetbrains.annotations.NotNull;
+import com.hivemq.client2.internal.mqtt.message.MqttReasonCodes;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -32,12 +31,12 @@ public enum Mqtt5PubCompReasonCode implements Mqtt5ReasonCode {
     /**
      * Packet identifier released. Publication of the QoS 2 message is complete.
      */
-    SUCCESS(MqttCommonReasonCode.SUCCESS),
+    SUCCESS(MqttReasonCodes.SUCCESS),
     /**
      * The packet identifier is not known. This is not an error during recovery, but at other times indicates a mismatch
      * between the session state on the client and server.
      */
-    PACKET_IDENTIFIER_NOT_FOUND(MqttCommonReasonCode.PACKET_IDENTIFIER_NOT_FOUND);
+    PACKET_IDENTIFIER_NOT_FOUND(MqttReasonCodes.PACKET_IDENTIFIER_NOT_FOUND);
 
     private final int code;
 
@@ -45,10 +44,6 @@ public enum Mqtt5PubCompReasonCode implements Mqtt5ReasonCode {
         this.code = code;
     }
 
-    Mqtt5PubCompReasonCode(final @NotNull MqttCommonReasonCode reasonCode) {
-        this(reasonCode.getCode());
-    }
-
     @Override
     public int getCode() {
         return code;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRec.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRec.java
similarity index 78%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRec.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRec.java
index 8e2aa05a7..184ae9a33 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRec.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRec.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubrec;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -31,7 +31,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PubRec extends Mqtt5Message {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRecBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRecBuilder.java
similarity index 85%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRecBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRecBuilder.java
index e090e13df..0965ed6cf 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRecBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRecBuilder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubrec;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -30,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PubRecBuilder {
 
     /**
@@ -75,5 +75,5 @@ public interface Mqtt5PubRecBuilder {
      * @see #userProperties(Mqtt5UserProperties)
      */
     @CheckReturnValue
-    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends Mqtt5PubRecBuilder> userProperties();
+    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends Mqtt5PubRecBuilder> userPropertiesWith();
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRecReasonCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRecReasonCode.java
similarity index 77%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRecReasonCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRecReasonCode.java
index c4c3d5e6c..9b4ef904f 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRecReasonCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRecReasonCode.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubrec;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.MqttCommonReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
+import com.hivemq.client2.internal.mqtt.message.MqttReasonCodes;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -34,40 +34,40 @@ public enum Mqtt5PubRecReasonCode implements Mqtt5ReasonCode {
     /**
      * The message is accepted. Publication of the QoS 2 message proceeds.
      */
-    SUCCESS(MqttCommonReasonCode.SUCCESS),
+    SUCCESS(MqttReasonCodes.SUCCESS),
     /**
      * The message is accepted but there are no subscribers.
      */
-    NO_MATCHING_SUBSCRIBERS(MqttCommonReasonCode.NO_MATCHING_SUBSCRIBERS),
+    NO_MATCHING_SUBSCRIBERS(MqttReasonCodes.NO_MATCHING_SUBSCRIBERS),
     /**
      * The receiver either does not want to reveal the reason for the failure or none of the other reason codes apply.
      */
-    UNSPECIFIED_ERROR(MqttCommonReasonCode.UNSPECIFIED_ERROR),
+    UNSPECIFIED_ERROR(MqttReasonCodes.UNSPECIFIED_ERROR),
     /**
      * The PUBLISH packet is valid but is not accepted by the receiver.
      */
-    IMPLEMENTATION_SPECIFIC_ERROR(MqttCommonReasonCode.IMPLEMENTATION_SPECIFIC_ERROR),
+    IMPLEMENTATION_SPECIFIC_ERROR(MqttReasonCodes.IMPLEMENTATION_SPECIFIC_ERROR),
     /**
      * The sender is not authorized to make the publication.
      */
-    NOT_AUTHORIZED(MqttCommonReasonCode.NOT_AUTHORIZED),
+    NOT_AUTHORIZED(MqttReasonCodes.NOT_AUTHORIZED),
     /**
      * The topic name is formed correctly but is not accepted by the receiver.
      */
-    TOPIC_NAME_INVALID(MqttCommonReasonCode.TOPIC_NAME_INVALID),
+    TOPIC_NAME_INVALID(MqttReasonCodes.TOPIC_NAME_INVALID),
     /**
      * The packet identifier is already in use. This might indicate a mismatch between the session state on the client
      * and server.
      */
-    PACKET_IDENTIFIER_IN_USE(MqttCommonReasonCode.PACKET_IDENTIFIER_IN_USE),
+    PACKET_IDENTIFIER_IN_USE(MqttReasonCodes.PACKET_IDENTIFIER_IN_USE),
     /**
      * An implementation or administrative imposed limit has been exceeded.
      */
-    QUOTA_EXCEEDED(MqttCommonReasonCode.QUOTA_EXCEEDED),
+    QUOTA_EXCEEDED(MqttReasonCodes.QUOTA_EXCEEDED),
     /**
      * The payload does not match the specified payload format indicator.
      */
-    PAYLOAD_FORMAT_INVALID(MqttCommonReasonCode.PAYLOAD_FORMAT_INVALID);
+    PAYLOAD_FORMAT_INVALID(MqttReasonCodes.PAYLOAD_FORMAT_INVALID);
 
     private static final @NotNull Mqtt5PubRecReasonCode @NotNull [] VALUES = values();
 
@@ -77,10 +77,6 @@ public enum Mqtt5PubRecReasonCode implements Mqtt5ReasonCode {
         this.code = code;
     }
 
-    Mqtt5PubRecReasonCode(final @NotNull MqttCommonReasonCode reasonCode) {
-        this(reasonCode.getCode());
-    }
-
     @Override
     public int getCode() {
         return code;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRel.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRel.java
similarity index 78%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRel.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRel.java
index 7d84c6d27..ae8f6df81 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRel.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRel.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubrel;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -31,7 +31,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PubRel extends Mqtt5Message {
 
     /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRelBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRelBuilder.java
similarity index 85%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRelBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRelBuilder.java
index 33e2711ba..966f14441 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRelBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRelBuilder.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubrel;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -30,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PubRelBuilder {
 
     /**
@@ -67,7 +67,7 @@ public interface Mqtt5PubRelBuilder {
      * @see #userProperties(Mqtt5UserProperties)
      */
     @CheckReturnValue
-    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends Mqtt5PubRelBuilder> userProperties();
+    Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends Mqtt5PubRelBuilder> userPropertiesWith();
 
     /**
      * @return the Reason Code of the PubRel message.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRelReasonCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRelReasonCode.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRelReasonCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRelReasonCode.java
index 2db5a1d6a..1aba65422 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRelReasonCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRelReasonCode.java
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubrel;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.internal.mqtt.message.MqttCommonReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
-import org.jetbrains.annotations.NotNull;
+import com.hivemq.client2.internal.mqtt.message.MqttReasonCodes;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -32,12 +31,12 @@ public enum Mqtt5PubRelReasonCode implements Mqtt5ReasonCode {
     /**
      * Message released.
      */
-    SUCCESS(MqttCommonReasonCode.SUCCESS),
+    SUCCESS(MqttReasonCodes.SUCCESS),
     /**
      * The packet identifier is not known. This is not an error during recovery, but at other times indicates a mismatch
      * between the session state on the client and server.
      */
-    PACKET_IDENTIFIER_NOT_FOUND(MqttCommonReasonCode.PACKET_IDENTIFIER_NOT_FOUND);
+    PACKET_IDENTIFIER_NOT_FOUND(MqttReasonCodes.PACKET_IDENTIFIER_NOT_FOUND);
 
     private final int code;
 
@@ -45,10 +44,6 @@ public enum Mqtt5PubRelReasonCode implements Mqtt5ReasonCode {
         this.code = code;
     }
 
-    Mqtt5PubRelReasonCode(final @NotNull MqttCommonReasonCode reasonCode) {
-        this(reasonCode.getCode());
-    }
-
     @Override
     public int getCode() {
         return code;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5Publish.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5Publish.java
similarity index 82%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5Publish.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5Publish.java
index 9d24b1bc3..c6b612dd4 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5Publish.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5Publish.java
@@ -14,17 +14,19 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish;
-
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
+
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishBuilder;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 import java.nio.ByteBuffer;
 import java.util.Optional;
@@ -36,7 +38,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5Publish extends Mqtt5Message {
 
     /**
@@ -82,7 +84,7 @@ public interface Mqtt5Publish extends Mqtt5Message {
     /**
      * @return the optional message expiry interval in seconds of this Publish message.
      */
-    @NotNull OptionalLong getMessageExpiryInterval();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) @NotNull OptionalLong getMessageExpiryInterval();
 
     /**
      * @return the optional payload format indicator of this Publish message.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PublishBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PublishBuilder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PublishBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PublishBuilder.java
index eb3329ddf..cb834c141 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PublishBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PublishBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,7 +26,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PublishBuilder extends Mqtt5PublishBuilderBase<Mqtt5PublishBuilder.Complete> {
 
     /**
@@ -40,7 +40,7 @@ public interface Mqtt5PublishBuilder extends Mqtt5PublishBuilderBase<Mqtt5Publis
     /**
      * {@link Mqtt5PublishBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete extends Mqtt5PublishBuilder, Mqtt5PublishBuilderBase.Complete<Mqtt5PublishBuilder.Complete> {
 
         /**
@@ -62,12 +62,12 @@ interface Complete extends Mqtt5PublishBuilder, Mqtt5PublishBuilderBase.Complete
     }
 
     /**
-     * Builder for a {@link Mqtt5Publish} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client}
+     * Builder for a {@link Mqtt5Publish} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client}
      * which then sends the Publish message.
      *
      * @param <P> the type of the result when the built {@link Mqtt5Publish} is sent by the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5PublishBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -75,7 +75,7 @@ interface Nested<P> extends Mqtt5PublishBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt5Publish} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Mqtt5PublishBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
@@ -88,10 +88,10 @@ interface Complete<P> extends Nested<P>, Mqtt5PublishBuilderBase.Complete<Nested
     }
 
     /**
-     * Builder for a {@link Mqtt5Publish} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client}
+     * Builder for a {@link Mqtt5Publish} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client}
      * which then sends the Publish message without returning a result.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Send<P> extends Mqtt5PublishBuilderBase<Send.Complete<P>> {
 
         /**
@@ -99,7 +99,7 @@ interface Send<P> extends Mqtt5PublishBuilderBase<Send.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt5Publish} is sent by the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Send<P>, Mqtt5PublishBuilderBase.Complete<Send.Complete<P>> {
 
             /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PublishBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PublishBuilderBase.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PublishBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PublishBuilderBase.java
index 93717c410..689d66647 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PublishBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PublishBuilderBase.java
@@ -14,18 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopic;
-import com.hivemq.client.mqtt.datatypes.MqttTopicBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopic;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicBuilder;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Range;
 
 import java.nio.ByteBuffer;
 
@@ -36,7 +38,7 @@
  * @author Bilvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PublishBuilderBase<C extends Mqtt5PublishBuilderBase.Complete<C>> {
 
     /**
@@ -67,14 +69,14 @@ public interface Mqtt5PublishBuilderBase<C extends Mqtt5PublishBuilderBase.Compl
      * @see #topic(MqttTopic)
      */
     @CheckReturnValue
-    MqttTopicBuilder.@NotNull Nested<? extends C> topic();
+    MqttTopicBuilder.@NotNull Nested<? extends C> topicWith();
 
     /**
      * {@link Mqtt5PublishBuilderBase} that is complete which means all mandatory fields are set.
      *
      * @param <C> the type of the complete builder.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete<C extends Mqtt5PublishBuilderBase.Complete<C>> extends Mqtt5PublishBuilderBase<C> {
 
         /**
@@ -122,7 +124,8 @@ interface Complete<C extends Mqtt5PublishBuilderBase.Complete<C>> extends Mqtt5P
          * @return the builder.
          */
         @CheckReturnValue
-        @NotNull C messageExpiryInterval(long messageExpiryInterval);
+        @NotNull C messageExpiryInterval(
+                @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long messageExpiryInterval);
 
         /**
          * Disables the {@link Mqtt5Publish#getMessageExpiryInterval() message expiry}.
@@ -188,7 +191,7 @@ interface Complete<C extends Mqtt5PublishBuilderBase.Complete<C>> extends Mqtt5P
          * @see #responseTopic(MqttTopic)
          */
         @CheckReturnValue
-        MqttTopicBuilder.@NotNull Nested<? extends C> responseTopic();
+        MqttTopicBuilder.@NotNull Nested<? extends C> responseTopicWith();
 
         /**
          * Sets the optional {@link Mqtt5Publish#getCorrelationData() correlation data}.
@@ -229,7 +232,7 @@ interface Complete<C extends Mqtt5PublishBuilderBase.Complete<C>> extends Mqtt5P
          * @see #userProperties(Mqtt5UserProperties)
          */
         @CheckReturnValue
-        Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends C> userProperties();
+        Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends C> userPropertiesWith();
     }
 
     /**
@@ -237,7 +240,7 @@ interface Complete<C extends Mqtt5PublishBuilderBase.Complete<C>> extends Mqtt5P
      *
      * @param <C> the type of the complete builder.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface WillBase<C extends WillBase.Complete<C>> extends Mqtt5PublishBuilderBase<C> {
 
         /**
@@ -245,7 +248,7 @@ interface WillBase<C extends WillBase.Complete<C>> extends Mqtt5PublishBuilderBa
          *
          * @param <C> the type of the complete builder.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<C extends WillBase.Complete<C>> extends Mqtt5PublishBuilderBase.Complete<C>, WillBase<C> {
 
             /**
@@ -257,7 +260,8 @@ interface Complete<C extends WillBase.Complete<C>> extends Mqtt5PublishBuilderBa
              * @return the builder.
              */
             @CheckReturnValue
-            @NotNull C delayInterval(long delayInterval);
+            @NotNull C delayInterval(
+                    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long delayInterval);
         }
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PublishResult.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PublishResult.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PublishResult.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PublishResult.java
index 92d275e39..9e8708630 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PublishResult.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PublishResult.java
@@ -14,13 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAck;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubComp;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRec;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRel;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Optional;
@@ -29,12 +25,12 @@
  * Result for an {@link Mqtt5Publish MQTT 5 Publish message} sent by the client.
  * <p>
  * The result is provided if a Publish message is successfully delivered (sent or acknowledged respectively to its
- * {@link com.hivemq.client.mqtt.datatypes.MqttQos QoS} level).
+ * {@link com.hivemq.client2.mqtt.datatypes.MqttQos QoS} level).
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5PublishResult {
 
     /**
@@ -48,12 +44,12 @@ public interface Mqtt5PublishResult {
     @NotNull Optional<Throwable> getError();
 
     /**
-     * Result for a {@link Mqtt5Publish MQTT 5 Publish message} with {@link com.hivemq.client.mqtt.datatypes.MqttQos#AT_LEAST_ONCE
+     * Result for a {@link Mqtt5Publish MQTT 5 Publish message} with {@link com.hivemq.client2.mqtt.datatypes.MqttQos#AT_LEAST_ONCE
      * QoS level 1} sent by the client.
      * <p>
      * This result additionally provides the {@link Mqtt5PubAck PubAck message} that acknowledged the Publish message.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Mqtt5Qos1Result extends Mqtt5PublishResult {
 
         /**
@@ -63,12 +59,12 @@ interface Mqtt5Qos1Result extends Mqtt5PublishResult {
     }
 
     /**
-     * Result for a {@link Mqtt5Publish MQTT 5 Publish message} with {@link com.hivemq.client.mqtt.datatypes.MqttQos#EXACTLY_ONCE
+     * Result for a {@link Mqtt5Publish MQTT 5 Publish message} with {@link com.hivemq.client2.mqtt.datatypes.MqttQos#EXACTLY_ONCE
      * QoS level 2} sent by the client.
      * <p>
      * This result additionally provides the {@link Mqtt5PubRec PubRec message} that acknowledged the Publish message.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Mqtt5Qos2Result extends Mqtt5PublishResult {
 
         /**
@@ -78,7 +74,7 @@ interface Mqtt5Qos2Result extends Mqtt5PublishResult {
     }
 
     /**
-     * Result for a {@link Mqtt5Publish MQTT 5 Publish message} with {@link com.hivemq.client.mqtt.datatypes.MqttQos#EXACTLY_ONCE
+     * Result for a {@link Mqtt5Publish MQTT 5 Publish message} with {@link com.hivemq.client2.mqtt.datatypes.MqttQos#EXACTLY_ONCE
      * QoS level 2} sent by the client.
      * <p>
      * This result additionally provides the {@link Mqtt5PubRec PubRec message}, {@link Mqtt5PubRel PubRel message} and
@@ -86,7 +82,7 @@ interface Mqtt5Qos2Result extends Mqtt5PublishResult {
      * <p>
      * By default just a {@link Mqtt5Qos2Result} is provided as a result for a Publish message with QoS level 2.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Mqtt5Qos2CompleteResult extends Mqtt5Qos2Result {
 
         /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5WillPublish.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5WillPublish.java
similarity index 75%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5WillPublish.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5WillPublish.java
index 068be0d4f..06b0e5722 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5WillPublish.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5WillPublish.java
@@ -14,20 +14,22 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishBuilder;
+import com.hivemq.client2.internal.util.UnsignedDataTypes;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Range;
 
 /**
- * MQTT 5 Will Publish which can be a part of an {@link com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect MQTT 5
- * Connect message}.
+ * MQTT 5 Will Publish which can be a part of an {@link com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect MQTT
+ * 5 Connect message}.
  *
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5WillPublish extends Mqtt5Publish {
 
     /**
@@ -47,7 +49,7 @@ public interface Mqtt5WillPublish extends Mqtt5Publish {
     /**
      * @return the delay of this Will Publish. The default is {@link #DEFAULT_DELAY_INTERVAL}.
      */
-    long getDelayInterval();
+    @Range(from = 0, to = UnsignedDataTypes.UNSIGNED_INT_MAX_VALUE) long getDelayInterval();
 
     /**
      * Creates a builder for extending this Will Publish.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5WillPublishBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5WillPublishBuilder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5WillPublishBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5WillPublishBuilder.java
index 1f79263e9..9b96188c6 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5WillPublishBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5WillPublishBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,13 +26,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5WillPublishBuilder extends Mqtt5PublishBuilderBase.WillBase<Mqtt5WillPublishBuilder.Complete> {
 
     /**
      * {@link Mqtt5WillPublishBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete extends Mqtt5WillPublishBuilder,
             Mqtt5PublishBuilderBase.WillBase.Complete<Mqtt5WillPublishBuilder.Complete> {
 
@@ -50,7 +50,7 @@ interface Complete extends Mqtt5WillPublishBuilder,
      *
      * @param <P> the type of the result when the built {@link Mqtt5WillPublish} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5PublishBuilderBase.WillBase<Nested.Complete<P>> {
 
         /**
@@ -58,7 +58,7 @@ interface Nested<P> extends Mqtt5PublishBuilderBase.WillBase<Nested.Complete<P>>
          *
          * @param <P> the type of the result when the built {@link Mqtt5WillPublish} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Mqtt5PublishBuilderBase.WillBase.Complete<Nested.Complete<P>> {
 
             /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandling.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandling.java
similarity index 80%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandling.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandling.java
index 4e1b941db..67cf65005 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandling.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandling.java
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
 
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -33,12 +34,14 @@ public enum Mqtt5RetainHandling {
     /**
      * Send retained messages for the current subscription only if the subscription does not currently exist.
      */
-    SEND_IF_SUBSCRIPTION_DOES_NOT_EXIST,
+    SEND_IF_NEW_SUBSCRIPTION,
     /**
      * Do not send retained messages for the current subscription.
      */
     DO_NOT_SEND;
 
+    private static final @NotNull Mqtt5RetainHandling @NotNull [] VALUES = values();
+
     /**
      * @return the byte code of this Retain Handling.
      */
@@ -53,13 +56,9 @@ public int getCode() {
      * @return the Retain Handling belonging to the byte code or null if the byte code is not a valid Retain Handling.
      */
     public static @Nullable Mqtt5RetainHandling fromCode(final int code) {
-        if (code == SEND.getCode()) {
-            return SEND;
-        } else if (code == SEND_IF_SUBSCRIPTION_DOES_NOT_EXIST.getCode()) {
-            return SEND_IF_SUBSCRIPTION_DOES_NOT_EXIST;
-        } else if (code == DO_NOT_SEND.getCode()) {
-            return DO_NOT_SEND;
+        if (code < 0 || code >= VALUES.length) {
+            return null;
         }
-        return null;
+        return VALUES[code];
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/suback/Mqtt5SubAck.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubAck.java
similarity index 69%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/suback/Mqtt5SubAck.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubAck.java
index 55b8d8de0..e9338ab9b 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/suback/Mqtt5SubAck.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubAck.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe.suback;
-
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
+
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.List;
 import java.util.Optional;
@@ -33,15 +33,15 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5SubAck extends Mqtt5Message {
 
     /**
-     * @return the Reason Codes of this SubAck message, each belonging to a {@link com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscription
-     *         Subscription} in the corresponding {@link com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe
+     * @return the Reason Codes of this SubAck message, each belonging to a {@link com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscription
+     *         Subscription} in the corresponding {@link com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe
      *         Subscribe message} in the same order.
      */
-    @Immutable @NotNull List<@NotNull Mqtt5SubAckReasonCode> getReasonCodes();
+    @Unmodifiable @NotNull List<@NotNull Mqtt5SubAckReasonCode> getReasonCodes();
 
     /**
      * @return the optional reason string of this SubAck message.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/suback/Mqtt5SubAckReasonCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubAckReasonCode.java
similarity index 72%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/suback/Mqtt5SubAckReasonCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubAckReasonCode.java
index 334c63a03..e16d8d69b 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/suback/Mqtt5SubAckReasonCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubAckReasonCode.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe.suback;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
 
-import com.hivemq.client.internal.mqtt.message.MqttCommonReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
+import com.hivemq.client2.internal.mqtt.message.MqttReasonCodes;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -33,52 +33,52 @@ public enum Mqtt5SubAckReasonCode implements Mqtt5ReasonCode {
      * The subscription is accepted and the maximum QoS sent will be QoS 0 (this might be a lower QoS than was
      * requested).
      */
-    GRANTED_QOS_0(0x00),
+    GRANTED_QOS_0(MqttReasonCodes.SUCCESS),
     /**
      * The subscription is accepted and the maximum QoS sent will be QoS 1 (this might be a lower QoS than was
      * requested).
      */
-    GRANTED_QOS_1(0x01),
+    GRANTED_QOS_1(MqttReasonCodes.GRANTED_QOS_1),
     /**
      * The subscription is accepted and the maximum QoS sent will be QoS 2.
      */
-    GRANTED_QOS_2(0x02),
+    GRANTED_QOS_2(MqttReasonCodes.GRANTED_QOS_2),
     /**
      * The server either does not want to reveal the reason for the failure or none of the other reason codes apply.
      */
-    UNSPECIFIED_ERROR(MqttCommonReasonCode.UNSPECIFIED_ERROR),
+    UNSPECIFIED_ERROR(MqttReasonCodes.UNSPECIFIED_ERROR),
     /**
      * The SUBSCRIBE packet is valid but is not accepted by the server.
      */
-    IMPLEMENTATION_SPECIFIC_ERROR(MqttCommonReasonCode.IMPLEMENTATION_SPECIFIC_ERROR),
+    IMPLEMENTATION_SPECIFIC_ERROR(MqttReasonCodes.IMPLEMENTATION_SPECIFIC_ERROR),
     /**
      * The client is not authorized to make the subscription.
      */
-    NOT_AUTHORIZED(MqttCommonReasonCode.NOT_AUTHORIZED),
+    NOT_AUTHORIZED(MqttReasonCodes.NOT_AUTHORIZED),
     /**
      * The topic filter is formed correctly but is not accepted by the server (for this client).
      */
-    TOPIC_FILTER_INVALID(MqttCommonReasonCode.TOPIC_FILTER_INVALID),
+    TOPIC_FILTER_INVALID(MqttReasonCodes.TOPIC_FILTER_INVALID),
     /**
      * The specified packet identifier is already in use.
      */
-    PACKET_IDENTIFIER_IN_USE(MqttCommonReasonCode.PACKET_IDENTIFIER_IN_USE),
+    PACKET_IDENTIFIER_IN_USE(MqttReasonCodes.PACKET_IDENTIFIER_IN_USE),
     /**
      * An implementation or administrative imposed limit has been exceeded.
      */
-    QUOTA_EXCEEDED(MqttCommonReasonCode.QUOTA_EXCEEDED),
+    QUOTA_EXCEEDED(MqttReasonCodes.QUOTA_EXCEEDED),
     /**
      * The server does not support shared subscriptions (for this client).
      */
-    SHARED_SUBSCRIPTIONS_NOT_SUPPORTED(MqttCommonReasonCode.SHARED_SUBSCRIPTIONS_NOT_SUPPORTED),
+    SHARED_SUBSCRIPTIONS_NOT_SUPPORTED(MqttReasonCodes.SHARED_SUBSCRIPTIONS_NOT_SUPPORTED),
     /**
      * The server does not support subscription identifiers (for this client).
      */
-    SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED(MqttCommonReasonCode.SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED),
+    SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED(MqttReasonCodes.SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED),
     /**
      * The server does not support wildcard subscriptions (for this client).
      */
-    WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED(MqttCommonReasonCode.WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED);
+    WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED(MqttReasonCodes.WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED);
 
     private static final @NotNull Mqtt5SubAckReasonCode @NotNull [] VALUES = values();
 
@@ -88,10 +88,6 @@ public enum Mqtt5SubAckReasonCode implements Mqtt5ReasonCode {
         this.code = code;
     }
 
-    Mqtt5SubAckReasonCode(final @NotNull MqttCommonReasonCode reasonCode) {
-        this(reasonCode.getCode());
-    }
-
     @Override
     public int getCode() {
         return code;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5Subscribe.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5Subscribe.java
similarity index 76%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5Subscribe.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5Subscribe.java
index 972ab6069..c5873a0f2 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5Subscribe.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5Subscribe.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.List;
 
@@ -32,7 +32,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5Subscribe extends Mqtt5Message {
 
     /**
@@ -48,7 +48,7 @@ public interface Mqtt5Subscribe extends Mqtt5Message {
      * @return the {@link Mqtt5Subscription Subscriptions} of this Subscribe message. The list contains at least one
      *         Subscription.
      */
-    @Immutable @NotNull List<@NotNull ? extends Mqtt5Subscription> getSubscriptions();
+    @Unmodifiable @NotNull List<@NotNull ? extends Mqtt5Subscription> getSubscriptions();
 
     /**
      * @return the optional user properties of this Subscribe message.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilder.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilder.java
index 579f905a7..4550337f7 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,13 +26,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5SubscribeBuilder extends Mqtt5SubscribeBuilderBase<Mqtt5SubscribeBuilder.Complete> {
 
     /**
      * {@link Mqtt5SubscribeBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete
             extends Mqtt5SubscribeBuilder, Mqtt5SubscribeBuilderBase.Complete<Mqtt5SubscribeBuilder.Complete> {
 
@@ -48,7 +48,7 @@ interface Complete
     /**
      * {@link Mqtt5SubscribeBuilder} that provides additional methods for the first subscription.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Start extends Mqtt5SubscribeBuilder,
             Mqtt5SubscribeBuilderBase.Start<Mqtt5SubscribeBuilder.Complete, Mqtt5SubscribeBuilder.Start.Complete> {
 
@@ -56,7 +56,7 @@ interface Start extends Mqtt5SubscribeBuilder,
          * {@link Mqtt5SubscribeBuilder.Start} that is complete which means all mandatory fields are set.
          */
         // @formatter:off
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete extends Mqtt5SubscribeBuilder.Start, Mqtt5SubscribeBuilder.Complete,
                 Mqtt5SubscribeBuilderBase.Start.Complete<
                         Mqtt5SubscribeBuilder.Complete, Mqtt5SubscribeBuilder.Start.Complete> {}
@@ -68,7 +68,7 @@ interface Complete extends Mqtt5SubscribeBuilder.Start, Mqtt5SubscribeBuilder.Co
      *
      * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5SubscribeBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -76,7 +76,7 @@ interface Nested<P> extends Mqtt5SubscribeBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Mqtt5SubscribeBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
@@ -92,7 +92,7 @@ interface Complete<P> extends Nested<P>, Mqtt5SubscribeBuilderBase.Complete<Nest
          *
          * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Start<P>
                 extends Nested<P>, Mqtt5SubscribeBuilderBase.Start<Nested.Complete<P>, Nested.Start.Complete<P>> {
 
@@ -101,19 +101,19 @@ interface Start<P>
              *
              * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is applied to the parent.
              */
-            @DoNotImplement
+            @ApiStatus.NonExtendable
             interface Complete<P> extends Nested.Start<P>, Nested.Complete<P>,
                     Mqtt5SubscribeBuilderBase.Start.Complete<Nested.Complete<P>, Nested.Start.Complete<P>> {}
         }
     }
 
     /**
-     * Builder for a {@link Mqtt5Subscribe} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt5.Mqtt5Client
+     * Builder for a {@link Mqtt5Subscribe} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt5.Mqtt5Client
      * Mqtt5Client} which then sends the Subscribe message.
      *
      * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is sent by the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Send<P> extends Mqtt5SubscribeBuilderBase<Send.Complete<P>> {
 
         /**
@@ -121,7 +121,7 @@ interface Send<P> extends Mqtt5SubscribeBuilderBase<Send.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is sent by the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Send<P>, Mqtt5SubscribeBuilderBase.Complete<Send.Complete<P>> {
 
             /**
@@ -137,7 +137,7 @@ interface Complete<P> extends Send<P>, Mqtt5SubscribeBuilderBase.Complete<Send.C
          *
          * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is sent by the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Start<P> extends Send<P>, Mqtt5SubscribeBuilderBase.Start<Send.Complete<P>, Send.Start.Complete<P>> {
 
             /**
@@ -145,7 +145,7 @@ interface Start<P> extends Send<P>, Mqtt5SubscribeBuilderBase.Start<Send.Complet
              *
              * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is sent by the parent.
              */
-            @DoNotImplement
+            @ApiStatus.NonExtendable
             interface Complete<P> extends Send.Start<P>, Send.Complete<P>,
                     Mqtt5SubscribeBuilderBase.Start.Complete<Send.Complete<P>, Send.Start.Complete<P>> {}
         }
@@ -153,12 +153,12 @@ interface Complete<P> extends Send.Start<P>, Send.Complete<P>,
 
     /**
      * Builder for a {@link Mqtt5Subscribe} and additional arguments that are applied to a parent {@link
-     * com.hivemq.client.mqtt.mqtt5.Mqtt5Client Mqtt5Client} <code>subscribePublishes</code> call.
+     * com.hivemq.client2.mqtt.mqtt5.Mqtt5Client Mqtt5Client} <code>subscribePublishes</code> call.
      *
      * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is applied to the parent.
      * @since 1.2
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Publishes<P> extends Mqtt5SubscribeBuilderBase<Publishes.Complete<P>> {
 
         /**
@@ -166,16 +166,16 @@ interface Publishes<P> extends Mqtt5SubscribeBuilderBase<Publishes.Complete<P>>
          *
          * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P>
-                extends Publishes<P>, Publishes.Args<P>, Mqtt5SubscribeBuilderBase.Complete<Publishes.Complete<P>> {}
+                extends Publishes<P>, AfterComplete<P>, Mqtt5SubscribeBuilderBase.Complete<Publishes.Complete<P>> {}
 
         /**
          * {@link Publishes} that provides additional methods for the first subscription.
          *
          * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Start<P> extends Publishes<P>,
                 Mqtt5SubscribeBuilderBase.Start<Publishes.Complete<P>, Publishes.Start.Complete<P>> {
 
@@ -184,19 +184,19 @@ interface Start<P> extends Publishes<P>,
              *
              * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is applied to the parent.
              */
-            @DoNotImplement
+            @ApiStatus.NonExtendable
             interface Complete<P> extends Publishes.Start<P>, Publishes.Complete<P>,
                     Mqtt5SubscribeBuilderBase.Start.Complete<Publishes.Complete<P>, Publishes.Start.Complete<P>> {}
         }
 
         /**
          * Builder for additional arguments alongside the {@link Mqtt5Subscribe} that are applied to a parent {@link
-         * com.hivemq.client.mqtt.mqtt5.Mqtt5Client Mqtt5Client} <code>subscribePublishes</code> call.
+         * com.hivemq.client2.mqtt.mqtt5.Mqtt5Client Mqtt5Client} <code>subscribePublishes</code> call.
          *
          * @param <P> the type of the result when the built {@link Mqtt5Subscribe} is applied to the parent.
          */
-        @DoNotImplement
-        interface Args<P> {
+        @ApiStatus.NonExtendable
+        interface AfterComplete<P> {
 
             /**
              * Sets whether the matching Publish messages consumed via the subscriptions are acknowledged manually.
@@ -205,7 +205,7 @@ interface Args<P> {
              * @return the builder.
              */
             @CheckReturnValue
-            @NotNull Args<P> manualAcknowledgement(boolean manualAcknowledgement);
+            @NotNull AfterComplete<P> manualAcknowledgement(boolean manualAcknowledgement);
 
             /**
              * Builds the {@link Mqtt5Subscribe} and applies it and additional arguments to the parent.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilderBase.java
similarity index 92%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilderBase.java
index 677ff3a9a..36ece9dbc 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscribeBuilderBase.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
@@ -32,7 +32,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5SubscribeBuilderBase<C extends Mqtt5SubscribeBuilderBase.Complete<C>> {
 
     /**
@@ -56,7 +56,7 @@ public interface Mqtt5SubscribeBuilderBase<C extends Mqtt5SubscribeBuilderBase.C
      * @see #addSubscription(Mqtt5Subscription)
      */
     @CheckReturnValue
-    Mqtt5SubscriptionBuilder.@NotNull Nested<? extends C> addSubscription();
+    Mqtt5SubscriptionBuilder.@NotNull Nested<? extends C> addSubscriptionWith();
 
     /**
      * Adds {@link Mqtt5Subscription}s to the {@link Mqtt5Subscribe#getSubscriptions() list of subscriptions}. At least
@@ -96,7 +96,7 @@ public interface Mqtt5SubscribeBuilderBase<C extends Mqtt5SubscribeBuilderBase.C
      *
      * @param <C> the type of the complete builder.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete<C extends Mqtt5SubscribeBuilderBase.Complete<C>> extends Mqtt5SubscribeBuilderBase<C> {
 
         /**
@@ -118,7 +118,7 @@ interface Complete<C extends Mqtt5SubscribeBuilderBase.Complete<C>> extends Mqtt
          * @see #userProperties(Mqtt5UserProperties)
          */
         @CheckReturnValue
-        Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends C> userProperties();
+        Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends C> userPropertiesWith();
     }
 
     /**
@@ -128,7 +128,7 @@ interface Complete<C extends Mqtt5SubscribeBuilderBase.Complete<C>> extends Mqtt
      * @param <SC> the type of the complete start builder.
      */
     // @formatter:off
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Start<
             C extends Mqtt5SubscribeBuilderBase.Complete<C>,
             SC extends Mqtt5SubscribeBuilderBase.Start.Complete<C, SC>>
@@ -142,7 +142,7 @@ interface Start<
          * @param <SC> the type of the complete start builder.
          */
         // @formatter:off
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<
                 C extends Mqtt5SubscribeBuilderBase.Complete<C>,
                 SC extends Mqtt5SubscribeBuilderBase.Start.Complete<C, SC>>
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5Subscription.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5Subscription.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5Subscription.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5Subscription.java
index 88e7e4a8e..453e4f5f1 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5Subscription.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5Subscription.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscriptionBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscriptionBuilder;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -28,7 +28,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5Subscription {
 
     /**
@@ -64,9 +64,9 @@ public interface Mqtt5Subscription {
     @NotNull MqttTopicFilter getTopicFilter();
 
     /**
-     * @return the QoS of this Subscription.
+     * @return the maximum QoS of this Subscription.
      */
-    @NotNull MqttQos getQos();
+    @NotNull MqttQos getMaxQos();
 
     /**
      * @return whether the client must not receive messages published by itself. The default is {@link
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilder.java
index aaea78f51..c463c77fa 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,13 +26,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5SubscriptionBuilder extends Mqtt5SubscriptionBuilderBase<Mqtt5SubscriptionBuilder.Complete> {
 
     /**
      * {@link Mqtt5Subscription} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete
             extends Mqtt5SubscriptionBuilder, Mqtt5SubscriptionBuilderBase.Complete<Mqtt5SubscriptionBuilder.Complete> {
 
@@ -50,7 +50,7 @@ interface Complete
      *
      * @param <P> the type of the result when the built {@link Mqtt5Subscription} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5SubscriptionBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -58,7 +58,7 @@ interface Nested<P> extends Mqtt5SubscriptionBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt5Subscription} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Mqtt5SubscriptionBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilderBase.java
similarity index 86%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilderBase.java
index de53418e2..5d314945c 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubscriptionBuilderBase.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilterBuilder;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilterBuilder;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -30,7 +30,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5SubscriptionBuilderBase<C extends Mqtt5SubscriptionBuilderBase.Complete<C>> {
 
     /**
@@ -62,24 +62,24 @@ public interface Mqtt5SubscriptionBuilderBase<C extends Mqtt5SubscriptionBuilder
      * @see #topicFilter(MqttTopicFilter)
      */
     @CheckReturnValue
-    MqttTopicFilterBuilder.@NotNull Nested<? extends C> topicFilter();
+    MqttTopicFilterBuilder.@NotNull Nested<? extends C> topicFilterWith();
 
     /**
      * {@link Mqtt5SubscriptionBuilderBase} that is complete which means all mandatory fields are set.
      *
      * @param <C> the type of the complete builder.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete<C extends Mqtt5SubscriptionBuilderBase.Complete<C>> extends Mqtt5SubscriptionBuilderBase<C> {
 
         /**
-         * Sets the {@link Mqtt5Subscription#getQos() QoS}.
+         * Sets the {@link Mqtt5Subscription#getMaxQos() maximum QoS}.
          *
-         * @param qos the QoS.
+         * @param maxQos the maximum QoS.
          * @return the builder.
          */
         @CheckReturnValue
-        @NotNull C qos(@NotNull MqttQos qos);
+        @NotNull C maxQos(@NotNull MqttQos maxQos);
 
         /**
          * Sets whether the subscription is {@link Mqtt5Subscription#isNoLocal() not local}.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/unsuback/Mqtt5UnsubAck.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubAck.java
similarity index 70%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/unsuback/Mqtt5UnsubAck.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubAck.java
index 7c442bfed..9bd4f1b15 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/unsuback/Mqtt5UnsubAck.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubAck.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback;
-
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+package com.hivemq.client2.mqtt.mqtt5.message.unsubscribe;
+
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.List;
 import java.util.Optional;
@@ -33,15 +33,15 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5UnsubAck extends Mqtt5Message {
 
     /**
      * @return the Reason Codes of this UnsubAck message, each belonging to a Topic Filter in the corresponding {@link
-     *         com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe Unsubscribe message} in the same
+     *         com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe Unsubscribe message} in the same
      *         order.
      */
-    @Immutable @NotNull List<@NotNull Mqtt5UnsubAckReasonCode> getReasonCodes();
+    @Unmodifiable @NotNull List<@NotNull Mqtt5UnsubAckReasonCode> getReasonCodes();
 
     /**
      * @return the optional reason string of this UnsubAck message.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/unsuback/Mqtt5UnsubAckReasonCode.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubAckReasonCode.java
similarity index 75%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/unsuback/Mqtt5UnsubAckReasonCode.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubAckReasonCode.java
index 94f5e858c..43f6b5a8a 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/unsuback/Mqtt5UnsubAckReasonCode.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubAckReasonCode.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback;
+package com.hivemq.client2.mqtt.mqtt5.message.unsubscribe;
 
-import com.hivemq.client.internal.mqtt.message.MqttCommonReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5ReasonCode;
+import com.hivemq.client2.internal.mqtt.message.MqttReasonCodes;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5ReasonCode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -32,31 +32,31 @@ public enum Mqtt5UnsubAckReasonCode implements Mqtt5ReasonCode {
     /**
      * The subscription is deleted.
      */
-    SUCCESS(MqttCommonReasonCode.SUCCESS),
+    SUCCESS(MqttReasonCodes.SUCCESS),
     /**
      * No matching topic filter is being used by the client.
      */
-    NO_SUBSCRIPTIONS_EXISTED(0x11),
+    NO_SUBSCRIPTIONS_EXISTED(MqttReasonCodes.NO_SUBSCRIPTIONS_EXISTED),
     /**
      * The server either does not want to reveal the reason for the failure or none of the other reason codes apply.
      */
-    UNSPECIFIED_ERROR(MqttCommonReasonCode.UNSPECIFIED_ERROR),
+    UNSPECIFIED_ERROR(MqttReasonCodes.UNSPECIFIED_ERROR),
     /**
      * The UNSUBSCRIBE packet is valid but is not accepted by the server.
      */
-    IMPLEMENTATION_SPECIFIC_ERROR(MqttCommonReasonCode.IMPLEMENTATION_SPECIFIC_ERROR),
+    IMPLEMENTATION_SPECIFIC_ERROR(MqttReasonCodes.IMPLEMENTATION_SPECIFIC_ERROR),
     /**
      * The client is not authorized to unsubscribe.
      */
-    NOT_AUTHORIZED(MqttCommonReasonCode.NOT_AUTHORIZED),
+    NOT_AUTHORIZED(MqttReasonCodes.NOT_AUTHORIZED),
     /**
      * The topic filter is formed correctly but is not accepted by the server (for this client).
      */
-    TOPIC_FILTER_INVALID(MqttCommonReasonCode.TOPIC_FILTER_INVALID),
+    TOPIC_FILTER_INVALID(MqttReasonCodes.TOPIC_FILTER_INVALID),
     /**
      * The specified packet identifier is already in use.
      */
-    PACKET_IDENTIFIER_IN_USE(MqttCommonReasonCode.PACKET_IDENTIFIER_IN_USE);
+    PACKET_IDENTIFIER_IN_USE(MqttReasonCodes.PACKET_IDENTIFIER_IN_USE);
 
     private static final @NotNull Mqtt5UnsubAckReasonCode @NotNull [] VALUES = values();
 
@@ -66,10 +66,6 @@ public enum Mqtt5UnsubAckReasonCode implements Mqtt5ReasonCode {
         this.code = code;
     }
 
-    Mqtt5UnsubAckReasonCode(final @NotNull MqttCommonReasonCode reasonCode) {
-        this(reasonCode.getCode());
-    }
-
     @Override
     public int getCode() {
         return code;
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/Mqtt5Unsubscribe.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5Unsubscribe.java
similarity index 74%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/Mqtt5Unsubscribe.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5Unsubscribe.java
index deef107fe..81f40e2f2 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/Mqtt5Unsubscribe.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5Unsubscribe.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.unsubscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.unsubscribe;
 
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.annotations.Immutable;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribeBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribeBuilder;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
 
 import java.util.List;
 
@@ -33,7 +33,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5Unsubscribe extends Mqtt5Message {
 
     /**
@@ -48,7 +48,7 @@ public interface Mqtt5Unsubscribe extends Mqtt5Message {
     /**
      * @return the Topic Filters of this Unsubscribe message. The list contains at least one Topic Filter.
      */
-    @Immutable @NotNull List<@NotNull ? extends MqttTopicFilter> getTopicFilters();
+    @Unmodifiable @NotNull List<@NotNull ? extends MqttTopicFilter> getTopicFilters();
 
     /**
      * @return the optional user properties of this Unsubscribe message.
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilder.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilder.java
similarity index 89%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilder.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilder.java
index 3255a2774..b544ee7aa 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilder.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilder.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.unsubscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.unsubscribe;
 
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
+import com.hivemq.client2.annotations.CheckReturnValue;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -26,13 +26,13 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5UnsubscribeBuilder extends Mqtt5UnsubscribeBuilderBase<Mqtt5UnsubscribeBuilder.Complete> {
 
     /**
      * {@link Mqtt5UnsubscribeBuilder} that is complete which means all mandatory fields are set.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete
             extends Mqtt5UnsubscribeBuilder, Mqtt5UnsubscribeBuilderBase.Complete<Mqtt5UnsubscribeBuilder.Complete> {
 
@@ -48,7 +48,7 @@ interface Complete
     /**
      * {@link Mqtt5UnsubscribeBuilder} that provides additional methods for the first Topic Filter.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Start
             extends Mqtt5UnsubscribeBuilder, Mqtt5UnsubscribeBuilderBase.Start<Mqtt5UnsubscribeBuilder.Complete> {}
 
@@ -57,7 +57,7 @@ interface Start
      *
      * @param <P> the type of the result when the built {@link Mqtt5Unsubscribe} is applied to the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Nested<P> extends Mqtt5UnsubscribeBuilderBase<Nested.Complete<P>> {
 
         /**
@@ -65,7 +65,7 @@ interface Nested<P> extends Mqtt5UnsubscribeBuilderBase<Nested.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt5Unsubscribe} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Nested<P>, Mqtt5UnsubscribeBuilderBase.Complete<Nested.Complete<P>> {
 
             /**
@@ -81,17 +81,17 @@ interface Complete<P> extends Nested<P>, Mqtt5UnsubscribeBuilderBase.Complete<Ne
          *
          * @param <P> the type of the result when the built {@link Mqtt5Unsubscribe} is applied to the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Start<P> extends Nested<P>, Mqtt5UnsubscribeBuilderBase.Start<Nested.Complete<P>> {}
     }
 
     /**
-     * Builder for a {@link Mqtt5Unsubscribe} that is applied to a parent {@link com.hivemq.client.mqtt.mqtt3.Mqtt3Client}
+     * Builder for a {@link Mqtt5Unsubscribe} that is applied to a parent {@link com.hivemq.client2.mqtt.mqtt3.Mqtt3Client}
      * which then sends the Unsubscribe message.
      *
      * @param <P> the type of the result when the built {@link Mqtt5Unsubscribe} is sent by the parent.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Send<P> extends Mqtt5UnsubscribeBuilderBase<Send.Complete<P>> {
 
         /**
@@ -99,7 +99,7 @@ interface Send<P> extends Mqtt5UnsubscribeBuilderBase<Send.Complete<P>> {
          *
          * @param <P> the type of the result when the built {@link Mqtt5Unsubscribe} is sent by the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Complete<P> extends Send<P>, Mqtt5UnsubscribeBuilderBase.Complete<Send.Complete<P>> {
 
             /**
@@ -116,7 +116,7 @@ interface Complete<P> extends Send<P>, Mqtt5UnsubscribeBuilderBase.Complete<Send
          *
          * @param <P> the type of the result when the built {@link Mqtt5Unsubscribe} is sent by the parent.
          */
-        @DoNotImplement
+        @ApiStatus.NonExtendable
         interface Start<P> extends Send<P>, Mqtt5UnsubscribeBuilderBase.Start<Send.Complete<P>> {}
     }
 }
diff --git a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilderBase.java b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilderBase.java
similarity index 91%
rename from src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilderBase.java
rename to src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilderBase.java
index 4b79645de..1888d5261 100644
--- a/src/main/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilderBase.java
+++ b/src/main/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubscribeBuilderBase.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.unsubscribe;
-
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.annotations.DoNotImplement;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilterBuilder;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.unsubscribe;
+
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilterBuilder;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
@@ -35,7 +35,7 @@
  * @author Silvio Giebl
  * @since 1.0
  */
-@DoNotImplement
+@ApiStatus.NonExtendable
 public interface Mqtt5UnsubscribeBuilderBase<C extends Mqtt5UnsubscribeBuilderBase.Complete<C>> {
 
     /**
@@ -69,7 +69,7 @@ public interface Mqtt5UnsubscribeBuilderBase<C extends Mqtt5UnsubscribeBuilderBa
      * @see #addTopicFilter(MqttTopicFilter)
      */
     @CheckReturnValue
-    MqttTopicFilterBuilder.@NotNull Nested<? extends C> addTopicFilter();
+    MqttTopicFilterBuilder.@NotNull Nested<? extends C> addTopicFilterWith();
 
     /**
      * Adds {@link MqttTopicFilter Topic Filters} to the {@link Mqtt5Unsubscribe#getTopicFilters() list of Topic
@@ -118,7 +118,7 @@ public interface Mqtt5UnsubscribeBuilderBase<C extends Mqtt5UnsubscribeBuilderBa
      *
      * @param <C> the type of the complete builder.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Complete<C extends Mqtt5UnsubscribeBuilderBase.Complete<C>> extends Mqtt5UnsubscribeBuilderBase<C> {
 
         /**
@@ -140,7 +140,7 @@ interface Complete<C extends Mqtt5UnsubscribeBuilderBase.Complete<C>> extends Mq
          * @see #userProperties(Mqtt5UserProperties)
          */
         @CheckReturnValue
-        Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends C> userProperties();
+        Mqtt5UserPropertiesBuilder.@NotNull Nested<? extends C> userPropertiesWith();
     }
 
     /**
@@ -148,7 +148,7 @@ interface Complete<C extends Mqtt5UnsubscribeBuilderBase.Complete<C>> extends Mq
      *
      * @param <C> the type of the complete builder.
      */
-    @DoNotImplement
+    @ApiStatus.NonExtendable
     interface Start<C extends Mqtt5UnsubscribeBuilderBase.Complete<C>> extends Mqtt5UnsubscribeBuilderBase<C> {
 
         /**
@@ -180,6 +180,6 @@ interface Start<C extends Mqtt5UnsubscribeBuilderBase.Complete<C>> extends Mqtt5
          * @see #addTopicFilter(MqttTopicFilter)
          */
         @CheckReturnValue
-        MqttTopicFilterBuilder.@NotNull Nested<? extends C> topicFilter();
+        MqttTopicFilterBuilder.@NotNull Nested<? extends C> topicFilterWith();
     }
 }
diff --git a/src/main/java/com/hivemq/client/rx/FlowableWithSingle.java b/src/main/java/com/hivemq/client2/rx/FlowableWithSingle.java
similarity index 93%
rename from src/main/java/com/hivemq/client/rx/FlowableWithSingle.java
rename to src/main/java/com/hivemq/client2/rx/FlowableWithSingle.java
index 5eb5de2be..615f4d833 100644
--- a/src/main/java/com/hivemq/client/rx/FlowableWithSingle.java
+++ b/src/main/java/com/hivemq/client2/rx/FlowableWithSingle.java
@@ -14,24 +14,24 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx;
-
-import com.hivemq.client.annotations.CheckReturnValue;
-import com.hivemq.client.internal.rx.WithSingleStrictSubscriber;
-import com.hivemq.client.internal.rx.operators.FlowableWithSingleMap;
-import com.hivemq.client.internal.rx.operators.FlowableWithSingleMapError;
-import com.hivemq.client.internal.rx.operators.FlowableWithSingleObserveOn;
-import com.hivemq.client.internal.util.Checks;
-import com.hivemq.client.rx.reactivestreams.PublisherWithSingle;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import io.reactivex.Flowable;
-import io.reactivex.Scheduler;
-import io.reactivex.annotations.BackpressureKind;
-import io.reactivex.annotations.BackpressureSupport;
-import io.reactivex.annotations.SchedulerSupport;
-import io.reactivex.functions.Action;
-import io.reactivex.functions.Consumer;
-import io.reactivex.functions.Function;
+package com.hivemq.client2.rx;
+
+import com.hivemq.client2.annotations.CheckReturnValue;
+import com.hivemq.client2.internal.rx.WithSingleStrictSubscriber;
+import com.hivemq.client2.internal.rx.operators.FlowableWithSingleMap;
+import com.hivemq.client2.internal.rx.operators.FlowableWithSingleMapError;
+import com.hivemq.client2.internal.rx.operators.FlowableWithSingleObserveOn;
+import com.hivemq.client2.internal.util.Checks;
+import com.hivemq.client2.rx.reactivestreams.PublisherWithSingle;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import io.reactivex.rxjava3.annotations.BackpressureKind;
+import io.reactivex.rxjava3.annotations.BackpressureSupport;
+import io.reactivex.rxjava3.annotations.SchedulerSupport;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.Scheduler;
+import io.reactivex.rxjava3.functions.Action;
+import io.reactivex.rxjava3.functions.Consumer;
+import io.reactivex.rxjava3.functions.Function;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
@@ -62,8 +62,8 @@ public abstract class FlowableWithSingle<F, S> extends Flowable<F> implements Pu
     @CheckReturnValue
     @BackpressureSupport(BackpressureKind.FULL)
     @SchedulerSupport(SchedulerSupport.CUSTOM)
-    public final @NotNull FlowableWithSingle<F, S> observeOnBoth(final @NotNull Scheduler scheduler) {
-        return observeOnBoth(scheduler, false, bufferSize());
+    public final @NotNull FlowableWithSingle<F, S> observeBothOn(final @NotNull Scheduler scheduler) {
+        return observeBothOn(scheduler, false, bufferSize());
     }
 
     /**
@@ -79,10 +79,10 @@ public abstract class FlowableWithSingle<F, S> extends Flowable<F> implements Pu
     @CheckReturnValue
     @BackpressureSupport(BackpressureKind.FULL)
     @SchedulerSupport(SchedulerSupport.CUSTOM)
-    public final @NotNull FlowableWithSingle<F, S> observeOnBoth(
+    public final @NotNull FlowableWithSingle<F, S> observeBothOn(
             final @NotNull Scheduler scheduler, final boolean delayError) {
 
-        return observeOnBoth(scheduler, delayError, bufferSize());
+        return observeBothOn(scheduler, delayError, bufferSize());
     }
 
     /**
@@ -100,7 +100,7 @@ public abstract class FlowableWithSingle<F, S> extends Flowable<F> implements Pu
     @CheckReturnValue
     @BackpressureSupport(BackpressureKind.FULL)
     @SchedulerSupport(SchedulerSupport.CUSTOM)
-    public final @NotNull FlowableWithSingle<F, S> observeOnBoth(
+    public final @NotNull FlowableWithSingle<F, S> observeBothOn(
             final @NotNull Scheduler scheduler, final boolean delayError, final int bufferSize) {
 
         Checks.notNull(scheduler, "Scheduler");
diff --git a/src/main/java/com/hivemq/client/rx/FlowableWithSingleSubscriber.java b/src/main/java/com/hivemq/client2/rx/FlowableWithSingleSubscriber.java
similarity index 88%
rename from src/main/java/com/hivemq/client/rx/FlowableWithSingleSubscriber.java
rename to src/main/java/com/hivemq/client2/rx/FlowableWithSingleSubscriber.java
index 2f54963b6..353ba1dc7 100644
--- a/src/main/java/com/hivemq/client/rx/FlowableWithSingleSubscriber.java
+++ b/src/main/java/com/hivemq/client2/rx/FlowableWithSingleSubscriber.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx;
+package com.hivemq.client2.rx;
 
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import io.reactivex.FlowableSubscriber;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import io.reactivex.rxjava3.core.FlowableSubscriber;
 
 /**
  * Represents a Reactive-Streams inspired {@link WithSingleSubscriber} that is RxJava 2 only and weakens rules for
diff --git a/src/main/java/com/hivemq/client/rx/reactivestreams/PublisherWithSingle.java b/src/main/java/com/hivemq/client2/rx/reactivestreams/PublisherWithSingle.java
similarity index 97%
rename from src/main/java/com/hivemq/client/rx/reactivestreams/PublisherWithSingle.java
rename to src/main/java/com/hivemq/client2/rx/reactivestreams/PublisherWithSingle.java
index d5a6ad36a..57b3eb080 100644
--- a/src/main/java/com/hivemq/client/rx/reactivestreams/PublisherWithSingle.java
+++ b/src/main/java/com/hivemq/client2/rx/reactivestreams/PublisherWithSingle.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx.reactivestreams;
+package com.hivemq.client2.rx.reactivestreams;
 
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Publisher;
diff --git a/src/main/java/com/hivemq/client/rx/reactivestreams/WithSingleSubscriber.java b/src/main/java/com/hivemq/client2/rx/reactivestreams/WithSingleSubscriber.java
similarity index 96%
rename from src/main/java/com/hivemq/client/rx/reactivestreams/WithSingleSubscriber.java
rename to src/main/java/com/hivemq/client2/rx/reactivestreams/WithSingleSubscriber.java
index aa4c57cb0..3562eb766 100644
--- a/src/main/java/com/hivemq/client/rx/reactivestreams/WithSingleSubscriber.java
+++ b/src/main/java/com/hivemq/client2/rx/reactivestreams/WithSingleSubscriber.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx.reactivestreams;
+package com.hivemq.client2.rx.reactivestreams;
 
 import org.jetbrains.annotations.NotNull;
 import org.reactivestreams.Subscriber;
diff --git a/src/main/java/com/hivemq/client/util/KeyStoreUtil.java b/src/main/java/com/hivemq/client2/util/KeyStoreUtil.java
similarity index 97%
rename from src/main/java/com/hivemq/client/util/KeyStoreUtil.java
rename to src/main/java/com/hivemq/client2/util/KeyStoreUtil.java
index 42a9c4685..89c1de836 100644
--- a/src/main/java/com/hivemq/client/util/KeyStoreUtil.java
+++ b/src/main/java/com/hivemq/client2/util/KeyStoreUtil.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.util;
+package com.hivemq.client2.util;
 
-import com.hivemq.client.internal.util.Checks;
+import com.hivemq.client2.internal.util.Checks;
 import org.jetbrains.annotations.NotNull;
 
 import javax.net.ssl.KeyManagerFactory;
diff --git a/src/main/java/com/hivemq/client/util/TypeSwitch.java b/src/main/java/com/hivemq/client2/util/TypeSwitch.java
similarity index 96%
rename from src/main/java/com/hivemq/client/util/TypeSwitch.java
rename to src/main/java/com/hivemq/client2/util/TypeSwitch.java
index c72c60c05..32a6c6090 100644
--- a/src/main/java/com/hivemq/client/util/TypeSwitch.java
+++ b/src/main/java/com/hivemq/client2/util/TypeSwitch.java
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.util;
+package com.hivemq.client2.util;
 
+import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -37,6 +38,7 @@
  * @param <T> the super type to switch over.
  * @author Silvio Giebl
  */
+@ApiStatus.NonExtendable
 public interface TypeSwitch<T> {
 
     /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/MqttCommonReasonCodeTest.java b/src/test/java/com/hivemq/client/internal/mqtt/message/MqttCommonReasonCodeTest.java
deleted file mode 100644
index 28eaf3d5c..000000000
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/MqttCommonReasonCodeTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2018-present HiveMQ and the HiveMQ Community
- *
- * Licensed 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
- *
- *     http://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 com.hivemq.client.internal.mqtt.message;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-/**
- * @author Silvio Giebl
- */
-class MqttCommonReasonCodeTest {
-
-    @Test
-    void test_getCode_success() {
-        assertEquals(0x00, MqttCommonReasonCode.SUCCESS.getCode());
-    }
-
-    @Test
-    void test_getCode_noMatchingSubscribers() {
-        assertEquals(0x10, MqttCommonReasonCode.NO_MATCHING_SUBSCRIBERS.getCode());
-    }
-
-    @Test
-    void test_getCode_unspecifiedError() {
-        assertEquals(0x80, MqttCommonReasonCode.UNSPECIFIED_ERROR.getCode());
-    }
-
-    @Test
-    void test_getCode_malformedPacket() {
-        assertEquals(0x81, MqttCommonReasonCode.MALFORMED_PACKET.getCode());
-    }
-
-    @Test
-    void test_getCode_protocolError() {
-        assertEquals(0x82, MqttCommonReasonCode.PROTOCOL_ERROR.getCode());
-    }
-
-    @Test
-    void test_getCode_implementationSpecificError() {
-        assertEquals(0x83, MqttCommonReasonCode.IMPLEMENTATION_SPECIFIC_ERROR.getCode());
-    }
-
-    @Test
-    void test_getCode_notAuthorized() {
-        assertEquals(0x87, MqttCommonReasonCode.NOT_AUTHORIZED.getCode());
-    }
-
-    @Test
-    void test_getCode_SererBusy() {
-        assertEquals(0x89, MqttCommonReasonCode.SERVER_BUSY.getCode());
-    }
-
-    @Test
-    void test_getCode_badAuthenticationMethod() {
-        assertEquals(0x8C, MqttCommonReasonCode.BAD_AUTHENTICATION_METHOD.getCode());
-    }
-
-    @Test
-    void test_getCode_topicFilterInvalid() {
-        assertEquals(0x8F, MqttCommonReasonCode.TOPIC_FILTER_INVALID.getCode());
-    }
-
-    @Test
-    void test_getCode_TopicNameInvalid() {
-        assertEquals(0x90, MqttCommonReasonCode.TOPIC_NAME_INVALID.getCode());
-    }
-
-    @Test
-    void test_getCode_packetIdentifierInUse() {
-        assertEquals(0x91, MqttCommonReasonCode.PACKET_IDENTIFIER_IN_USE.getCode());
-    }
-
-    @Test
-    void test_getCode_packetIdentifierNotFound() {
-        assertEquals(0x92, MqttCommonReasonCode.PACKET_IDENTIFIER_NOT_FOUND.getCode());
-    }
-
-    @Test
-    void test_getCode_packetTooLarge() {
-        assertEquals(0x95, MqttCommonReasonCode.PACKET_TOO_LARGE.getCode());
-    }
-
-    @Test
-    void test_getCode_quotaExceeded() {
-        assertEquals(0x97, MqttCommonReasonCode.QUOTA_EXCEEDED.getCode());
-    }
-
-    @Test
-    void test_getCode_payloadFormatInvalid() {
-        assertEquals(0x99, MqttCommonReasonCode.PAYLOAD_FORMAT_INVALID.getCode());
-    }
-
-    @Test
-    void test_getCode_retainNotSupported() {
-        assertEquals(0x9A, MqttCommonReasonCode.RETAIN_NOT_SUPPORTED.getCode());
-    }
-
-    @Test
-    void test_getCode_qosNotSupported() {
-        assertEquals(0x9B, MqttCommonReasonCode.QOS_NOT_SUPPORTED.getCode());
-    }
-
-    @Test
-    void test_getCode_useAnotherServer() {
-        assertEquals(0x9C, MqttCommonReasonCode.USE_ANOTHER_SERVER.getCode());
-    }
-
-    @Test
-    void test_getCode_serverMoved() {
-        assertEquals(0x9D, MqttCommonReasonCode.SERVER_MOVED.getCode());
-    }
-
-    @Test
-    void test_getCode_sharedSubscriptionNotSupported() {
-        assertEquals(0x9E, MqttCommonReasonCode.SHARED_SUBSCRIPTIONS_NOT_SUPPORTED.getCode());
-    }
-
-    @Test
-    void test_getCode_connectionRateExceeded() {
-        assertEquals(0x9F, MqttCommonReasonCode.CONNECTION_RATE_EXCEEDED.getCode());
-    }
-
-    @Test
-    void test_getCode_subscriptionIdentifiersNotSupported() {
-        assertEquals(0xA1, MqttCommonReasonCode.SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED.getCode());
-    }
-
-    @Test
-    void test_getCode_wildcardSubscriptionNotSupported() {
-        assertEquals(0xA2, MqttCommonReasonCode.WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED.getCode());
-    }
-
-}
diff --git a/src/test/java/com/hivemq/client/internal/rx/RxFutureConverterTest.java b/src/test/java/com/hivemq/client/internal/rx/RxFutureConverterTest.java
deleted file mode 100644
index 7c9b0df71..000000000
--- a/src/test/java/com/hivemq/client/internal/rx/RxFutureConverterTest.java
+++ /dev/null
@@ -1,905 +0,0 @@
-/*
- * Copyright 2018-present HiveMQ and the HiveMQ Community
- *
- * Licensed 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
- *
- *     http://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 com.hivemq.client.internal.rx;
-
-import io.reactivex.*;
-import io.reactivex.disposables.Disposable;
-import io.reactivex.schedulers.Schedulers;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.junit.jupiter.api.Test;
-
-import java.util.Optional;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * @author Silvio Giebl
- */
-class RxFutureConverterTest {
-
-    @Test
-    void toFuture_completable_immediate() {
-        final CompletableFuture<Void> future = RxFutureConverter.toFuture(Completable.complete());
-        assertTrue(future.isDone());
-    }
-
-    @Test
-    void toFuture_completable_immediate_error() {
-        final CompletableFuture<Void> future = RxFutureConverter.toFuture(Completable.error(new Exception("test")));
-        assertTrue(future.isDone());
-        assertTrue(future.isCompletedExceptionally());
-        final ExecutionException exception = assertThrows(ExecutionException.class, future::get);
-        assertEquals("test", exception.getCause().getMessage());
-    }
-
-    @Test
-    void toFuture_completable() throws InterruptedException {
-        final CountDownLatch emitLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Completable completable = Completable.create(emitter -> {
-            emitLatch.await(1, TimeUnit.SECONDS);
-            emitter.onComplete();
-            completedLatch.countDown();
-        }).subscribeOn(Schedulers.single());
-
-        final CompletableFuture<Void> future = RxFutureConverter.toFuture(completable);
-        assertFalse(future.isDone());
-
-        emitLatch.countDown();
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-    }
-
-    @Test
-    void toFuture_completable_error() throws InterruptedException {
-        final CountDownLatch emitLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Completable completable = Completable.create(emitter -> {
-            emitLatch.await(1, TimeUnit.SECONDS);
-            emitter.onError(new Exception("test"));
-            completedLatch.countDown();
-        }).subscribeOn(Schedulers.single());
-
-        final CompletableFuture<Void> future = RxFutureConverter.toFuture(completable);
-        assertFalse(future.isDone());
-
-        emitLatch.countDown();
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        assertTrue(future.isCompletedExceptionally());
-        final ExecutionException exception = assertThrows(ExecutionException.class, future::get);
-        assertEquals("test", exception.getCause().getMessage());
-    }
-
-    @Test
-    void toFuture_completable_cancel() throws InterruptedException {
-        final CountDownLatch subscribeLatch = new CountDownLatch(1);
-        final CountDownLatch emitLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Completable completable = Completable.create(emitter -> {
-            subscribeLatch.countDown();
-            try {
-                emitLatch.await(1, TimeUnit.SECONDS);
-            } catch (InterruptedException e) {
-                // ignore
-            }
-            if (emitter.isDisposed()) {
-                completedLatch.countDown();
-            }
-        }).subscribeOn(Schedulers.single());
-
-        final CompletableFuture<Void> future = RxFutureConverter.toFuture(completable);
-        assertFalse(future.isDone());
-
-        assertTrue(subscribeLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.cancel(false));
-
-        emitLatch.countDown();
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        assertThrows(CancellationException.class, future::get);
-    }
-
-    @Test
-    void toFuture_completable_cancel_before_onSubscribe() throws InterruptedException {
-        final CountDownLatch subscribeLatch = new CountDownLatch(1);
-        final CountDownLatch cancelLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Completable completable = new Completable() {
-            @Override
-            protected void subscribeActual(final @NotNull CompletableObserver observer) {
-                subscribeLatch.countDown();
-                final Thread thread = new Thread(() -> {
-                    try {
-                        assertTrue(cancelLatch.await(1, TimeUnit.SECONDS));
-                    } catch (final InterruptedException e) {
-                        fail(e);
-                    }
-                    final Disposable disposable = new TestDisposable();
-                    observer.onSubscribe(disposable);
-                    assertTrue(disposable.isDisposed());
-                    completedLatch.countDown();
-                });
-                thread.setUncaughtExceptionHandler((t, e) -> e.printStackTrace());
-                thread.start();
-            }
-        };
-
-        final CompletableFuture<Void> future = RxFutureConverter.toFuture(completable);
-        assertFalse(future.isDone());
-
-        assertTrue(subscribeLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.cancel(false));
-        cancelLatch.countDown();
-
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        assertThrows(CancellationException.class, future::get);
-    }
-
-    @Test
-    void toFuture_maybe_immediate() throws ExecutionException, InterruptedException {
-        final CompletableFuture<Optional<String>> future = RxFutureConverter.toFuture(Maybe.just("maybe"));
-        assertTrue(future.isDone());
-        final Optional<String> optional = future.get();
-        assertNotNull(optional);
-        assertTrue(optional.isPresent());
-        assertEquals("maybe", optional.get());
-    }
-
-    @Test
-    void toFuture_maybe_immediate_empty() throws ExecutionException, InterruptedException {
-        final CompletableFuture<Optional<String>> future = RxFutureConverter.toFuture(Maybe.empty());
-        assertTrue(future.isDone());
-        final Optional<String> optional = future.get();
-        assertNotNull(optional);
-        assertFalse(optional.isPresent());
-    }
-
-    @Test
-    void toFuture_maybe_immediate_error() {
-        final CompletableFuture<Optional<String>> future =
-                RxFutureConverter.toFuture(Maybe.error(new Exception("test")));
-        assertTrue(future.isDone());
-        assertTrue(future.isCompletedExceptionally());
-        final ExecutionException exception = assertThrows(ExecutionException.class, future::get);
-        assertEquals("test", exception.getCause().getMessage());
-    }
-
-    @Test
-    void toFuture_maybe() throws InterruptedException, ExecutionException {
-        final CountDownLatch emitLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Maybe<String> maybe = Maybe.<String>create(emitter -> {
-            emitLatch.await(1, TimeUnit.SECONDS);
-            emitter.onSuccess("maybe");
-            completedLatch.countDown();
-        }).subscribeOn(Schedulers.single());
-
-        final CompletableFuture<Optional<String>> future = RxFutureConverter.toFuture(maybe);
-        assertFalse(future.isDone());
-
-        emitLatch.countDown();
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        final Optional<String> optional = future.get();
-        assertNotNull(optional);
-        assertTrue(optional.isPresent());
-        assertEquals("maybe", optional.get());
-    }
-
-    @Test
-    void toFuture_maybe_empty() throws InterruptedException, ExecutionException {
-        final CountDownLatch emitLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Maybe<String> maybe = Maybe.<String>create(emitter -> {
-            emitLatch.await(1, TimeUnit.SECONDS);
-            emitter.onComplete();
-            completedLatch.countDown();
-        }).subscribeOn(Schedulers.single());
-
-        final CompletableFuture<Optional<String>> future = RxFutureConverter.toFuture(maybe);
-        assertFalse(future.isDone());
-
-        emitLatch.countDown();
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        final Optional<String> optional = future.get();
-        assertNotNull(optional);
-        assertFalse(optional.isPresent());
-    }
-
-    @Test
-    void toFuture_maybe_cancel() throws InterruptedException {
-        final CountDownLatch subscribeLatch = new CountDownLatch(1);
-        final CountDownLatch emitLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Maybe<String> completable = Maybe.<String>create(emitter -> {
-            subscribeLatch.countDown();
-            try {
-                emitLatch.await(1, TimeUnit.SECONDS);
-            } catch (InterruptedException e) {
-                // ignore
-            }
-            if (emitter.isDisposed()) {
-                completedLatch.countDown();
-            }
-        }).subscribeOn(Schedulers.single());
-
-        final CompletableFuture<Optional<String>> future = RxFutureConverter.toFuture(completable);
-        assertFalse(future.isDone());
-
-        assertTrue(subscribeLatch.await(1, TimeUnit.SECONDS));
-        future.cancel(false);
-
-        emitLatch.countDown();
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        assertThrows(CancellationException.class, future::get);
-    }
-
-    @Test
-    void toFuture_maybe_cancel_before_onSubscribe() throws InterruptedException {
-        final CountDownLatch subscribeLatch = new CountDownLatch(1);
-        final CountDownLatch cancelLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Maybe<String> maybe = new Maybe<String>() {
-            @Override
-            protected void subscribeActual(final @NotNull MaybeObserver<? super String> observer) {
-                subscribeLatch.countDown();
-                final Thread thread = new Thread(() -> {
-                    try {
-                        assertTrue(cancelLatch.await(1, TimeUnit.SECONDS));
-                    } catch (final InterruptedException e) {
-                        fail(e);
-                    }
-                    final Disposable disposable = new TestDisposable();
-                    observer.onSubscribe(disposable);
-                    assertTrue(disposable.isDisposed());
-                    completedLatch.countDown();
-                });
-                thread.setUncaughtExceptionHandler((t, e) -> e.printStackTrace());
-                thread.start();
-            }
-        };
-
-        final CompletableFuture<Optional<String>> future = RxFutureConverter.toFuture(maybe);
-        assertFalse(future.isDone());
-
-        assertTrue(subscribeLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.cancel(false));
-        cancelLatch.countDown();
-
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        assertThrows(CancellationException.class, future::get);
-    }
-
-    @Test
-    void toFuture_maybe_error() throws InterruptedException {
-        final CountDownLatch emitLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Maybe<String> maybe = Maybe.<String>create(emitter -> {
-            emitLatch.await(1, TimeUnit.SECONDS);
-            emitter.onError(new Exception("test"));
-            completedLatch.countDown();
-        }).subscribeOn(Schedulers.single());
-
-        final CompletableFuture<Optional<String>> future = RxFutureConverter.toFuture(maybe);
-        assertFalse(future.isDone());
-
-        emitLatch.countDown();
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        assertTrue(future.isCompletedExceptionally());
-        final ExecutionException exception = assertThrows(ExecutionException.class, future::get);
-        assertEquals("test", exception.getCause().getMessage());
-    }
-
-    @Test
-    void toFuture_single_immediate() throws ExecutionException, InterruptedException {
-        final CompletableFuture<String> future = RxFutureConverter.toFuture(Single.just("single"));
-        assertTrue(future.isDone());
-        assertEquals("single", future.get());
-    }
-
-    @Test
-    void toFuture_single_immediate_error() {
-        final CompletableFuture<String> future = RxFutureConverter.toFuture(Single.error(new Exception("test")));
-        assertTrue(future.isDone());
-        assertTrue(future.isCompletedExceptionally());
-        final ExecutionException exception = assertThrows(ExecutionException.class, future::get);
-        assertEquals("test", exception.getCause().getMessage());
-    }
-
-    @Test
-    void toFuture_single() throws InterruptedException, ExecutionException {
-        final CountDownLatch emitLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Single<String> single = Single.<String>create(emitter -> {
-            emitLatch.await(1, TimeUnit.SECONDS);
-            emitter.onSuccess("single");
-            completedLatch.countDown();
-        }).subscribeOn(Schedulers.single());
-
-        final CompletableFuture<String> future = RxFutureConverter.toFuture(single);
-        assertFalse(future.isDone());
-
-        emitLatch.countDown();
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        assertEquals("single", future.get());
-    }
-
-    @Test
-    void toFuture_single_error() throws InterruptedException {
-        final CountDownLatch emitLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Single<String> single = Single.<String>create(emitter -> {
-            emitLatch.await(1, TimeUnit.SECONDS);
-            emitter.onError(new Exception("test"));
-            completedLatch.countDown();
-        }).subscribeOn(Schedulers.single());
-
-        final CompletableFuture<String> future = RxFutureConverter.toFuture(single);
-        assertFalse(future.isDone());
-
-        emitLatch.countDown();
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        assertTrue(future.isCompletedExceptionally());
-        final ExecutionException exception = assertThrows(ExecutionException.class, future::get);
-        assertEquals("test", exception.getCause().getMessage());
-    }
-
-    @Test
-    void toFuture_single_cancel() throws InterruptedException {
-        final CountDownLatch subscribeLatch = new CountDownLatch(1);
-        final CountDownLatch emitLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Single<String> completable = Single.<String>create(emitter -> {
-            subscribeLatch.countDown();
-            try {
-                emitLatch.await(1, TimeUnit.SECONDS);
-            } catch (InterruptedException e) {
-                // ignore
-            }
-            if (emitter.isDisposed()) {
-                completedLatch.countDown();
-            }
-        }).subscribeOn(Schedulers.single());
-
-        final CompletableFuture<String> future = RxFutureConverter.toFuture(completable);
-        assertFalse(future.isDone());
-
-        assertTrue(subscribeLatch.await(1, TimeUnit.SECONDS));
-        future.cancel(false);
-
-        emitLatch.countDown();
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        assertThrows(CancellationException.class, future::get);
-    }
-
-    @Test
-    void toFuture_single_cancel_before_onSubscribe() throws InterruptedException {
-        final CountDownLatch subscribeLatch = new CountDownLatch(1);
-        final CountDownLatch cancelLatch = new CountDownLatch(1);
-        final CountDownLatch completedLatch = new CountDownLatch(1);
-        final Single<String> single = new Single<String>() {
-            @Override
-            protected void subscribeActual(final @NotNull SingleObserver<? super String> observer) {
-                subscribeLatch.countDown();
-                final Thread thread = new Thread(() -> {
-                    try {
-                        assertTrue(cancelLatch.await(1, TimeUnit.SECONDS));
-                    } catch (final InterruptedException e) {
-                        fail(e);
-                    }
-                    final Disposable disposable = new TestDisposable();
-                    observer.onSubscribe(disposable);
-                    assertTrue(disposable.isDisposed());
-                    completedLatch.countDown();
-                });
-                thread.setUncaughtExceptionHandler((t, e) -> e.printStackTrace());
-                thread.start();
-            }
-        };
-
-        final CompletableFuture<String> future = RxFutureConverter.toFuture(single);
-        assertFalse(future.isDone());
-
-        assertTrue(subscribeLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.cancel(false));
-        cancelLatch.countDown();
-
-        assertTrue(completedLatch.await(1, TimeUnit.SECONDS));
-        assertTrue(future.isDone());
-        assertThrows(CancellationException.class, future::get);
-    }
-
-    @Test
-    void toCompletable_immediate() {
-        final Completable completable = RxFutureConverter.toCompletable(CompletableFuture.completedFuture("test"));
-
-        final AtomicInteger counter = new AtomicInteger();
-        completable.subscribe(new TestCompletableObserver() {
-            @Override
-            public void onComplete() {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                counter.incrementAndGet();
-            }
-        });
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toCompletable_immediate_error() {
-        final CompletableFuture<String> future = new CompletableFuture<>();
-        future.completeExceptionally(new Exception("test"));
-        final Completable completable = RxFutureConverter.toCompletable(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        completable.subscribe(new TestCompletableObserver() {
-            @Override
-            public void onError(final @NotNull Throwable e) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertEquals("test", e.getMessage());
-                counter.incrementAndGet();
-            }
-        });
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toCompletable() {
-        final CompletableFuture<String> future = new CompletableFuture<>();
-        final Completable completable = RxFutureConverter.toCompletable(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestCompletableObserver observer = new TestCompletableObserver() {
-            @Override
-            public void onComplete() {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                counter.incrementAndGet();
-            }
-        };
-        completable.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        future.complete("test");
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toCompletable_error() {
-        final CompletableFuture<String> future = new CompletableFuture<>();
-        final Completable completable = RxFutureConverter.toCompletable(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestCompletableObserver observer = new TestCompletableObserver() {
-            @Override
-            public void onError(final @NotNull Throwable e) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertEquals("test", e.getMessage());
-                counter.incrementAndGet();
-            }
-        };
-        completable.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        future.completeExceptionally(new Exception("test"));
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toCompletable_dispose() {
-        final CompletableFuture<String> future = new CompletableFuture<>();
-        final Completable completable = RxFutureConverter.toCompletable(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestCompletableObserver observer = new TestCompletableObserver() {
-            @Override
-            public void onComplete() {
-                counter.incrementAndGet();
-            }
-        };
-        completable.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        observer.disposable.dispose();
-        assertTrue(observer.disposable.isDisposed());
-        assertTrue(future.isCancelled());
-        future.complete("test");
-        assertEquals(0, counter.get());
-    }
-
-    @Test
-    void toMaybe_immediate() {
-        final Maybe<String> maybe = RxFutureConverter.toMaybe(CompletableFuture.completedFuture(Optional.of("test")));
-
-        final AtomicInteger counter = new AtomicInteger();
-        maybe.subscribe(new TestMaybeObserver<String>() {
-            @Override
-            public void onSuccess(final @NotNull String s) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertEquals("test", s);
-                counter.incrementAndGet();
-            }
-        });
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toMaybe_immediate_empty() {
-        final Maybe<String> maybe = RxFutureConverter.toMaybe(CompletableFuture.completedFuture(Optional.empty()));
-
-        final AtomicInteger counter = new AtomicInteger();
-        maybe.subscribe(new TestMaybeObserver<String>() {
-            @Override
-            public void onComplete() {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                counter.incrementAndGet();
-            }
-        });
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toMaybe_immediate_null() {
-        final Maybe<String> maybe = RxFutureConverter.toMaybe(CompletableFuture.completedFuture(null));
-
-        final AtomicInteger counter = new AtomicInteger();
-        maybe.subscribe(new TestMaybeObserver<String>() {
-            @Override
-            public void onError(final @NotNull Throwable e) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertTrue(e instanceof NullPointerException);
-                counter.incrementAndGet();
-            }
-        });
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toMaybe_immediate_error() {
-        final CompletableFuture<Optional<String>> future = new CompletableFuture<>();
-        future.completeExceptionally(new Exception("test"));
-        final Maybe<String> maybe = RxFutureConverter.toMaybe(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        maybe.subscribe(new TestMaybeObserver<String>() {
-            @Override
-            public void onError(final @NotNull Throwable e) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertEquals("test", e.getMessage());
-                counter.incrementAndGet();
-            }
-        });
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toMaybe() {
-        final CompletableFuture<Optional<String>> future = new CompletableFuture<>();
-        final Maybe<String> maybe = RxFutureConverter.toMaybe(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestMaybeObserver<String> observer = new TestMaybeObserver<String>() {
-            @Override
-            public void onSuccess(final @NotNull String s) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertEquals("test", s);
-                counter.incrementAndGet();
-            }
-        };
-        maybe.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        future.complete(Optional.of("test"));
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toMaybe_empty() {
-        final CompletableFuture<Optional<String>> future = new CompletableFuture<>();
-        final Maybe<String> maybe = RxFutureConverter.toMaybe(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestMaybeObserver<String> observer = new TestMaybeObserver<String>() {
-            @Override
-            public void onComplete() {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                counter.incrementAndGet();
-            }
-        };
-        maybe.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        future.complete(Optional.empty());
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toMaybe_null() {
-        final CompletableFuture<Optional<String>> future = new CompletableFuture<>();
-        final Maybe<String> maybe = RxFutureConverter.toMaybe(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestMaybeObserver<String> observer = new TestMaybeObserver<String>() {
-            @Override
-            public void onError(final @NotNull Throwable e) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertTrue(e instanceof NullPointerException);
-                counter.incrementAndGet();
-            }
-        };
-        maybe.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        future.complete(null);
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toMaybe_error() {
-        final CompletableFuture<Optional<String>> future = new CompletableFuture<>();
-        final Maybe<String> maybe = RxFutureConverter.toMaybe(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestMaybeObserver<String> observer = new TestMaybeObserver<String>() {
-            @Override
-            public void onError(final @NotNull Throwable e) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertEquals("test", e.getMessage());
-                counter.incrementAndGet();
-            }
-        };
-        maybe.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        future.completeExceptionally(new Exception("test"));
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toMaybe_dispose() {
-        final CompletableFuture<Optional<String>> future = new CompletableFuture<>();
-        final Maybe<String> completable = RxFutureConverter.toMaybe(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestMaybeObserver<String> observer = new TestMaybeObserver<String>() {
-            @Override
-            public void onSuccess(final @NotNull String s) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                counter.incrementAndGet();
-            }
-        };
-        completable.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        observer.disposable.dispose();
-        assertTrue(future.isCancelled());
-        future.complete(Optional.of("test"));
-        assertEquals(0, counter.get());
-    }
-
-    @Test
-    void toSingle_immediate() {
-        final Single<String> single = RxFutureConverter.toSingle(CompletableFuture.completedFuture("test"));
-
-        final AtomicInteger counter = new AtomicInteger();
-        single.subscribe(new TestSingleObserver<String>() {
-            @Override
-            public void onSuccess(final @NotNull String s) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertEquals("test", s);
-                counter.incrementAndGet();
-            }
-        });
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toSingle_immediate_error() {
-        final CompletableFuture<String> future = new CompletableFuture<>();
-        future.completeExceptionally(new Exception("test"));
-        final Single<String> single = RxFutureConverter.toSingle(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        single.subscribe(new TestSingleObserver<String>() {
-            @Override
-            public void onError(final @NotNull Throwable e) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertEquals("test", e.getMessage());
-                counter.incrementAndGet();
-            }
-        });
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toSingle() {
-        final CompletableFuture<String> future = new CompletableFuture<>();
-        final Single<String> single = RxFutureConverter.toSingle(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestSingleObserver<String> observer = new TestSingleObserver<String>() {
-            @Override
-            public void onSuccess(final @NotNull String s) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertEquals("test", s);
-                counter.incrementAndGet();
-            }
-        };
-        single.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        future.complete("test");
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toSingle_error() {
-        final CompletableFuture<String> future = new CompletableFuture<>();
-        final Single<String> single = RxFutureConverter.toSingle(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestSingleObserver<String> observer = new TestSingleObserver<String>() {
-            @Override
-            public void onError(final @NotNull Throwable e) {
-                assertNotNull(disposable);
-                assertTrue(disposable.isDisposed());
-                assertEquals("test", e.getMessage());
-                counter.incrementAndGet();
-            }
-        };
-        single.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        future.completeExceptionally(new Exception("test"));
-        assertEquals(1, counter.get());
-    }
-
-    @Test
-    void toSingle_dispose() {
-        final CompletableFuture<String> future = new CompletableFuture<>();
-        final Single<String> single = RxFutureConverter.toSingle(future);
-
-        final AtomicInteger counter = new AtomicInteger();
-        final TestSingleObserver<String> observer = new TestSingleObserver<String>() {
-            @Override
-            public void onSuccess(final @NotNull String s) {
-                counter.incrementAndGet();
-            }
-        };
-        single.subscribe(observer);
-        assertNotNull(observer.disposable);
-        assertFalse(observer.disposable.isDisposed());
-        assertEquals(0, counter.get());
-
-        observer.disposable.dispose();
-        assertTrue(future.isCancelled());
-        future.complete("test");
-        assertEquals(0, counter.get());
-    }
-
-    private static class TestDisposable implements Disposable {
-
-        private volatile boolean disposed;
-
-        @Override
-        public void dispose() {
-            disposed = true;
-        }
-
-        @Override
-        public boolean isDisposed() {
-            return disposed;
-        }
-    }
-
-    private static abstract class TestCompletableObserver implements CompletableObserver {
-
-        @Nullable Disposable disposable;
-
-        @Override
-        public void onSubscribe(final @NotNull Disposable d) {
-            disposable = d;
-        }
-
-        @Override
-        public void onComplete() {}
-
-        @Override
-        public void onError(final @NotNull Throwable e) {}
-    }
-
-    private static abstract class TestMaybeObserver<T> implements MaybeObserver<T> {
-
-        @Nullable Disposable disposable;
-
-        @Override
-        public void onSubscribe(final @NotNull Disposable d) {
-            disposable = d;
-        }
-
-        @Override
-        public void onSuccess(final @NotNull T t) {}
-
-        @Override
-        public void onComplete() {}
-
-        @Override
-        public void onError(final @NotNull Throwable e) {}
-    }
-
-    private static abstract class TestSingleObserver<T> implements SingleObserver<T> {
-
-        @Nullable Disposable disposable;
-
-        @Override
-        public void onSubscribe(final @NotNull Disposable d) {
-            disposable = d;
-        }
-
-        @Override
-        public void onSuccess(final @NotNull T t) {}
-
-        @Override
-        public void onError(final @NotNull Throwable e) {}
-    }
-}
\ No newline at end of file
diff --git a/src/test/java/com/hivemq/client/example/Mqtt3ClientExample.java b/src/test/java/com/hivemq/client2/example/Mqtt3ClientExample.java
similarity index 76%
rename from src/test/java/com/hivemq/client/example/Mqtt3ClientExample.java
rename to src/test/java/com/hivemq/client2/example/Mqtt3ClientExample.java
index 1517ab22d..0c466c28f 100644
--- a/src/test/java/com/hivemq/client/example/Mqtt3ClientExample.java
+++ b/src/test/java/com/hivemq/client2/example/Mqtt3ClientExample.java
@@ -14,24 +14,24 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.example;
-
-import com.hivemq.client.mqtt.MqttClient;
-import com.hivemq.client.mqtt.MqttClientBuilder;
-import com.hivemq.client.mqtt.MqttClientSslConfig;
-import com.hivemq.client.mqtt.MqttWebSocketConfig;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt3.Mqtt3RxClient;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
-import io.reactivex.Completable;
-import io.reactivex.Flowable;
-import io.reactivex.Single;
+package com.hivemq.client2.example;
+
+import com.hivemq.client2.mqtt.MqttClient;
+import com.hivemq.client2.mqtt.MqttClientBuilder;
+import com.hivemq.client2.mqtt.MqttTlsConfig;
+import com.hivemq.client2.mqtt.MqttWebSocketConfig;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt3.Mqtt3RxClient;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.Single;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -88,23 +88,25 @@ Completable subscribeTo(
 
         // create a SUBSCRIBE message for the topic with QoS
         final Mqtt3Subscribe subscribeMessage = Mqtt3Subscribe.builder()
-                .addSubscription(Mqtt3Subscription.builder().topicFilter(topic).qos(qos).build())
+                .addSubscription(Mqtt3Subscription.builder().topicFilter(topic).maxQos(qos).build())
                 .build();
         // define what to do with the publishes that match the subscription. This does not subscribe until rxJava's subscribe is called
         // NOTE: you can also subscribe without the stream, and then handle the incoming publishes on client.allPublishes()
-        final Flowable<Mqtt3Publish> subscribeScenario = client.subscribeStream(subscribeMessage).doOnSingle(subAck -> {
-            subscribedLatch.countDown();
-            System.out.println("subscribed to " + topic + ": return codes: " + subAck.getReturnCodes());
-        }).doOnNext(publish -> {
-            if (publish.getPayload().isPresent()) {
-                final int receivedCount = this.receivedCount.incrementAndGet();
-                final String message = new String(publish.getPayloadAsBytes());
-                System.out.println("received message with payload '" + message + "' on topic '" + publish.getTopic() +
-                        "' received count: " + receivedCount);
-            } else {
-                System.out.println("received message without payload on topic '" + publish.getTopic() + "'");
-            }
-        });
+        final Flowable<Mqtt3Publish> subscribeScenario =
+                client.subscribePublishes(subscribeMessage).doOnSingle(subAck -> {
+                    subscribedLatch.countDown();
+                    System.out.println("subscribed to " + topic + ": return codes: " + subAck.getReturnCodes());
+                }).doOnNext(publish -> {
+                    if (publish.getPayload().isPresent()) {
+                        final int receivedCount = this.receivedCount.incrementAndGet();
+                        final String message = new String(publish.getPayloadAsBytes());
+                        System.out.println(
+                                "received message with payload '" + message + "' on topic '" + publish.getTopic() +
+                                        "' received count: " + receivedCount);
+                    } else {
+                        System.out.println("received message without payload on topic '" + publish.getTopic() + "'");
+                    }
+                });
 
         // define what to do when we disconnect, this does not disconnect yet
         final Completable disconnectScenario =
@@ -166,14 +168,14 @@ private Mqtt3RxClient getClient() {
                 MqttClient.builder().identifier(UUID.randomUUID().toString()).serverHost(server).serverPort(port);
 
         if (usesSsl) {
-            mqttClientBuilder.sslConfig(MqttClientSslConfig.builder()
+            mqttClientBuilder.tlsConfig(MqttTlsConfig.builder()
                     .keyManagerFactory(keyManagerFactory)
                     .trustManagerFactory(trustManagerFactory)
                     .build());
         }
 
         if (isNotUsingMqttPort(port)) {
-            mqttClientBuilder.webSocketConfig(MqttWebSocketConfig.builder().serverPath(serverPath).build());
+            mqttClientBuilder.webSocketConfig(MqttWebSocketConfig.builder().path(serverPath).build());
         }
 
         return mqttClientBuilder.useMqttVersion3().buildRx();
diff --git a/src/test/java/com/hivemq/client/example/Mqtt3SmokeTest.java b/src/test/java/com/hivemq/client2/example/Mqtt3SmokeTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/example/Mqtt3SmokeTest.java
rename to src/test/java/com/hivemq/client2/example/Mqtt3SmokeTest.java
index 33a2fc117..3f0b30a06 100644
--- a/src/test/java/com/hivemq/client/example/Mqtt3SmokeTest.java
+++ b/src/test/java/com/hivemq/client2/example/Mqtt3SmokeTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.example;
+package com.hivemq.client2.example;
 
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.util.KeyStoreUtil;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.util.KeyStoreUtil;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/MqttClientExecutorConfigImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/MqttExecutorConfigImplTest.java
similarity index 88%
rename from src/test/java/com/hivemq/client/internal/mqtt/MqttClientExecutorConfigImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/MqttExecutorConfigImplTest.java
index 8e271969b..e8354aa76 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/MqttClientExecutorConfigImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/MqttExecutorConfigImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -24,11 +24,11 @@
 /**
  * @author Silvio Giebl
  */
-class MqttClientExecutorConfigImplTest {
+class MqttExecutorConfigImplTest {
 
     @Test
     void equals() {
-        EqualsVerifier.forClass(MqttClientExecutorConfigImpl.class)
+        EqualsVerifier.forClass(MqttExecutorConfigImpl.class)
                 .withIgnoredAnnotations(NotNull.class) // EqualsVerifier thinks @NotNull Optional is @NotNull
                 .withNonnullFields("applicationScheduler")
                 .suppress(Warning.STRICT_INHERITANCE)
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/MqttProxyConfigImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/MqttProxyConfigImplTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/internal/mqtt/MqttProxyConfigImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/MqttProxyConfigImplTest.java
index a3aa06208..72107c659 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/MqttProxyConfigImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/MqttProxyConfigImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/MqttClientSslConfigImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/MqttTlsConfigImplTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/internal/mqtt/MqttClientSslConfigImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/MqttTlsConfigImplTest.java
index dba92a6da..edb0ba620 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/MqttClientSslConfigImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/MqttTlsConfigImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -28,7 +28,7 @@
 /**
  * @author Silvio Giebl
  */
-class MqttClientSslConfigImplTest {
+class MqttTlsConfigImplTest {
 
     @Test
     void equals() throws NoSuchAlgorithmException {
@@ -37,7 +37,7 @@ void equals() throws NoSuchAlgorithmException {
         final TrustManagerFactory tmf1 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
         final TrustManagerFactory tmf2 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
 
-        EqualsVerifier.forClass(MqttClientSslConfigImpl.class)
+        EqualsVerifier.forClass(MqttTlsConfigImpl.class)
                 .withIgnoredAnnotations(NotNull.class) // EqualsVerifier thinks @NotNull Optional is @NotNull
                 .withPrefabValues(KeyManagerFactory.class, kmf1, kmf2)
                 .withPrefabValues(TrustManagerFactory.class, tmf1, tmf2)
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/MqttClientTransportConfigImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/MqttTransportConfigImplTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/internal/mqtt/MqttClientTransportConfigImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/MqttTransportConfigImplTest.java
index faeffea69..47e3666b3 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/MqttClientTransportConfigImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/MqttTransportConfigImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -28,7 +28,7 @@
 /**
  * @author Silvio Giebl
  */
-class MqttClientTransportConfigImplTest {
+class MqttTransportConfigImplTest {
 
     @Test
     void equals() throws NoSuchAlgorithmException {
@@ -37,7 +37,7 @@ void equals() throws NoSuchAlgorithmException {
         final TrustManagerFactory tmf1 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
         final TrustManagerFactory tmf2 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
 
-        EqualsVerifier.forClass(MqttClientTransportConfigImpl.class)
+        EqualsVerifier.forClass(MqttTransportConfigImpl.class)
                 .suppress(Warning.STRICT_INHERITANCE)
                 .withIgnoredAnnotations(NotNull.class) // EqualsVerifier thinks @NotNull Optional is @NotNull
                 .withNonnullFields("serverAddress")
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/MqttWebSocketConfigImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/MqttWebSocketConfigImplTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/MqttWebSocketConfigImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/MqttWebSocketConfigImplTest.java
index eb02a54f9..ac3223726 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/MqttWebSocketConfigImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/MqttWebSocketConfigImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt;
+package com.hivemq.client2.internal.mqtt;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/advanced/MqttClientAdvancedConfigTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/advanced/MqttAdvancedConfigTest.java
similarity index 80%
rename from src/test/java/com/hivemq/client/internal/mqtt/advanced/MqttClientAdvancedConfigTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/advanced/MqttAdvancedConfigTest.java
index 0765f940c..e2c2a9718 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/advanced/MqttClientAdvancedConfigTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/advanced/MqttAdvancedConfigTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.advanced;
+package com.hivemq.client2.internal.mqtt.advanced;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -23,10 +23,10 @@
 /**
  * @author Silvio Giebl
  */
-class MqttClientAdvancedConfigTest {
+class MqttAdvancedConfigTest {
 
     @Test
     void equals() {
-        EqualsVerifier.forClass(MqttClientAdvancedConfig.class).suppress(Warning.STRICT_INHERITANCE).verify();
+        EqualsVerifier.forClass(MqttAdvancedConfig.class).suppress(Warning.STRICT_INHERITANCE).verify();
     }
 }
\ No newline at end of file
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/advanced/interceptor/MqttClientInterceptorsTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/advanced/interceptor/MqttClientInterceptorsTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/advanced/interceptor/MqttClientInterceptorsTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/advanced/interceptor/MqttClientInterceptorsTest.java
index 50c1ae774..c5f3ea70a 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/advanced/interceptor/MqttClientInterceptorsTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/advanced/interceptor/MqttClientInterceptorsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.advanced.interceptor;
+package com.hivemq.client2.internal.mqtt.advanced.interceptor;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/AbstractMqttDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/AbstractMqttDecoderTest.java
similarity index 75%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/AbstractMqttDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/AbstractMqttDecoderTest.java
index 311c9fd65..8984fb6e0 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/AbstractMqttDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/AbstractMqttDecoderTest.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder;
-
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttClientExecutorConfigImpl;
-import com.hivemq.client.internal.mqtt.MqttClientTransportConfigImpl;
-import com.hivemq.client.internal.mqtt.advanced.MqttClientAdvancedConfig;
-import com.hivemq.client.internal.mqtt.advanced.MqttClientAdvancedConfigBuilder;
-import com.hivemq.client.internal.mqtt.datatypes.MqttClientIdentifierImpl;
-import com.hivemq.client.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.MqttVersion;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5MessageException;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5Message;
+package com.hivemq.client2.internal.mqtt.codec.decoder;
+
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttExecutorConfigImpl;
+import com.hivemq.client2.internal.mqtt.MqttTransportConfigImpl;
+import com.hivemq.client2.internal.mqtt.advanced.MqttAdvancedConfig;
+import com.hivemq.client2.internal.mqtt.advanced.MqttAdvancedConfigBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttClientIdentifierImpl;
+import com.hivemq.client2.internal.mqtt.handler.disconnect.MqttDisconnectEvent;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.MqttVersion;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5MessageException;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5Message;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
@@ -106,11 +106,11 @@ protected void createChannel() {
     }
 
     private void createChannel(final boolean validatePayloadFormat) {
-        final MqttClientAdvancedConfig advancedConfig =
-                new MqttClientAdvancedConfigBuilder.Default().validatePayloadFormat(validatePayloadFormat).build();
+        final MqttAdvancedConfig advancedConfig =
+                new MqttAdvancedConfigBuilder.Default().validatePayloadFormat(validatePayloadFormat).build();
         final MqttClientConfig clientConfig =
                 new MqttClientConfig(MqttVersion.MQTT_5_0, MqttClientIdentifierImpl.of("test"),
-                        MqttClientTransportConfigImpl.DEFAULT, MqttClientExecutorConfigImpl.DEFAULT, advancedConfig,
+                        MqttTransportConfigImpl.DEFAULT, MqttExecutorConfigImpl.DEFAULT, advancedConfig,
                         MqttClientConfig.ConnectDefaults.of(null, null, null), ImmutableList.of(), ImmutableList.of());
 
         channel = new EmbeddedChannel();
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/AbstractMqtt3DecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/AbstractMqtt3DecoderTest.java
similarity index 73%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/AbstractMqtt3DecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/AbstractMqtt3DecoderTest.java
index 0726edf2f..2a79193c9 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/AbstractMqtt3DecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/AbstractMqtt3DecoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.AbstractMqttDecoderTest;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
-import com.hivemq.client.mqtt.MqttVersion;
+import com.hivemq.client2.internal.mqtt.codec.decoder.AbstractMqttDecoderTest;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectView;
+import com.hivemq.client2.mqtt.MqttVersion;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecodersTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecodersTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecodersTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecodersTest.java
index ad972d684..1ec495d8e 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecodersTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ClientMessageDecodersTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.AbstractMqttDecoderTest;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttPingRespDecoder;
+import com.hivemq.client2.internal.mqtt.codec.decoder.AbstractMqttDecoderTest;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttPingRespDecoder;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertNull;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoderTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoderTest.java
index e6b6d0489..5581bc149 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3ConnAckDecoderTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
 import com.google.common.primitives.Bytes;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckReasonCode;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoderTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoderTest.java
index 9c1993df1..ff643d5ee 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubAckDecoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
 import com.google.common.primitives.Bytes;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoderTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoderTest.java
index 83ff67d92..b8b8b16ec 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubCompDecoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
 import com.google.common.primitives.Bytes;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoderTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoderTest.java
index 731fe56a8..56109bc39 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRecDecoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
 import com.google.common.primitives.Bytes;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoderTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoderTest.java
index 6da8b34d8..c1f2a985f 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PubRelDecoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
 import com.google.common.primitives.Bytes;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoderTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoderTest.java
index 1d0ddd9c7..cce83a7a3 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3PublishDecoderTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoderTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoderTest.java
index 4a17009e1..f51f68783 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3SubAckDecoderTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
 import com.google.common.primitives.Bytes;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAck;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAckReasonCode;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAckReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoderTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoderTest.java
index 0f7a57fa2..66808b660 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt3/Mqtt3UnsubAckDecoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt3;
 
 import com.google.common.primitives.Bytes;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.MqttUnsubAck;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubAck;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/AbstractMqtt5DecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/AbstractMqtt5DecoderTest.java
similarity index 71%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/AbstractMqtt5DecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/AbstractMqtt5DecoderTest.java
index 812065e55..5f22d840d 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/AbstractMqtt5DecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/AbstractMqtt5DecoderTest.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.AbstractMqttDecoderTest;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectBuilder;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictions;
-import com.hivemq.client.mqtt.MqttVersion;
+import com.hivemq.client2.internal.mqtt.codec.decoder.AbstractMqttDecoderTest;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectBuilder;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectRestrictions;
+import com.hivemq.client2.mqtt.MqttVersion;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -30,7 +30,7 @@
 abstract class AbstractMqtt5DecoderTest extends AbstractMqttDecoderTest {
 
     private static @NotNull MqttConnect createConnect(final int maximumPacketSize) {
-        return new MqttConnectBuilder.Default().restrictions()
+        return new MqttConnectBuilder.Default().restrictionsWith()
                 .maximumPacketSize(maximumPacketSize)
                 .topicAliasMaximum(3)
                 .requestResponseInformation(true)
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoderTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoderTest.java
index 6fafbe6d2..58e7c5fbc 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5AuthDecoderTest.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.message.auth.MqttAuth;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5Auth;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttAuth;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5Auth;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecodersTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecodersTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecodersTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecodersTest.java
index 57ce0ac7a..79946d579 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecodersTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ClientMessageDecodersTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.AbstractMqttDecoderTest;
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttPingRespDecoder;
+import com.hivemq.client2.internal.mqtt.codec.decoder.AbstractMqttDecoderTest;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttPingRespDecoder;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertNull;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoderTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoderTest.java
index a24f884d1..8ac133986 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5ConnAckDecoderTest.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAck;
-import com.hivemq.client.internal.mqtt.message.connect.connack.MqttConnAckRestrictions;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuth;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckRestrictions;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAck;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnAckRestrictions;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuth;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAckRestrictions;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoderTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoderTest.java
index 333819b86..60dd41c67 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5DisconnectDecoderTest.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtilTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtilTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtilTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtilTest.java
index 967ab72c8..6220a8567 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtilTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5MessageDecoderUtilTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttDecoderException;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttDecoderException;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.junit.jupiter.api.AfterEach;
@@ -25,8 +25,8 @@
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 
-import static com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.MALFORMED_PACKET;
-import static com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.PROTOCOL_ERROR;
+import static com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.MALFORMED_PACKET;
+import static com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.PROTOCOL_ERROR;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PingRespDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PingRespDecoderTest.java
similarity index 87%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PingRespDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PingRespDecoderTest.java
index 28404b332..8e4f67fa6 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PingRespDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PingRespDecoderTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.ping.Mqtt5PingResp;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.ping.Mqtt5PingResp;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoderTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoderTest.java
index afd6022ec..9e5454806 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubAckDecoderTest.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAckReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoderTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoderTest.java
index b9507d2ea..0e86859ea 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubCompDecoderTest.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoderTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoderTest.java
index d1be2e21f..6c9c15279 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRecDecoderTest.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -31,8 +31,8 @@
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 
-import static com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.MALFORMED_PACKET;
-import static com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecReasonCode.SUCCESS;
+import static com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.MALFORMED_PACKET;
+import static com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecReasonCode.SUCCESS;
 import static org.junit.jupiter.api.Assertions.*;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoderTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoderTest.java
index aff4e0ba2..aa852082f 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PubRelDecoderTest.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelReasonCode;
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRelReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -31,8 +31,8 @@
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.EnumSource;
 
-import static com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.MALFORMED_PACKET;
-import static com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelReasonCode.SUCCESS;
+import static com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.MALFORMED_PACKET;
+import static com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRelReasonCode.SUCCESS;
 import static org.junit.jupiter.api.Assertions.*;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoderTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoderTest.java
index 273c67054..91c25c77f 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5PublishDecoderTest.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.util.collections.ImmutableIntList;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish;
+import com.hivemq.client2.internal.util.collections.ImmutableIntList;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
@@ -34,7 +34,7 @@
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 
-import static com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.*;
+import static com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.*;
 import static org.junit.jupiter.api.Assertions.*;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoderTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoderTest.java
index 176a68cbf..30fe718c9 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5SubAckDecoderTest.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.message.subscribe.suback.MqttSubAck;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubAck;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAckReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -31,7 +31,7 @@
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.EnumSource;
 
-import static com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.MALFORMED_PACKET;
+import static com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.MALFORMED_PACKET;
 import static org.junit.jupiter.api.Assertions.*;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoderTest.java
similarity index 94%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoderTest.java
index cf00ae19e..aec500c38 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/decoder/mqtt5/Mqtt5UnsubAckDecoderTest.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.decoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.decoder.MqttMessageDecoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback.MqttUnsubAck;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.decoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.decoder.MqttMessageDecoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubAck;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperty;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAckReasonCode;
 import io.netty.buffer.ByteBuf;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -36,9 +36,9 @@
 import java.util.List;
 import java.util.Optional;
 
-import static com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.MALFORMED_PACKET;
-import static com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.PROTOCOL_ERROR;
-import static com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAckReasonCode.*;
+import static com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.MALFORMED_PACKET;
+import static com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.PROTOCOL_ERROR;
+import static com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAckReasonCode.*;
 import static org.junit.jupiter.api.Assertions.*;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/AbstractMqttEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/AbstractMqttEncoderTest.java
similarity index 80%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/AbstractMqttEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/AbstractMqttEncoderTest.java
index 9bdb3ea75..12c841d7b 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/AbstractMqttEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/AbstractMqttEncoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder;
+package com.hivemq.client2.internal.mqtt.codec.encoder;
 
-import com.hivemq.client.internal.mqtt.MqttClientConnectionConfig;
-import com.hivemq.client.internal.mqtt.MqttClientTransportConfigImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.internal.mqtt.MqttClientConnectionConfig;
+import com.hivemq.client2.internal.mqtt.MqttTransportConfigImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.embedded.EmbeddedChannel;
 import org.jetbrains.annotations.NotNull;
@@ -65,9 +65,9 @@ private void createChannel() {
 
     protected void connected(final int maximumPacketSize) {
         encoder.onConnected(
-                new MqttClientConnectionConfig(MqttClientTransportConfigImpl.DEFAULT, 10, true, true, 0, false, false,
-                        null, 10, MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT, 0, true, false, 10,
-                        maximumPacketSize, 3, MqttQos.EXACTLY_ONCE, true, true, true, true, channel));
+                new MqttClientConnectionConfig(MqttTransportConfigImpl.DEFAULT, 10, true, true, 0, false, false, null,
+                        10, MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT, 0, true, false, 10, maximumPacketSize, 3,
+                        MqttQos.EXACTLY_ONCE, true, true, true, true, channel));
     }
 
     protected void encode(final @NotNull Object message, final @NotNull byte[] expected) {
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/AbstractMqtt3EncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/AbstractMqtt3EncoderTest.java
similarity index 85%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/AbstractMqtt3EncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/AbstractMqtt3EncoderTest.java
index 8cac80a9c..1bde23765 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/AbstractMqtt3EncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/AbstractMqtt3EncoderTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
 import com.google.common.primitives.Bytes;
-import com.hivemq.client.internal.mqtt.codec.encoder.AbstractMqttEncoderTest;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.codec.encoder.AbstractMqttEncoderTest;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
 import org.eclipse.paho.client.mqttv3.MqttException;
 import org.eclipse.paho.client.mqttv3.internal.wire.MqttWireMessage;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoderTest.java
similarity index 86%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoderTest.java
index a22542143..7363efdca 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3ConnectEncoderTest.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttClientIdentifierImpl;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttStatefulConnect;
-import com.hivemq.client.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttClientIdentifierImpl;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttStatefulConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.mqtt3.Mqtt3ConnectViewBuilder;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import org.eclipse.paho.client.mqttv3.MqttException;
 import org.eclipse.paho.client.mqttv3.MqttMessage;
 import org.jetbrains.annotations.NotNull;
@@ -68,13 +68,13 @@ void matchesPaho(
         Mqtt3ConnectViewBuilder.Default connectBuilder =
                 new Mqtt3ConnectViewBuilder.Default().cleanSession(cleanSession).keepAlive(keepAliveInterval);
         if (hasAuth) {
-            connectBuilder = connectBuilder.simpleAuth()
+            connectBuilder = connectBuilder.simpleAuthWith()
                     .username(userName)
                     .password(password.getBytes(StandardCharsets.UTF_8))
                     .applySimpleAuth();
         }
         if (hasWill) {
-            connectBuilder = connectBuilder.willPublish()
+            connectBuilder = connectBuilder.willPublishWith()
                     .topic(willTopic)
                     .qos(Objects.requireNonNull(MqttQos.fromCode(willQos)))
                     .payload(willMessage.getBytes(StandardCharsets.UTF_8))
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PingReqEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PingReqEncoderTest.java
similarity index 82%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PingReqEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PingReqEncoderTest.java
index 6d489c57e..efc49d569 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PingReqEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PingReqEncoderTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.message.ping.MqttPingReq;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.message.ping.MqttPingReq;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import org.eclipse.paho.client.mqttv3.MqttException;
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoderTest.java
similarity index 78%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoderTest.java
index 574efd163..3ae7efbe3 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubAckEncoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.internal.mqtt.message.publish.puback.mqtt3.Mqtt3PubAckView;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubAckView;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import org.eclipse.paho.client.mqttv3.MqttException;
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoderTest.java
similarity index 78%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoderTest.java
index 08eb61b51..ccfd90f42 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubCompEncoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.mqtt3.Mqtt3PubCompView;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubCompView;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import org.eclipse.paho.client.mqttv3.MqttException;
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoderTest.java
similarity index 81%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoderTest.java
index 5d19f6107..c96f2948d 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRecEncoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.mqtt3.Mqtt3PubRecView;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubRecView;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import org.eclipse.paho.client.mqttv3.MqttException;
 import org.eclipse.paho.client.mqttv3.MqttMessage;
 import org.eclipse.paho.client.mqttv3.internal.wire.MqttPublish;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoderTest.java
similarity index 82%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoderTest.java
index b246d855e..ba7682f23 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt3/Mqtt3PubRelEncoderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt3;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt3;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.mqtt3.Mqtt3PubRelView;
-import com.hivemq.client.mqtt.mqtt3.message.Mqtt3MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubRelView;
+import com.hivemq.client2.mqtt.mqtt3.message.Mqtt3MessageType;
 import org.eclipse.paho.client.mqttv3.MqttException;
 import org.eclipse.paho.client.mqttv3.MqttMessage;
 import org.eclipse.paho.client.mqttv3.internal.wire.MqttPubRec;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderTest.java
similarity index 81%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderTest.java
index 1f785c266..780053680 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.AbstractMqttEncoderTest;
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.codec.encoder.AbstractMqttEncoderTest;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderWithUserPropertiesTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderWithUserPropertiesTest.java
similarity index 90%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderWithUserPropertiesTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderWithUserPropertiesTest.java
index 48a03514c..81d20197c 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderWithUserPropertiesTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/AbstractMqtt5EncoderWithUserPropertiesTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Arrays;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoderTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoderTest.java
index 8c5c054f2..9efdbb983 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5AuthEncoderTest.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.auth.MqttAuth;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttAuth;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthReasonCode;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.handler.codec.EncoderException;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoderTest.java
similarity index 94%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoderTest.java
index bb0b0089e..fb29d9e86 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5ConnectEncoderTest.java
@@ -14,31 +14,31 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.*;
-import com.hivemq.client.internal.mqtt.message.auth.MqttEnhancedAuth;
-import com.hivemq.client.internal.mqtt.message.auth.MqttSimpleAuth;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnect;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictions;
-import com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictionsBuilder;
-import com.hivemq.client.internal.mqtt.message.connect.MqttStatefulConnect;
-import com.hivemq.client.internal.mqtt.message.publish.MqttWillPublish;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.datatypes.MqttUtf8String;
-import com.hivemq.client.mqtt.exceptions.MqttEncodeException;
-import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientConfig;
-import com.hivemq.client.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5Auth;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5AuthBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuthBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.*;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttEnhancedAuth;
+import com.hivemq.client2.internal.mqtt.message.auth.MqttSimpleAuth;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnect;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectRestrictions;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttConnectRestrictionsBuilder;
+import com.hivemq.client2.internal.mqtt.message.connect.MqttStatefulConnect;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttWillPublish;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.datatypes.MqttUtf8String;
+import com.hivemq.client2.mqtt.exceptions.MqttEncodeException;
+import com.hivemq.client2.mqtt.mqtt5.Mqtt5ClientConfig;
+import com.hivemq.client2.mqtt.mqtt5.auth.Mqtt5EnhancedAuthMechanism;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5Auth;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5AuthBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5EnhancedAuthBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5Connect;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
 import io.netty.handler.codec.EncoderException;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Disabled;
@@ -48,7 +48,7 @@
 import java.util.Arrays;
 import java.util.concurrent.CompletableFuture;
 
-import static com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictions.DEFAULT;
+import static com.hivemq.client2.internal.mqtt.message.connect.MqttConnectRestrictions.DEFAULT;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoderTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoderTest.java
index 3140a2004..42e217248 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5DisconnectEncoderTest.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
@@ -34,8 +34,8 @@
 
 import java.util.Arrays;
 
-import static com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
-import static com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.*;
+import static com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect.SESSION_EXPIRY_INTERVAL_FROM_CONNECT;
+import static com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectReasonCode.*;
 import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PingReqEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PingReqEncoderTest.java
similarity index 85%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PingReqEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PingReqEncoderTest.java
index 3a4c9de9a..841760c1e 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PingReqEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PingReqEncoderTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
 
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.message.ping.MqttPingReq;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.message.ping.MqttPingReq;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import io.netty.buffer.ByteBuf;
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoderTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoderTest.java
index 325bccc68..1e8e6b17d 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubAckEncoderTest.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.publish.puback.MqttPubAck;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAckReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubAck;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAckReasonCode;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
@@ -32,7 +32,7 @@
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.EnumSource;
 
-import static com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT;
+import static com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT;
 import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoderTest.java
similarity index 91%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoderTest.java
index 6f224b309..36ce57ab4 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubCompEncoderTest.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.publish.pubcomp.MqttPubComp;
-import com.hivemq.client.mqtt.exceptions.MqttEncodeException;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubComp;
+import com.hivemq.client2.mqtt.exceptions.MqttEncodeException;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompReasonCode;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
@@ -31,9 +31,9 @@
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.EnumSource;
 
-import static com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT;
-import static com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompReasonCode.PACKET_IDENTIFIER_NOT_FOUND;
-import static com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp.Mqtt5PubCompReasonCode.SUCCESS;
+import static com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT;
+import static com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompReasonCode.PACKET_IDENTIFIER_NOT_FOUND;
+import static com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubCompReasonCode.SUCCESS;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoderTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoderTest.java
index dabb4839c..c4d724b0c 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRecEncoderTest.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.publish.pubrec.MqttPubRec;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRec;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecReasonCode;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
@@ -29,8 +29,8 @@
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.EnumSource;
 
-import static com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT;
-import static com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRecReasonCode.SUCCESS;
+import static com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT;
+import static com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRecReasonCode.SUCCESS;
 import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoderTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoderTest.java
index 2dc2e46c1..1d6f41856 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PubRelEncoderTest.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger;
-import com.hivemq.client.internal.mqtt.message.publish.pubrel.MqttPubRel;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelReasonCode;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPubRel;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRelReasonCode;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
@@ -30,8 +30,8 @@
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.EnumSource;
 
-import static com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT;
-import static com.hivemq.client.mqtt.mqtt5.message.publish.pubrel.Mqtt5PubRelReasonCode.SUCCESS;
+import static com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT;
+import static com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRelReasonCode.SUCCESS;
 import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoderTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoderTest.java
index 64158e4ac..dc6e45b66 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5PublishEncoderTest.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.*;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishProperty;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.util.collections.ImmutableIntList;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.exceptions.MqttEncodeException;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.*;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishProperty;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish;
+import com.hivemq.client2.internal.util.collections.ImmutableIntList;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.exceptions.MqttEncodeException;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
@@ -34,9 +34,9 @@
 
 import java.nio.ByteBuffer;
 
-import static com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl.NO_USER_PROPERTIES;
-import static com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish.DEFAULT_NO_SUBSCRIPTION_IDENTIFIERS;
-import static com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish.DEFAULT_NO_TOPIC_ALIAS;
+import static com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl.NO_USER_PROPERTIES;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish.DEFAULT_NO_SUBSCRIPTION_IDENTIFIERS;
+import static com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish.DEFAULT_NO_TOPIC_ALIAS;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoderTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoderTest.java
index 1ff1cd840..5baf15dcc 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5SubscribeEncoderTest.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttStatefulSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscribe;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.exceptions.MqttEncodeException;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttStatefulSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscribe;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.exceptions.MqttEncodeException;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -39,8 +39,8 @@
 import java.util.Collections;
 import java.util.List;
 
-import static com.hivemq.client.internal.mqtt.datatypes.MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT;
-import static com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscription.*;
+import static com.hivemq.client2.internal.mqtt.datatypes.MqttVariableByteInteger.MAXIMUM_PACKET_SIZE_LIMIT;
+import static com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscription.*;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
@@ -88,7 +88,7 @@ void encode_allProperties() {
         final MqttTopicFilterImpl topicFiler = MqttTopicFilterImpl.of("topic/#");
         final MqttQos qos = MqttQos.AT_LEAST_ONCE;
         final boolean isNoLocal = true;
-        final Mqtt5RetainHandling retainHandling = Mqtt5RetainHandling.SEND_IF_SUBSCRIPTION_DOES_NOT_EXIST;
+        final Mqtt5RetainHandling retainHandling = Mqtt5RetainHandling.SEND_IF_NEW_SUBSCRIPTION;
         final boolean isRetainAsPublished = true;
         final ImmutableList<MqttSubscription> subscriptions =
                 ImmutableList.of(new MqttSubscription(topicFiler, qos, isNoLocal, retainHandling, isRetainAsPublished));
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoderTest.java
similarity index 94%
rename from src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoderTest.java
index 3c6b72faf..0f74dab1c 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/codec/encoder/mqtt5/Mqtt5UnsubscribeEncoderTest.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.codec.encoder.mqtt5;
-
-import com.hivemq.client.internal.mqtt.codec.encoder.MqttMessageEncoders;
-import com.hivemq.client.internal.mqtt.datatypes.*;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttStatefulUnsubscribe;
-import com.hivemq.client.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.exceptions.MqttEncodeException;
-import com.hivemq.client.mqtt.mqtt5.message.Mqtt5MessageType;
+package com.hivemq.client2.internal.mqtt.codec.encoder.mqtt5;
+
+import com.hivemq.client2.internal.mqtt.codec.encoder.MqttMessageEncoders;
+import com.hivemq.client2.internal.mqtt.datatypes.*;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttStatefulUnsubscribe;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.MqttUnsubscribe;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.exceptions.MqttEncodeException;
+import com.hivemq.client2.mqtt.mqtt5.message.Mqtt5MessageType;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttBinaryDataTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttBinaryDataTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttBinaryDataTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttBinaryDataTest.java
index ce3652ef3..a1e3520d0 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttBinaryDataTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttBinaryDataTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttClientIdentifierImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttClientIdentifierImplTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttClientIdentifierImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttClientIdentifierImplTest.java
index 8dd1479e3..8c91c37f3 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttClientIdentifierImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttClientIdentifierImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttSharedTopicFilterImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttSharedTopicFilterImplTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttSharedTopicFilterImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttSharedTopicFilterImplTest.java
index bb7b18629..cb981ec65 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttSharedTopicFilterImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttSharedTopicFilterImplTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicFilterImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicFilterImplTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicFilterImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicFilterImplTest.java
index 41b3ea98e..0c75ccf91 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicFilterImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicFilterImplTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicImplTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicImplTest.java
index 2aa9cb718..be9f54bad 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicImplTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicIteratorTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicIteratorTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicIteratorTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicIteratorTest.java
index c4ac1ef24..fbda64679 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicIteratorTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicIteratorTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevelTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevelTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevelTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevelTest.java
index 756e00e2c..e47038f3c 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevelTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevelTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevelsTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevelsTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevelsTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevelsTest.java
index 33306bd34..b60e632f8 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttTopicLevelsTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttTopicLevelsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImplBuilderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImplBuilderTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImplBuilderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImplBuilderTest.java
index 27681e7f2..8498bebf8 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImplBuilderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImplBuilderTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
-import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperties;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserPropertiesBuilder;
+import com.hivemq.client2.mqtt.mqtt5.datatypes.Mqtt5UserProperty;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImplTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImplTest.java
index d80bb5bf8..3b7c46b92 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertiesImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertiesImplTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
-import com.hivemq.client.internal.mqtt.message.MqttProperty;
-import com.hivemq.client.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.mqtt.message.MqttProperty;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertyImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertyImplTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertyImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertyImplTest.java
index 8e8cd516f..a8a6eb92e 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUserPropertyImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUserPropertyImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUtf8StringImplTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUtf8StringImplTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUtf8StringImplTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUtf8StringImplTest.java
index b93af02c1..6da80e8ea 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttUtf8StringImplTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttUtf8StringImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
 import com.google.common.base.Utf8;
 import io.netty.buffer.ByteBuf;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttVariableByteIntegerTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttVariableByteIntegerTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttVariableByteIntegerTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttVariableByteIntegerTest.java
index 0253b5764..322773c1e 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/datatypes/MqttVariableByteIntegerTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/datatypes/MqttVariableByteIntegerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.datatypes;
+package com.hivemq.client2.internal.mqtt.datatypes;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTreeTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTreeTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTreeTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTreeTest.java
index 7071a831e..534433929 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTreeTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowTreeTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscriptionBuilder;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscriptionBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowsTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowsTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowsTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowsTest.java
index 163645bff..bdc3cf801 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowsTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/handler/publish/incoming/MqttSubscribedPublishFlowsTest.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.publish.incoming;
+package com.hivemq.client2.internal.mqtt.handler.publish.incoming;
 
 import com.google.common.collect.ImmutableSet;
-import com.hivemq.client.internal.mqtt.datatypes.MqttTopicFilterImpl;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishBuilder;
-import com.hivemq.client.internal.mqtt.message.publish.MqttStatefulPublish;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscription;
-import com.hivemq.client.internal.mqtt.message.subscribe.MqttSubscriptionBuilder;
-import com.hivemq.client.internal.util.collections.HandleList;
-import com.hivemq.client.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttTopicFilterImpl;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttStatefulPublish;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscription;
+import com.hivemq.client2.internal.mqtt.message.subscribe.MqttSubscriptionBuilder;
+import com.hivemq.client2.internal.util.collections.HandleList;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/handler/ssl/MqttSslInitializerTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/handler/tls/MqttTlsInitializerTest.java
similarity index 82%
rename from src/test/java/com/hivemq/client/internal/mqtt/handler/ssl/MqttSslInitializerTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/handler/tls/MqttTlsInitializerTest.java
index e163dccf0..094f869cf 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/handler/ssl/MqttSslInitializerTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/handler/tls/MqttTlsInitializerTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.handler.ssl;
+package com.hivemq.client2.internal.mqtt.handler.tls;
 
-import com.hivemq.client.internal.mqtt.MqttClientSslConfigImpl;
-import com.hivemq.client.internal.mqtt.MqttClientSslConfigImplBuilder;
-import com.hivemq.client.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.mqtt.MqttTlsConfigImpl;
+import com.hivemq.client2.internal.mqtt.MqttTlsConfigImplBuilder;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
 import io.netty.channel.Channel;
 import io.netty.channel.embedded.EmbeddedChannel;
 import io.netty.handler.ssl.SslContextBuilder;
@@ -40,7 +40,7 @@
 /**
  * @author Christoph Schäbel
  */
-class MqttSslInitializerTest {
+class MqttTlsInitializerTest {
 
     @SuppressWarnings("NullabilityAnnotations")
     private EmbeddedChannel embeddedChannel;
@@ -56,7 +56,7 @@ public void test_createSslEngine_null_values() throws Exception {
         final TrustManagerFactory tmf = null;
 
         final SSLEngine sslEngine = createSslEngine(embeddedChannel,
-                new MqttClientSslConfigImplBuilder.Default().trustManagerFactory(tmf).build());
+                new MqttTlsConfigImplBuilder.Default().trustManagerFactory(tmf).build());
 
         assertNotNull(sslEngine);
         assertTrue(sslEngine.getUseClientMode());
@@ -72,9 +72,7 @@ public void test_createSslEngine_cipher_suite() throws Exception {
         final ImmutableList<String> cipherSuite = getFirstSupportedCipherSuite();
 
         final SSLEngine sslEngine = createSslEngine(embeddedChannel,
-                new MqttClientSslConfigImplBuilder.Default().trustManagerFactory(tmf)
-                        .cipherSuites(cipherSuite)
-                        .build());
+                new MqttTlsConfigImplBuilder.Default().trustManagerFactory(tmf).cipherSuites(cipherSuite).build());
 
         assertNotNull(sslEngine);
 
@@ -92,9 +90,7 @@ public void test_createSslEngine_multiple_cipher_suites() throws Exception {
         final ImmutableList<String> cipherSuites = getOtherSupportedCipherSuites();
 
         final SSLEngine sslEngine = createSslEngine(embeddedChannel,
-                new MqttClientSslConfigImplBuilder.Default().trustManagerFactory(tmf)
-                        .cipherSuites(cipherSuites)
-                        .build());
+                new MqttTlsConfigImplBuilder.Default().trustManagerFactory(tmf).cipherSuites(cipherSuites).build());
 
         assertNotNull(sslEngine);
 
@@ -115,7 +111,7 @@ public void test_createSslEngine_protocol() throws Exception {
         final ImmutableList<String> protocol = ImmutableList.of("TLSv1");
 
         final SSLEngine sslEngine = createSslEngine(embeddedChannel,
-                new MqttClientSslConfigImplBuilder.Default().trustManagerFactory(tmf).protocols(protocol).build());
+                new MqttTlsConfigImplBuilder.Default().trustManagerFactory(tmf).protocols(protocol).build());
 
         assertNotNull(sslEngine);
 
@@ -133,7 +129,7 @@ public void test_createSslEngine_multiple_protocols() throws Exception {
         final ImmutableList<String> protocols = ImmutableList.of("TLSv1.1", "TLSv1.2");
 
         final SSLEngine sslEngine = createSslEngine(embeddedChannel,
-                new MqttClientSslConfigImplBuilder.Default().trustManagerFactory(tmf).protocols(protocols).build());
+                new MqttTlsConfigImplBuilder.Default().trustManagerFactory(tmf).protocols(protocols).build());
 
         assertNotNull(sslEngine);
 
@@ -181,8 +177,8 @@ private List<String> getEnabledProtocols() throws Exception {
     }
 
     private static @NotNull SSLEngine createSslEngine(
-            final @NotNull Channel channel, final @NotNull MqttClientSslConfigImpl sslConfig) throws SSLException {
+            final @NotNull Channel channel, final @NotNull MqttTlsConfigImpl tlsConfig) throws SSLException {
 
-        return MqttSslInitializer.createSslContext(sslConfig).newEngine(channel.alloc());
+        return MqttTlsInitializer.createSslContext(tlsConfig).newEngine(channel.alloc());
     }
 }
\ No newline at end of file
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/MqttPropertyTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/MqttPropertyTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/MqttPropertyTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/MqttPropertyTest.java
index ad8dacb85..07877c239 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/MqttPropertyTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/MqttPropertyTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message;
+package com.hivemq.client2.internal.mqtt.message;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client2/internal/mqtt/message/MqttReasonCodesTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/MqttReasonCodesTest.java
new file mode 100644
index 000000000..b30ae9a5c
--- /dev/null
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/MqttReasonCodesTest.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2018-present HiveMQ and the HiveMQ Community
+ *
+ * Licensed 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
+ *
+ *     http://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 com.hivemq.client2.internal.mqtt.message;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Silvio Giebl
+ */
+class MqttReasonCodesTest {
+
+    @Test
+    void test_getCode_success() {
+        assertEquals(0x00, MqttReasonCodes.SUCCESS);
+    }
+
+    @Test
+    void test_getCode_grantedQos1() {
+        assertEquals(0x01, MqttReasonCodes.GRANTED_QOS_1);
+    }
+
+    @Test
+    void test_getCode_grantedQos2() {
+        assertEquals(0x02, MqttReasonCodes.GRANTED_QOS_2);
+    }
+
+    @Test
+    void test_getCode_disconnectWithWillMessage() {
+        assertEquals(0x04, MqttReasonCodes.DISCONNECT_WITH_WILL_MESSAGE);
+    }
+
+    @Test
+    void test_getCode_noMatchingSubscribers() {
+        assertEquals(0x10, MqttReasonCodes.NO_MATCHING_SUBSCRIBERS);
+    }
+
+    @Test
+    void test_getCode_noSubscriptionsExisted() {
+        assertEquals(0x11, MqttReasonCodes.NO_SUBSCRIPTIONS_EXISTED);
+    }
+
+    @Test
+    void test_getCode_continueAuthentication() {
+        assertEquals(0x18, MqttReasonCodes.CONTINUE_AUTHENTICATION);
+    }
+
+    @Test
+    void test_getCode_reauthenticate() {
+        assertEquals(0x19, MqttReasonCodes.REAUTHENTICATE);
+    }
+
+    @Test
+    void test_getCode_unspecifiedError() {
+        assertEquals(0x80, MqttReasonCodes.UNSPECIFIED_ERROR);
+    }
+
+    @Test
+    void test_getCode_malformedPacket() {
+        assertEquals(0x81, MqttReasonCodes.MALFORMED_PACKET);
+    }
+
+    @Test
+    void test_getCode_protocolError() {
+        assertEquals(0x82, MqttReasonCodes.PROTOCOL_ERROR);
+    }
+
+    @Test
+    void test_getCode_implementationSpecificError() {
+        assertEquals(0x83, MqttReasonCodes.IMPLEMENTATION_SPECIFIC_ERROR);
+    }
+
+    @Test
+    void test_getCode_unsupportedProtocolVersion() {
+        assertEquals(0x84, MqttReasonCodes.UNSUPPORTED_PROTOCOL_VERSION);
+    }
+
+    @Test
+    void test_getCode_clientIdentifierNotValid() {
+        assertEquals(0x85, MqttReasonCodes.CLIENT_IDENTIFIER_NOT_VALID);
+    }
+
+    @Test
+    void test_getCode_badUsernameOrPassword() {
+        assertEquals(0x86, MqttReasonCodes.BAD_USER_NAME_OR_PASSWORD);
+    }
+
+    @Test
+    void test_getCode_notAuthorized() {
+        assertEquals(0x87, MqttReasonCodes.NOT_AUTHORIZED);
+    }
+
+    @Test
+    void test_getCode_serverUnavailable() {
+        assertEquals(0x88, MqttReasonCodes.SERVER_UNAVAILABLE);
+    }
+
+    @Test
+    void test_getCode_SererBusy() {
+        assertEquals(0x89, MqttReasonCodes.SERVER_BUSY);
+    }
+
+    @Test
+    void test_getCode_banned() {
+        assertEquals(0x8A, MqttReasonCodes.BANNED);
+    }
+
+    @Test
+    void test_getCode_badAuthenticationMethod() {
+        assertEquals(0x8C, MqttReasonCodes.BAD_AUTHENTICATION_METHOD);
+    }
+
+    @Test
+    void test_getCode_keepAliveTimeout() {
+        assertEquals(0x8D, MqttReasonCodes.KEEP_ALIVE_TIMEOUT);
+    }
+
+    @Test
+    void test_getCode_sessionTakenOver() {
+        assertEquals(0x8E, MqttReasonCodes.SESSION_TAKEN_OVER);
+    }
+
+    @Test
+    void test_getCode_topicFilterInvalid() {
+        assertEquals(0x8F, MqttReasonCodes.TOPIC_FILTER_INVALID);
+    }
+
+    @Test
+    void test_getCode_TopicNameInvalid() {
+        assertEquals(0x90, MqttReasonCodes.TOPIC_NAME_INVALID);
+    }
+
+    @Test
+    void test_getCode_packetIdentifierInUse() {
+        assertEquals(0x91, MqttReasonCodes.PACKET_IDENTIFIER_IN_USE);
+    }
+
+    @Test
+    void test_getCode_packetIdentifierNotFound() {
+        assertEquals(0x92, MqttReasonCodes.PACKET_IDENTIFIER_NOT_FOUND);
+    }
+
+    @Test
+    void test_getCode_receiveMaximumExceeded() {
+        assertEquals(0x93, MqttReasonCodes.RECEIVE_MAXIMUM_EXCEEDED);
+    }
+
+    @Test
+    void test_getCode_topicAliasInvalid() {
+        assertEquals(0x94, MqttReasonCodes.TOPIC_ALIAS_INVALID);
+    }
+
+    @Test
+    void test_getCode_packetTooLarge() {
+        assertEquals(0x95, MqttReasonCodes.PACKET_TOO_LARGE);
+    }
+
+    @Test
+    void test_getCode_messageRateTooHigh() {
+        assertEquals(0x96, MqttReasonCodes.MESSAGE_RATE_TOO_HIGH);
+    }
+
+    @Test
+    void test_getCode_quotaExceeded() {
+        assertEquals(0x97, MqttReasonCodes.QUOTA_EXCEEDED);
+    }
+
+    @Test
+    void test_getCode_administrativeAction() {
+        assertEquals(0x98, MqttReasonCodes.ADMINISTRATIVE_ACTION);
+    }
+
+    @Test
+    void test_getCode_payloadFormatInvalid() {
+        assertEquals(0x99, MqttReasonCodes.PAYLOAD_FORMAT_INVALID);
+    }
+
+    @Test
+    void test_getCode_retainNotSupported() {
+        assertEquals(0x9A, MqttReasonCodes.RETAIN_NOT_SUPPORTED);
+    }
+
+    @Test
+    void test_getCode_qosNotSupported() {
+        assertEquals(0x9B, MqttReasonCodes.QOS_NOT_SUPPORTED);
+    }
+
+    @Test
+    void test_getCode_useAnotherServer() {
+        assertEquals(0x9C, MqttReasonCodes.USE_ANOTHER_SERVER);
+    }
+
+    @Test
+    void test_getCode_serverMoved() {
+        assertEquals(0x9D, MqttReasonCodes.SERVER_MOVED);
+    }
+
+    @Test
+    void test_getCode_sharedSubscriptionNotSupported() {
+        assertEquals(0x9E, MqttReasonCodes.SHARED_SUBSCRIPTIONS_NOT_SUPPORTED);
+    }
+
+    @Test
+    void test_getCode_connectionRateExceeded() {
+        assertEquals(0x9F, MqttReasonCodes.CONNECTION_RATE_EXCEEDED);
+    }
+
+    @Test
+    void test_getCode_maximumConnectTime() {
+        assertEquals(0xA0, MqttReasonCodes.MAXIMUM_CONNECT_TIME);
+    }
+
+    @Test
+    void test_getCode_subscriptionIdentifiersNotSupported() {
+        assertEquals(0xA1, MqttReasonCodes.SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED);
+    }
+
+    @Test
+    void test_getCode_wildcardSubscriptionNotSupported() {
+        assertEquals(0xA2, MqttReasonCodes.WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED);
+    }
+
+}
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuthTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuthTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuthTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuthTest.java
index 546570ba3..ddf6b43ba 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/auth/MqttAuthTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/auth/MqttAuthTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth;
+package com.hivemq.client2.internal.mqtt.message.auth;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/auth/MqttEnhancedAuthTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/auth/MqttEnhancedAuthTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/auth/MqttEnhancedAuthTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/auth/MqttEnhancedAuthTest.java
index 7190eda04..0a2f7c776 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/auth/MqttEnhancedAuthTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/auth/MqttEnhancedAuthTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth;
+package com.hivemq.client2.internal.mqtt.message.auth;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/auth/MqttSimpleAuthTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/auth/MqttSimpleAuthTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/auth/MqttSimpleAuthTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/auth/MqttSimpleAuthTest.java
index e8dc20414..d8e35cb13 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/auth/MqttSimpleAuthTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/auth/MqttSimpleAuthTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth;
+package com.hivemq.client2.internal.mqtt.message.auth;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewTest.java
index 6b8a3df73..cac87f291 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/auth/mqtt3/Mqtt3SimpleAuthViewTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.auth.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.auth.mqtt3;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckRestrictionsTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckRestrictionsTest.java
similarity index 94%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckRestrictionsTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckRestrictionsTest.java
index 7f65e768f..2742d2ae1 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckRestrictionsTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckRestrictionsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect.connack;
+package com.hivemq.client2.internal.mqtt.message.connect;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckTest.java
similarity index 94%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckTest.java
index fb577f944..95522cbdd 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/connack/MqttConnAckTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnAckTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect.connack;
+package com.hivemq.client2.internal.mqtt.message.connect;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectRestrictionsTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectRestrictionsTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectRestrictionsTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectRestrictionsTest.java
index 6b58281da..c57b4ec17 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectRestrictionsTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectRestrictionsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect;
+package com.hivemq.client2.internal.mqtt.message.connect;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectTest.java
index 304adab2c..af42ffea5 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/MqttConnectTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/MqttConnectTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect;
+package com.hivemq.client2.internal.mqtt.message.connect;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/connack/mqtt3/Mqtt3ConnAckViewTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnAckViewTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/connect/connack/mqtt3/Mqtt3ConnAckViewTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnAckViewTest.java
index 200a1924c..dfd974275 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/connack/mqtt3/Mqtt3ConnAckViewTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnAckViewTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect.connack.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.connect.mqtt3;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewTest.java
index a0aab8591..d6e8519d2 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/connect/mqtt3/Mqtt3ConnectViewTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.connect.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.connect.mqtt3;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnectTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnectTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnectTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnectTest.java
index cc9f009b6..cdddc1276 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/disconnect/MqttDisconnectTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/disconnect/MqttDisconnectTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.disconnect;
+package com.hivemq.client2.internal.mqtt.message.disconnect;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAckTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAckTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAckTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAckTest.java
index 49568c168..824444218 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/puback/MqttPubAckTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubAckTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.puback;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubCompTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubCompTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubCompTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubCompTest.java
index 21f5e367c..218b049b5 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/pubcomp/MqttPubCompTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubCompTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubcomp;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRecTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRecTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRecTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRecTest.java
index 856bbdb92..b579fdb60 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/pubrec/MqttPubRecTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRecTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubrec;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRelTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRelTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRelTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRelTest.java
index f8dbf11a7..3fbf4a757 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/pubrel/MqttPubRelTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPubRelTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.pubrel;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishResultTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishResultTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishResultTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishResultTest.java
index 185055edd..df7cfe98b 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishResultTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishResultTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishTest.java
index e7476e828..19f701d5e 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/MqttPublishTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttPublishTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import org.jetbrains.annotations.NotNull;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/MqttWillPublishTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttWillPublishTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/publish/MqttWillPublishTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttWillPublishTest.java
index d43bce5c6..e0a20c9b1 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/MqttWillPublishTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/MqttWillPublishTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish;
+package com.hivemq.client2.internal.mqtt.message.publish;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultViewTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultViewTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultViewTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultViewTest.java
index cb448fd25..f767e4e13 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultViewTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishResultViewTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.publish.mqtt3;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewTest.java
similarity index 90%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewTest.java
index 177bd0aa1..eb1b03042 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/publish/mqtt3/Mqtt3PublishViewTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.publish.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.publish.mqtt3;
 
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublish;
-import com.hivemq.client.internal.mqtt.message.publish.MqttPublishBuilder;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublish;
+import com.hivemq.client2.internal.mqtt.message.publish.MqttPublishBuilder;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/MqttSubAckTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubAckTest.java
similarity index 94%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/MqttSubAckTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubAckTest.java
index 8cf1d9f68..e9e3b0ba8 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/MqttSubAckTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubAckTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.suback;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeBuilderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeBuilderTest.java
similarity index 90%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeBuilderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeBuilderTest.java
index f17efb344..48dabb4ee 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeBuilderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeBuilderTest.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe;
-
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscription;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
+
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5RetainHandling;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5Subscription;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
 
@@ -61,7 +61,7 @@ void addSubscription_correct_subscription_default_properties() {
         final Mqtt5Subscription mqtt5Subscription = subscriptions.get(0);
 
         assertEquals("test", mqtt5Subscription.getTopicFilter().toString());
-        assertEquals(MqttQos.EXACTLY_ONCE, mqtt5Subscription.getQos());
+        assertEquals(MqttQos.EXACTLY_ONCE, mqtt5Subscription.getMaxQos());
         assertFalse(mqtt5Subscription.isNoLocal());
         assertFalse(mqtt5Subscription.isRetainAsPublished());
         assertEquals(Mqtt5RetainHandling.SEND, mqtt5Subscription.getRetainHandling());
@@ -72,7 +72,7 @@ void addSubscription_correct_subscription_custom_properties() {
 
         final Mqtt5Subscription subscription = Mqtt5Subscription.builder()
                 .topicFilter("test")
-                .qos(MqttQos.AT_LEAST_ONCE)
+                .maxQos(MqttQos.AT_LEAST_ONCE)
                 .noLocal(true)
                 .retainAsPublished(true)
                 .retainHandling(Mqtt5RetainHandling.DO_NOT_SEND)
@@ -86,7 +86,7 @@ void addSubscription_correct_subscription_custom_properties() {
         final Mqtt5Subscription mqtt5Subscription = subscriptions.get(0);
 
         assertEquals("test", mqtt5Subscription.getTopicFilter().toString());
-        assertEquals(MqttQos.AT_LEAST_ONCE, mqtt5Subscription.getQos());
+        assertEquals(MqttQos.AT_LEAST_ONCE, mqtt5Subscription.getMaxQos());
         assertTrue(mqtt5Subscription.isNoLocal());
         assertTrue(mqtt5Subscription.isRetainAsPublished());
         assertEquals(Mqtt5RetainHandling.DO_NOT_SEND, mqtt5Subscription.getRetainHandling());
@@ -96,7 +96,7 @@ void addSubscription_correct_subscription_custom_properties() {
     void addSubscription_fluent_subscription_is_finished_if_addSubscription_is_used() {
 
         final Mqtt5Subscription subscription =
-                Mqtt5Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt5SubscribeBuilder.Start subscribeBuilder = Mqtt5Subscribe.builder();
         subscribeBuilder.topicFilter("fluent");
@@ -112,10 +112,10 @@ void addSubscription_fluent_subscription_is_finished_if_addSubscription_is_used(
     void addSubscription_fluent_subscription_is_finished_if_addSubscription_is_used_second_time() {
 
         final Mqtt5Subscription subscription =
-                Mqtt5Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt5Subscription subscription2 =
-                Mqtt5Subscription.builder().topicFilter("test2").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test2").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt5SubscribeBuilder.Start subscribeBuilder = Mqtt5Subscribe.builder();
         subscribeBuilder.topicFilter("fluent");
@@ -137,7 +137,7 @@ void addSubscription_fluent_subscription_is_finished_if_fluent_addSubscription_i
 
         final Mqtt5SubscribeBuilder.Complete subscribeBuilder = Mqtt5Subscribe.builder().topicFilter("fluent");
         final Mqtt5Subscribe mqtt5Subscribe =
-                subscribeBuilder.addSubscription().topicFilter("test").applySubscription().build();
+                subscribeBuilder.addSubscriptionWith().topicFilter("test").applySubscription().build();
 
         final List<? extends Mqtt5Subscription> subscriptions = mqtt5Subscribe.getSubscriptions();
         assertEquals(2, subscriptions.size());
@@ -171,7 +171,7 @@ void addSubscriptions_error_when_list_is_empty() {
     void addSubscriptions_error_when_subscription_is_implemented() {
 
         final Mqtt5Subscription subscription =
-                Mqtt5Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final List<Mqtt5Subscription> subscriptions = new ArrayList<>();
         subscriptions.add(subscription);
@@ -185,13 +185,13 @@ void addSubscriptions_error_when_subscription_is_implemented() {
     void addSubscriptions_correct_use_list() {
 
         final Mqtt5Subscription subscription =
-                Mqtt5Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt5Subscription subscription2 =
-                Mqtt5Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt5Subscription subscription3 =
-                Mqtt5Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final List<Mqtt5Subscription> subscriptions = new ArrayList<>();
         subscriptions.add(subscription);
@@ -211,13 +211,13 @@ void addSubscriptions_correct_use_list() {
     void addSubscriptions_correct_use_set() {
 
         final Mqtt5Subscription subscription =
-                Mqtt5Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt5Subscription subscription2 =
-                Mqtt5Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt5Subscription subscription3 =
-                Mqtt5Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final Set<Mqtt5Subscription> subscriptions = new HashSet<>();
         subscriptions.add(subscription);
@@ -233,13 +233,13 @@ void addSubscriptions_correct_use_set() {
     void addSubscriptions_correct_use_map() {
 
         final Mqtt5Subscription subscription =
-                Mqtt5Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt5Subscription subscription2 =
-                Mqtt5Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt5Subscription subscription3 =
-                Mqtt5Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final Map<String, Mqtt5Subscription> subscriptions = new LinkedHashMap<>();
         subscriptions.put("1", subscription);
@@ -255,13 +255,13 @@ void addSubscriptions_correct_use_map() {
     void addSubscriptions_correct_use_array() {
 
         final Mqtt5Subscription subscription =
-                Mqtt5Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt5Subscription subscription2 =
-                Mqtt5Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt5Subscription subscription3 =
-                Mqtt5Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final Mqtt5Subscription[] subscriptions = new Mqtt5Subscription[]{
                 subscription, subscription2, subscription3
@@ -284,7 +284,7 @@ void addSubscriptions_correct_use_stream() {
                 .addSubscriptions(subscriptions.stream()
                         .map(topicFilter -> Mqtt5Subscription.builder()
                                 .topicFilter(topicFilter)
-                                .qos(MqttQos.AT_LEAST_ONCE)
+                                .maxQos(MqttQos.AT_LEAST_ONCE)
                                 .build()))
                 .build();
 
@@ -299,13 +299,13 @@ void addSubscriptions_correct_use_stream() {
     void addSubscriptions_fluent_subscription_is_finished_if_addSubscriptions_is_used() {
 
         final Mqtt5Subscription subscription =
-                Mqtt5Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt5Subscription subscription2 =
-                Mqtt5Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt5Subscription subscription3 =
-                Mqtt5Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final ImmutableList<Mqtt5Subscription> subscriptions =
                 ImmutableList.of(subscription, subscription2, subscription3);
@@ -326,13 +326,13 @@ void addSubscriptions_fluent_subscription_is_finished_if_addSubscriptions_is_use
     void addSubscriptions_fluent_subscription_is_finished_if_addSubscriptions_is_used_second_time() {
 
         final Mqtt5Subscription subscription =
-                Mqtt5Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt5Subscription subscription2 =
-                Mqtt5Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt5Subscription subscription3 =
-                Mqtt5Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final List<Mqtt5Subscription> subscriptions = new LinkedList<>();
         subscriptions.add(subscription);
@@ -360,13 +360,13 @@ void addSubscriptions_fluent_subscription_is_finished_if_addSubscriptions_is_use
     void addSubscriptions_fluent_subscription_and_addSubscription() {
 
         final Mqtt5Subscription subscription =
-                Mqtt5Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt5Subscription subscription2 =
-                Mqtt5Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt5Subscription subscription3 =
-                Mqtt5Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt5Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final List<Mqtt5Subscription> subscriptions = new ArrayList<>();
         subscriptions.add(subscription);
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeTest.java
index d4e44bfc7..33d61ce7d 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscribeTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscribeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscriptionTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscriptionTest.java
similarity index 89%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscriptionTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscriptionTest.java
index 562b52632..899d3efcc 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/MqttSubscriptionTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/MqttSubscriptionTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe;
+package com.hivemq.client2.internal.mqtt.message.subscribe;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -30,7 +30,7 @@ class MqttSubscriptionTest {
     void equals() {
         EqualsVerifier.forClass(MqttSubscription.class)
                 .withIgnoredAnnotations(NotNull.class) // EqualsVerifier thinks @NotNull Optional is @NotNull
-                .withNonnullFields("topicFilter", "qos", "retainHandling")
+                .withNonnullFields("topicFilter", "maxQos", "retainHandling")
                 .suppress(Warning.STRICT_INHERITANCE)
                 .verify();
     }
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/mqtt3/Mqtt3SubAckViewTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubAckViewTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/mqtt3/Mqtt3SubAckViewTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubAckViewTest.java
index 94a3b0f21..1f0e54cd2 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/suback/mqtt3/Mqtt3SubAckViewTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubAckViewTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.suback.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilderTest.java
similarity index 90%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilderTest.java
index c2e1ffae3..8955a4615 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewBuilderTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3;
 
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
 
@@ -60,14 +60,14 @@ void addSubscription_correct_subscription_default_properties() {
         final Mqtt3Subscription mqtt3Subscription = subscriptions.get(0);
 
         assertEquals("test", mqtt3Subscription.getTopicFilter().toString());
-        assertEquals(MqttQos.EXACTLY_ONCE, mqtt3Subscription.getQos());
+        assertEquals(MqttQos.EXACTLY_ONCE, mqtt3Subscription.getMaxQos());
     }
 
     @Test
     void addSubscription_correct_subscription_custom_properties() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt3Subscribe subscribe = Mqtt3Subscribe.builder().addSubscription(subscription).build();
 
@@ -77,14 +77,14 @@ void addSubscription_correct_subscription_custom_properties() {
         final Mqtt3Subscription mqtt3Subscription = subscriptions.get(0);
 
         assertEquals("test", mqtt3Subscription.getTopicFilter().toString());
-        assertEquals(MqttQos.AT_LEAST_ONCE, mqtt3Subscription.getQos());
+        assertEquals(MqttQos.AT_LEAST_ONCE, mqtt3Subscription.getMaxQos());
     }
 
     @Test
     void addSubscription_fluent_subscription_is_finished_if_addSubscription_is_used() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt3SubscribeBuilder.Start subscribeBuilder = Mqtt3Subscribe.builder();
         subscribeBuilder.topicFilter("fluent");
@@ -100,10 +100,10 @@ void addSubscription_fluent_subscription_is_finished_if_addSubscription_is_used(
     void addSubscription_fluent_subscription_is_finished_if_addSubscription_is_used_second_time() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt3Subscription subscription2 =
-                Mqtt3Subscription.builder().topicFilter("test2").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test2").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt3SubscribeBuilder.Start subscribeBuilder = Mqtt3Subscribe.builder();
         subscribeBuilder.topicFilter("fluent");
@@ -125,7 +125,7 @@ void addSubscription_fluent_subscription_is_finished_if_fluent_addSubscription_i
 
         final Mqtt3SubscribeBuilder.Complete subscribeBuilder = Mqtt3Subscribe.builder().topicFilter("fluent");
         final Mqtt3Subscribe Mqtt3Subscribe =
-                subscribeBuilder.addSubscription().topicFilter("test").applySubscription().build();
+                subscribeBuilder.addSubscriptionWith().topicFilter("test").applySubscription().build();
 
         final List<? extends Mqtt3Subscription> subscriptions = Mqtt3Subscribe.getSubscriptions();
         assertEquals(2, subscriptions.size());
@@ -159,7 +159,7 @@ void addSubscriptions_error_when_list_is_empty() {
     void addSubscriptions_error_when_subscription_is_implemented() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final List<Mqtt3Subscription> subscriptions = new ArrayList<>();
         subscriptions.add(subscription);
@@ -173,13 +173,13 @@ void addSubscriptions_error_when_subscription_is_implemented() {
     void addSubscriptions_correct_use_list() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt3Subscription subscription2 =
-                Mqtt3Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt3Subscription subscription3 =
-                Mqtt3Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final List<Mqtt3Subscription> subscriptions = new ArrayList<>();
         subscriptions.add(subscription);
@@ -195,13 +195,13 @@ void addSubscriptions_correct_use_list() {
     void addSubscriptions_correct_use_set() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt3Subscription subscription2 =
-                Mqtt3Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt3Subscription subscription3 =
-                Mqtt3Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final Set<Mqtt3Subscription> subscriptions = new HashSet<>();
         subscriptions.add(subscription);
@@ -217,13 +217,13 @@ void addSubscriptions_correct_use_set() {
     void addSubscriptions_correct_use_map() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt3Subscription subscription2 =
-                Mqtt3Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt3Subscription subscription3 =
-                Mqtt3Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final Map<String, Mqtt3Subscription> subscriptions = new LinkedHashMap<>();
         subscriptions.put("1", subscription);
@@ -239,13 +239,13 @@ void addSubscriptions_correct_use_map() {
     void addSubscriptions_correct_use_array() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt3Subscription subscription2 =
-                Mqtt3Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt3Subscription subscription3 =
-                Mqtt3Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final Mqtt3Subscription[] subscriptions = new Mqtt3Subscription[]{
                 subscription, subscription2, subscription3
@@ -268,7 +268,7 @@ void addSubscriptions_correct_use_stream() {
                 .addSubscriptions(subscriptions.stream()
                         .map(topicFilter -> Mqtt3Subscription.builder()
                                 .topicFilter(topicFilter)
-                                .qos(MqttQos.AT_LEAST_ONCE)
+                                .maxQos(MqttQos.AT_LEAST_ONCE)
                                 .build()))
                 .build();
 
@@ -283,13 +283,13 @@ void addSubscriptions_correct_use_stream() {
     void addSubscriptions_fluent_subscription_is_finished_if_addSubscriptions_is_used() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt3Subscription subscription2 =
-                Mqtt3Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt3Subscription subscription3 =
-                Mqtt3Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final List<Mqtt3Subscription> subscriptions = new ArrayList<>();
         subscriptions.add(subscription);
@@ -312,13 +312,13 @@ void addSubscriptions_fluent_subscription_is_finished_if_addSubscriptions_is_use
     void addSubscriptions_fluent_subscription_is_finished_if_addSubscriptions_is_used_second_time() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt3Subscription subscription2 =
-                Mqtt3Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt3Subscription subscription3 =
-                Mqtt3Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final ImmutableList<Mqtt3Subscription> subscriptions = ImmutableList.of(subscription, subscription2);
 
@@ -344,13 +344,13 @@ void addSubscriptions_fluent_subscription_is_finished_if_addSubscriptions_is_use
     void addSubscriptions_fluent_subscription_and_addSubscription() {
 
         final Mqtt3Subscription subscription =
-                Mqtt3Subscription.builder().topicFilter("test").qos(MqttQos.AT_LEAST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("test").maxQos(MqttQos.AT_LEAST_ONCE).build();
 
         final Mqtt3Subscription subscription2 =
-                Mqtt3Subscription.builder().topicFilter("multiple").qos(MqttQos.AT_MOST_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("multiple").maxQos(MqttQos.AT_MOST_ONCE).build();
 
         final Mqtt3Subscription subscription3 =
-                Mqtt3Subscription.builder().topicFilter("subscriptions").qos(MqttQos.EXACTLY_ONCE).build();
+                Mqtt3Subscription.builder().topicFilter("subscriptions").maxQos(MqttQos.EXACTLY_ONCE).build();
 
         final List<Mqtt3Subscription> subscriptions = new LinkedList<>();
         subscriptions.add(subscription);
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewTest.java
index a13cccbbd..735d066bf 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscribeViewTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewTest.java
index 59868c9fb..d397fd6db 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/subscribe/mqtt3/Mqtt3SubscriptionViewTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.subscribe.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.subscribe.mqtt3;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/MqttUnsubAckTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubAckTest.java
similarity index 88%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/MqttUnsubAckTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubAckTest.java
index 4f3c2c7aa..eb5965d2b 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/unsuback/MqttUnsubAckTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubAckTest.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe.unsuback;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe;
 
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertyImpl;
-import com.hivemq.client.internal.mqtt.datatypes.MqttUtf8StringImpl;
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAckReasonCode;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertyImpl;
+import com.hivemq.client2.internal.mqtt.datatypes.MqttUtf8StringImpl;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAckReasonCode;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
 
-import static com.hivemq.client.internal.mqtt.datatypes.MqttUserPropertiesImpl.NO_USER_PROPERTIES;
+import static com.hivemq.client2.internal.mqtt.datatypes.MqttUserPropertiesImpl.NO_USER_PROPERTIES;
 import static org.junit.jupiter.api.Assertions.*;
 
 /**
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilderTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilderTest.java
index c04731cd2..343f11d7f 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeBuilderTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe;
 
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe;
 import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;
@@ -95,7 +95,7 @@ void addTopicFilter_fluent_topic_is_finished_if_addTopicFilter_is_used_string()
     void addTopicFilter_nested_topic_builder_is_used_with_and_then_addTopicFilter_mqtttopic() {
 
         final Mqtt5Unsubscribe subscribe = Mqtt5Unsubscribe.builder()
-                .topicFilter()
+                .topicFilterWith()
                 .addLevel("first")
                 .addLevel("second")
                 .multiLevelWildcard()
@@ -114,7 +114,7 @@ void addTopicFilter_nested_topic_builder_is_used_with_and_then_addTopicFilter_mq
     void addTopicFilter_nested_topic_builder_is_used_and_then_addTopicFilter_string() {
 
         final Mqtt5Unsubscribe subscribe = Mqtt5Unsubscribe.builder()
-                .topicFilter()
+                .topicFilterWith()
                 .addLevel("first")
                 .addLevel("second")
                 .multiLevelWildcard()
@@ -135,7 +135,7 @@ void addTopicFilter_fluent_topic_is_finished_if_addTopicFilter_is_used_second_ti
         final Mqtt5Unsubscribe subscribe = Mqtt5Unsubscribe.builder()
                 .topicFilter("test")
                 .addTopicFilter(MqttTopicFilter.of("firstAdd"))
-                .addTopicFilter()
+                .addTopicFilterWith()
                 .addLevel("nested")
                 .applyTopicFilter()
                 .addTopicFilter(MqttTopicFilter.of("secondAdd"))
@@ -156,7 +156,7 @@ void addTopicFilter_fluent_topic_is_finished_if_addTopicFilter_is_used_second_ti
         final Mqtt5Unsubscribe subscribe = Mqtt5Unsubscribe.builder()
                 .topicFilter("test")
                 .addTopicFilter("firstAdd")
-                .addTopicFilter()
+                .addTopicFilterWith()
                 .addLevel("nested")
                 .applyTopicFilter()
                 .addTopicFilter("secondAdd")
@@ -176,7 +176,7 @@ void addTopicFilter_fluent_topic_is_finished_if_fluent_addTopicFilter_is_used()
 
         final Mqtt5Unsubscribe subscribe = Mqtt5Unsubscribe.builder()
                 .topicFilter("test")
-                .addTopicFilter()
+                .addTopicFilterWith()
                 .addLevel("first")
                 .addLevel("second")
                 .multiLevelWildcard()
@@ -323,7 +323,7 @@ void addTopicFilters_nested_topic_builder_is_used_and_then_addTopicFilters() {
                 ImmutableList.of(MqttTopicFilter.of("test"), MqttTopicFilter.of("list"), MqttTopicFilter.of("element"));
 
         final Mqtt5Unsubscribe subscribe = Mqtt5Unsubscribe.builder()
-                .topicFilter()
+                .topicFilterWith()
                 .addLevel("first")
                 .addLevel("second")
                 .multiLevelWildcard()
@@ -350,7 +350,7 @@ void addTopicFilters_fluent_topic_is_finished_if_addTopicFilters_is_used_second_
         final Mqtt5Unsubscribe subscribe = Mqtt5Unsubscribe.builder()
                 .topicFilter("fluent")
                 .addTopicFilters(topics)
-                .addTopicFilter()
+                .addTopicFilterWith()
                 .addLevel("nested")
                 .applyTopicFilter()
                 .addTopicFilters(topics2)
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeTest.java
index b087061c9..7c8f9f7a2 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/MqttUnsubscribeTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/MqttUnsubscribeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilderTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilderTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilderTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilderTest.java
index b59475d83..f68ed83ad 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilderTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewBuilderTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3;
 
-import com.hivemq.client.internal.util.collections.ImmutableList;
-import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
+import com.hivemq.client2.mqtt.datatypes.MqttTopicFilter;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
 import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;
@@ -95,7 +95,7 @@ void addTopicFilter_fluent_topic_is_finished_if_addTopicFilter_is_used_string()
     void addTopicFilter_nested_topic_builder_is_used_with_and_then_addTopicFilter_mqtttopic() {
 
         final Mqtt3Unsubscribe subscribe = Mqtt3Unsubscribe.builder()
-                .topicFilter()
+                .topicFilterWith()
                 .addLevel("first")
                 .addLevel("second")
                 .multiLevelWildcard()
@@ -114,7 +114,7 @@ void addTopicFilter_nested_topic_builder_is_used_with_and_then_addTopicFilter_mq
     void addTopicFilter_nested_topic_builder_is_used_and_then_addTopicFilter_string() {
 
         final Mqtt3Unsubscribe subscribe = Mqtt3Unsubscribe.builder()
-                .topicFilter()
+                .topicFilterWith()
                 .addLevel("first")
                 .addLevel("second")
                 .multiLevelWildcard()
@@ -135,7 +135,7 @@ void addTopicFilter_fluent_topic_is_finished_if_addTopicFilter_is_used_second_ti
         final Mqtt3Unsubscribe subscribe = Mqtt3Unsubscribe.builder()
                 .topicFilter("test")
                 .addTopicFilter(MqttTopicFilter.of("firstAdd"))
-                .addTopicFilter()
+                .addTopicFilterWith()
                 .addLevel("nested")
                 .applyTopicFilter()
                 .addTopicFilter(MqttTopicFilter.of("secondAdd"))
@@ -156,7 +156,7 @@ void addTopicFilter_fluent_topic_is_finished_if_addTopicFilter_is_used_second_ti
         final Mqtt3Unsubscribe subscribe = Mqtt3Unsubscribe.builder()
                 .topicFilter("test")
                 .addTopicFilter("firstAdd")
-                .addTopicFilter()
+                .addTopicFilterWith()
                 .addLevel("nested")
                 .applyTopicFilter()
                 .addTopicFilter("secondAdd")
@@ -176,7 +176,7 @@ void addTopicFilter_fluent_topic_is_finished_if_fluent_addTopicFilter_is_used()
 
         final Mqtt3Unsubscribe subscribe = Mqtt3Unsubscribe.builder()
                 .topicFilter("test")
-                .addTopicFilter()
+                .addTopicFilterWith()
                 .addLevel("first")
                 .addLevel("second")
                 .multiLevelWildcard()
@@ -323,7 +323,7 @@ void addTopicFilters_nested_topic_builder_is_used_and_then_addTopicFilters() {
                 ImmutableList.of(MqttTopicFilter.of("test"), MqttTopicFilter.of("list"), MqttTopicFilter.of("element"));
 
         final Mqtt3Unsubscribe subscribe = Mqtt3Unsubscribe.builder()
-                .topicFilter()
+                .topicFilterWith()
                 .addLevel("first")
                 .addLevel("second")
                 .multiLevelWildcard()
@@ -350,7 +350,7 @@ void addTopicFilters_fluent_topic_is_finished_if_addTopicFilters_is_used_second_
         final Mqtt3Unsubscribe subscribe = Mqtt3Unsubscribe.builder()
                 .topicFilter("fluent")
                 .addTopicFilters(topics)
-                .addTopicFilter()
+                .addTopicFilterWith()
                 .addLevel("nested")
                 .applyTopicFilter()
                 .addTopicFilters(topics2)
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewTest.java
similarity index 93%
rename from src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewTest.java
index 482e9daa6..a72cf1e4b 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/message/unsubscribe/mqtt3/Mqtt3UnsubscribeViewTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.message.unsubscribe.mqtt3;
+package com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
diff --git a/src/test/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3RxClientViewExceptionsTest.java b/src/test/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3RxClientViewExceptionsTest.java
similarity index 79%
rename from src/test/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3RxClientViewExceptionsTest.java
rename to src/test/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3RxClientViewExceptionsTest.java
index 1b2a9fb41..bef53e522 100644
--- a/src/test/java/com/hivemq/client/internal/mqtt/mqtt3/Mqtt3RxClientViewExceptionsTest.java
+++ b/src/test/java/com/hivemq/client2/internal/mqtt/mqtt3/Mqtt3RxClientViewExceptionsTest.java
@@ -14,27 +14,27 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.mqtt.mqtt3;
-
-import com.hivemq.client.internal.mqtt.MqttClientConfig;
-import com.hivemq.client.internal.mqtt.MqttRxClient;
-import com.hivemq.client.internal.mqtt.message.disconnect.MqttDisconnect;
-import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
-import com.hivemq.client.mqtt.datatypes.MqttQos;
-import com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3MessageException;
-import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect;
-import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
-import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5DisconnectException;
-import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5MessageException;
-import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
-import com.hivemq.client.rx.FlowableWithSingleSplit;
-import io.reactivex.Completable;
-import io.reactivex.Flowable;
-import io.reactivex.Single;
+package com.hivemq.client2.internal.mqtt.mqtt3;
+
+import com.hivemq.client2.internal.mqtt.MqttClientConfig;
+import com.hivemq.client2.internal.mqtt.MqttRxClient;
+import com.hivemq.client2.internal.mqtt.message.disconnect.MqttDisconnect;
+import com.hivemq.client2.mqtt.MqttGlobalPublishFilter;
+import com.hivemq.client2.mqtt.datatypes.MqttQos;
+import com.hivemq.client2.mqtt.mqtt3.exceptions.Mqtt3MessageException;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect;
+import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscription;
+import com.hivemq.client2.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5DisconnectException;
+import com.hivemq.client2.mqtt.mqtt5.exceptions.Mqtt5MessageException;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5Publish;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
+import com.hivemq.client2.rx.FlowableWithSingleSplit;
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.Single;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -78,7 +78,7 @@ void subscribe() {
         given(mqtt5Client.subscribe(any())).willReturn(Single.error(mqtt5MessageException));
 
         final Mqtt3Subscribe subscribe = Mqtt3Subscribe.builder()
-                .addSubscription(Mqtt3Subscription.builder().topicFilter("topic").qos(MqttQos.AT_LEAST_ONCE).build())
+                .addSubscription(Mqtt3Subscription.builder().topicFilter("topic").maxQos(MqttQos.AT_LEAST_ONCE).build())
                 .build();
         assertMqtt3Exception(() -> mqtt3Client.subscribe(subscribe).ignoreElement().blockingAwait(),
                 mqtt5MessageException);
@@ -93,7 +93,7 @@ void subscribeWithStream() {
                         Mqtt5SubAck.class));
 
         final Mqtt3Subscribe subscribe = Mqtt3Subscribe.builder()
-                .addSubscription(Mqtt3Subscription.builder().topicFilter("topic").qos(MqttQos.AT_LEAST_ONCE).build())
+                .addSubscription(Mqtt3Subscription.builder().topicFilter("topic").maxQos(MqttQos.AT_LEAST_ONCE).build())
                 .build();
         assertMqtt3Exception(
                 () -> mqtt3Client.subscribePublishes(subscribe, false).blockingSubscribe(), mqtt5MessageException);
@@ -116,7 +116,8 @@ void unsubscribe() {
         given(mqtt5Client.unsubscribe(any())).willReturn(Single.error(mqtt5MessageException));
 
         final Mqtt3Unsubscribe unsubscribe = Mqtt3Unsubscribe.builder().addTopicFilter("topic").build();
-        assertMqtt3Exception(() -> mqtt3Client.unsubscribe(unsubscribe).blockingAwait(), mqtt5MessageException);
+        assertMqtt3Exception(
+                () -> mqtt3Client.unsubscribe(unsubscribe).ignoreElement().blockingAwait(), mqtt5MessageException);
     }
 
     @Test
diff --git a/src/test/java/com/hivemq/client/internal/util/AsyncRuntimeExceptionTest.java b/src/test/java/com/hivemq/client2/internal/util/AsyncRuntimeExceptionTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/util/AsyncRuntimeExceptionTest.java
rename to src/test/java/com/hivemq/client2/internal/util/AsyncRuntimeExceptionTest.java
index 91350fa8b..56962ebd4 100644
--- a/src/test/java/com/hivemq/client/internal/util/AsyncRuntimeExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/AsyncRuntimeExceptionTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/test/java/com/hivemq/client/internal/util/ByteArrayTest.java b/src/test/java/com/hivemq/client2/internal/util/ByteArrayTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/internal/util/ByteArrayTest.java
rename to src/test/java/com/hivemq/client2/internal/util/ByteArrayTest.java
index 5bfacc162..652c9e35c 100644
--- a/src/test/java/com/hivemq/client/internal/util/ByteArrayTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/ByteArrayTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/util/ByteArrayUtilTest.java b/src/test/java/com/hivemq/client2/internal/util/ByteArrayUtilTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/util/ByteArrayUtilTest.java
rename to src/test/java/com/hivemq/client2/internal/util/ByteArrayUtilTest.java
index a36222f0c..64c62e5bf 100644
--- a/src/test/java/com/hivemq/client/internal/util/ByteArrayUtilTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/ByteArrayUtilTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/internal/util/ByteBufferUtilTest.java b/src/test/java/com/hivemq/client2/internal/util/ByteBufferUtilTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/util/ByteBufferUtilTest.java
rename to src/test/java/com/hivemq/client2/internal/util/ByteBufferUtilTest.java
index 4f14038f3..e47878b48 100644
--- a/src/test/java/com/hivemq/client/internal/util/ByteBufferUtilTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/ByteBufferUtilTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/internal/util/ChecksTest.java b/src/test/java/com/hivemq/client2/internal/util/ChecksTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/util/ChecksTest.java
rename to src/test/java/com/hivemq/client2/internal/util/ChecksTest.java
index ce04afb80..31f2939dd 100644
--- a/src/test/java/com/hivemq/client/internal/util/ChecksTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/ChecksTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
-import com.hivemq.client.internal.util.collections.ImmutableList;
+import com.hivemq.client2.internal.util.collections.ImmutableList;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
@@ -75,7 +75,7 @@ void notImplemented_otherImpl() {
         final IllegalArgumentException exception =
                 assertThrows(IllegalArgumentException.class, () -> Checks.notImplemented(o, Impl.class, "test-name"));
         assertEquals(
-                "test-name must not be implemented by the user, but was implemented by com.hivemq.client.internal.util.ChecksTest$OtherImpl.",
+                "test-name must not be implemented by the user, but was implemented by com.hivemq.client2.internal.util.ChecksTest$OtherImpl.",
                 exception.getMessage());
     }
 
@@ -99,7 +99,7 @@ void notImplementedOrNull_otherImpl() {
         final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
                 () -> Checks.notImplementedOrNull(o, Impl.class, "test-name"));
         assertEquals(
-                "test-name must not be implemented by the user, but was implemented by com.hivemq.client.internal.util.ChecksTest$OtherImpl.",
+                "test-name must not be implemented by the user, but was implemented by com.hivemq.client2.internal.util.ChecksTest$OtherImpl.",
                 exception.getMessage());
     }
 
@@ -155,7 +155,7 @@ void elementsNotImplemented_otherImpl() {
         final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
                 () -> Checks.elementsNotImplemented(o, Impl.class, "test-name"));
         assertEquals(
-                "test-name must not be implemented by the user, but was implemented by com.hivemq.client.internal.util.ChecksTest$OtherImpl.",
+                "test-name must not be implemented by the user, but was implemented by com.hivemq.client2.internal.util.ChecksTest$OtherImpl.",
                 exception.getMessage());
     }
 
diff --git a/src/test/java/com/hivemq/client/internal/util/ClassUtilTest.java b/src/test/java/com/hivemq/client2/internal/util/ClassUtilTest.java
similarity index 82%
rename from src/test/java/com/hivemq/client/internal/util/ClassUtilTest.java
rename to src/test/java/com/hivemq/client2/internal/util/ClassUtilTest.java
index 0830dda2f..5f6600aa6 100644
--- a/src/test/java/com/hivemq/client/internal/util/ClassUtilTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/ClassUtilTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.junit.jupiter.api.Test;
 
@@ -29,11 +29,11 @@ class ClassUtilTest {
     @Test
     void isAvailable_true() {
         assertTrue(ClassUtil.isAvailable("java.lang.String"));
-        assertTrue(ClassUtil.isAvailable("com.hivemq.client.internal.util.ClassUtilTest"));
+        assertTrue(ClassUtil.isAvailable("com.hivemq.client2.internal.util.ClassUtilTest"));
     }
 
     @Test
     void isAvailable_unknownClass() {
-        assertFalse(ClassUtil.isAvailable("com.hivemq.client.UnknownClass"));
+        assertFalse(ClassUtil.isAvailable("com.hivemq.client2.UnknownClass"));
     }
 }
\ No newline at end of file
diff --git a/src/test/java/com/hivemq/client/internal/util/ExecutorUtilTest.java b/src/test/java/com/hivemq/client2/internal/util/ExecutorUtilTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/util/ExecutorUtilTest.java
rename to src/test/java/com/hivemq/client2/internal/util/ExecutorUtilTest.java
index 7ba2dbbd1..1d66eafc0 100644
--- a/src/test/java/com/hivemq/client/internal/util/ExecutorUtilTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/ExecutorUtilTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/internal/util/Pow2UtilTest.java b/src/test/java/com/hivemq/client2/internal/util/Pow2UtilTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/internal/util/Pow2UtilTest.java
rename to src/test/java/com/hivemq/client2/internal/util/Pow2UtilTest.java
index 605800341..30813dadc 100644
--- a/src/test/java/com/hivemq/client/internal/util/Pow2UtilTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/Pow2UtilTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/internal/util/RangesTest.java b/src/test/java/com/hivemq/client2/internal/util/RangesTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/internal/util/RangesTest.java
rename to src/test/java/com/hivemq/client2/internal/util/RangesTest.java
index d9529db9a..2c349b5f5 100644
--- a/src/test/java/com/hivemq/client/internal/util/RangesTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/RangesTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/internal/util/StringUtilTest.java b/src/test/java/com/hivemq/client2/internal/util/StringUtilTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/util/StringUtilTest.java
rename to src/test/java/com/hivemq/client2/internal/util/StringUtilTest.java
index 54248a17c..fc5a63e2d 100644
--- a/src/test/java/com/hivemq/client/internal/util/StringUtilTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/StringUtilTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/internal/util/UnsignedDataTypesTest.java b/src/test/java/com/hivemq/client2/internal/util/UnsignedDataTypesTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/util/UnsignedDataTypesTest.java
rename to src/test/java/com/hivemq/client2/internal/util/UnsignedDataTypesTest.java
index 26b488d84..451398fe0 100644
--- a/src/test/java/com/hivemq/client/internal/util/UnsignedDataTypesTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/UnsignedDataTypesTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
diff --git a/src/test/java/com/hivemq/client/internal/util/Utf8UtilTest.java b/src/test/java/com/hivemq/client2/internal/util/Utf8UtilTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/util/Utf8UtilTest.java
rename to src/test/java/com/hivemq/client2/internal/util/Utf8UtilTest.java
index 06f557aee..ae14ec551 100644
--- a/src/test/java/com/hivemq/client/internal/util/Utf8UtilTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/Utf8UtilTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util;
+package com.hivemq.client2.internal.util;
 
 import com.google.common.base.Utf8;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/util/collections/ChunkedArrayQueueTest.java b/src/test/java/com/hivemq/client2/internal/util/collections/ChunkedArrayQueueTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/internal/util/collections/ChunkedArrayQueueTest.java
rename to src/test/java/com/hivemq/client2/internal/util/collections/ChunkedArrayQueueTest.java
index a4efc9550..798bb8ae5 100644
--- a/src/test/java/com/hivemq/client/internal/util/collections/ChunkedArrayQueueTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/collections/ChunkedArrayQueueTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/internal/util/collections/HandleListTest.java b/src/test/java/com/hivemq/client2/internal/util/collections/HandleListTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/internal/util/collections/HandleListTest.java
rename to src/test/java/com/hivemq/client2/internal/util/collections/HandleListTest.java
index d2cc66544..cc2fd8166 100644
--- a/src/test/java/com/hivemq/client/internal/util/collections/HandleListTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/collections/HandleListTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
-import com.hivemq.client.internal.util.collections.HandleList.Handle;
+import com.hivemq.client2.internal.util.collections.HandleList.Handle;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
diff --git a/src/test/java/com/hivemq/client/internal/util/collections/ImmutableIntListTest.java b/src/test/java/com/hivemq/client2/internal/util/collections/ImmutableIntListTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/util/collections/ImmutableIntListTest.java
rename to src/test/java/com/hivemq/client2/internal/util/collections/ImmutableIntListTest.java
index 26060539c..4d1c8233e 100644
--- a/src/test/java/com/hivemq/client/internal/util/collections/ImmutableIntListTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/collections/ImmutableIntListTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/util/collections/ImmutableListTest.java b/src/test/java/com/hivemq/client2/internal/util/collections/ImmutableListTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/util/collections/ImmutableListTest.java
rename to src/test/java/com/hivemq/client2/internal/util/collections/ImmutableListTest.java
index 7be22bdca..19d61826b 100644
--- a/src/test/java/com/hivemq/client/internal/util/collections/ImmutableListTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/collections/ImmutableListTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/internal/util/collections/IntIndexTest.java b/src/test/java/com/hivemq/client2/internal/util/collections/IntIndexTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/util/collections/IntIndexTest.java
rename to src/test/java/com/hivemq/client2/internal/util/collections/IntIndexTest.java
index ec707280e..a54cd7f3d 100644
--- a/src/test/java/com/hivemq/client/internal/util/collections/IntIndexTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/collections/IntIndexTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/src/test/java/com/hivemq/client/internal/util/collections/NodeListTest.java b/src/test/java/com/hivemq/client2/internal/util/collections/NodeListTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/internal/util/collections/NodeListTest.java
rename to src/test/java/com/hivemq/client2/internal/util/collections/NodeListTest.java
index c7268af27..021ab5baa 100644
--- a/src/test/java/com/hivemq/client/internal/util/collections/NodeListTest.java
+++ b/src/test/java/com/hivemq/client2/internal/util/collections/NodeListTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.internal.util.collections;
+package com.hivemq.client2.internal.util.collections;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/MqttClientStateTest.java b/src/test/java/com/hivemq/client2/mqtt/MqttClientStateTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/mqtt/MqttClientStateTest.java
rename to src/test/java/com/hivemq/client2/mqtt/MqttClientStateTest.java
index de81ec286..a2a220873 100644
--- a/src/test/java/com/hivemq/client/mqtt/MqttClientStateTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/MqttClientStateTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/hivemq/client/mqtt/MqttClientSslConfigBuilderTest.java b/src/test/java/com/hivemq/client2/mqtt/MqttTlsConfigBuilderTest.java
similarity index 52%
rename from src/test/java/com/hivemq/client/mqtt/MqttClientSslConfigBuilderTest.java
rename to src/test/java/com/hivemq/client2/mqtt/MqttTlsConfigBuilderTest.java
index 7ba5cfa13..064d62ac8 100644
--- a/src/test/java/com/hivemq/client/mqtt/MqttClientSslConfigBuilderTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/MqttTlsConfigBuilderTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt;
+package com.hivemq.client2.mqtt;
 
 import org.junit.jupiter.api.Test;
 
@@ -26,43 +26,43 @@
 /**
  * @author Christian Hoff
  */
-class MqttClientSslConfigBuilderTest {
+class MqttTlsConfigBuilderTest {
 
     @Test
     void cipherSuites_simple() {
         final List<String> expectedCipherSuites = Arrays.asList("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305");
 
-        final MqttClientSslConfig sslConfig = MqttClientSslConfig.builder().cipherSuites(expectedCipherSuites).build();
+        final MqttTlsConfig tlsConfig = MqttTlsConfig.builder().cipherSuites(expectedCipherSuites).build();
 
-        assertNotNull(sslConfig.getCipherSuites());
-        assertTrue(sslConfig.getCipherSuites().isPresent());
-        assertEquals(sslConfig.getCipherSuites().get(), expectedCipherSuites);
+        assertNotNull(tlsConfig.getCipherSuites());
+        assertTrue(tlsConfig.getCipherSuites().isPresent());
+        assertEquals(tlsConfig.getCipherSuites().get(), expectedCipherSuites);
     }
 
     @Test
     void cipherSuites_null() {
-        final MqttClientSslConfig sslConfig = MqttClientSslConfig.builder().cipherSuites(null).build();
+        final MqttTlsConfig tlsConfig = MqttTlsConfig.builder().cipherSuites(null).build();
 
-        assertNotNull(sslConfig.getCipherSuites());
-        assertFalse(sslConfig.getCipherSuites().isPresent());
+        assertNotNull(tlsConfig.getCipherSuites());
+        assertFalse(tlsConfig.getCipherSuites().isPresent());
     }
 
     @Test
     void protocols_simple() {
         final List<String> expectedProtocols = Arrays.asList("TLSv1.2", "TLSv1.1");
 
-        final MqttClientSslConfig sslConfig = MqttClientSslConfig.builder().protocols(expectedProtocols).build();
+        final MqttTlsConfig tlsConfig = MqttTlsConfig.builder().protocols(expectedProtocols).build();
 
-        assertNotNull(sslConfig.getProtocols());
-        assertTrue(sslConfig.getProtocols().isPresent());
-        assertEquals(sslConfig.getProtocols().get(), expectedProtocols);
+        assertNotNull(tlsConfig.getProtocols());
+        assertTrue(tlsConfig.getProtocols().isPresent());
+        assertEquals(tlsConfig.getProtocols().get(), expectedProtocols);
     }
 
     @Test
     void protocols_null() {
-        final MqttClientSslConfig sslConfig = MqttClientSslConfig.builder().protocols(null).build();
+        final MqttTlsConfig tlsConfig = MqttTlsConfig.builder().protocols(null).build();
 
-        assertNotNull(sslConfig.getProtocols());
-        assertFalse(sslConfig.getProtocols().isPresent());
+        assertNotNull(tlsConfig.getProtocols());
+        assertFalse(tlsConfig.getProtocols().isPresent());
     }
 }
diff --git a/src/test/java/com/hivemq/client/mqtt/datatypes/MqttQosTest.java b/src/test/java/com/hivemq/client2/mqtt/datatypes/MqttQosTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/mqtt/datatypes/MqttQosTest.java
rename to src/test/java/com/hivemq/client2/mqtt/datatypes/MqttQosTest.java
index afafa9442..4fd369bda 100644
--- a/src/test/java/com/hivemq/client/mqtt/datatypes/MqttQosTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/datatypes/MqttQosTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.datatypes;
+package com.hivemq.client2.mqtt.datatypes;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/mqtt/exceptions/ConnectionClosedExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/exceptions/ConnectionClosedExceptionTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/mqtt/exceptions/ConnectionClosedExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/exceptions/ConnectionClosedExceptionTest.java
index e27b0f678..53dd10783 100644
--- a/src/test/java/com/hivemq/client/mqtt/exceptions/ConnectionClosedExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/exceptions/ConnectionClosedExceptionTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/exceptions/ConnectionFailedExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/exceptions/ConnectionFailedExceptionTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/mqtt/exceptions/ConnectionFailedExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/exceptions/ConnectionFailedExceptionTest.java
index d08793180..93187a148 100644
--- a/src/test/java/com/hivemq/client/mqtt/exceptions/ConnectionFailedExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/exceptions/ConnectionFailedExceptionTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/exceptions/MqttClientStateExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/exceptions/MqttClientStateExceptionTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/mqtt/exceptions/MqttClientStateExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/exceptions/MqttClientStateExceptionTest.java
index 85d0e38a3..aff231ab4 100644
--- a/src/test/java/com/hivemq/client/mqtt/exceptions/MqttClientStateExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/exceptions/MqttClientStateExceptionTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/exceptions/MqttDecodeExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/exceptions/MqttDecodeExceptionTest.java
similarity index 94%
rename from src/test/java/com/hivemq/client/mqtt/exceptions/MqttDecodeExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/exceptions/MqttDecodeExceptionTest.java
index a2eb81199..8f8ce7368 100644
--- a/src/test/java/com/hivemq/client/mqtt/exceptions/MqttDecodeExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/exceptions/MqttDecodeExceptionTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/exceptions/MqttEncodeExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/exceptions/MqttEncodeExceptionTest.java
similarity index 94%
rename from src/test/java/com/hivemq/client/mqtt/exceptions/MqttEncodeExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/exceptions/MqttEncodeExceptionTest.java
index 17b1116c8..f4179cbdd 100644
--- a/src/test/java/com/hivemq/client/mqtt/exceptions/MqttEncodeExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/exceptions/MqttEncodeExceptionTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/exceptions/MqttSessionExpiredExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/exceptions/MqttSessionExpiredExceptionTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/mqtt/exceptions/MqttSessionExpiredExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/exceptions/MqttSessionExpiredExceptionTest.java
index 406f09dfa..9c8346bca 100644
--- a/src/test/java/com/hivemq/client/mqtt/exceptions/MqttSessionExpiredExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/exceptions/MqttSessionExpiredExceptionTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.exceptions;
+package com.hivemq.client2.mqtt.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3ConnAckExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3ConnAckExceptionTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3ConnAckExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3ConnAckExceptionTest.java
index cecf4d209..bad81ca42 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3ConnAckExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3ConnAckExceptionTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3DisconnectExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3DisconnectExceptionTest.java
similarity index 73%
rename from src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3DisconnectExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3DisconnectExceptionTest.java
index 2086e68fe..ee7268517 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3DisconnectExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3DisconnectExceptionTest.java
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.mqtt.message.disconnect.mqtt3.Mqtt3DisconnectView;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
@@ -28,7 +29,8 @@ class Mqtt3DisconnectExceptionTest {
 
     @Test
     void constructor() {
-        final Mqtt3DisconnectException exception = new Mqtt3DisconnectException(null, null);
+        final Mqtt3DisconnectException exception =
+                new Mqtt3DisconnectException(Mqtt3DisconnectView.INSTANCE, null, null);
         assertNull(exception.getMessage());
         assertNull(exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -37,7 +39,8 @@ void constructor() {
 
     @Test
     void constructor_message() {
-        final Mqtt3DisconnectException exception = new Mqtt3DisconnectException("message", null);
+        final Mqtt3DisconnectException exception =
+                new Mqtt3DisconnectException(Mqtt3DisconnectView.INSTANCE, "message", null);
         assertEquals("message", exception.getMessage());
         assertNull(exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -47,7 +50,8 @@ void constructor_message() {
     @Test
     void constructor_cause() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3DisconnectException exception = new Mqtt3DisconnectException(null, cause);
+        final Mqtt3DisconnectException exception =
+                new Mqtt3DisconnectException(Mqtt3DisconnectView.INSTANCE, null, cause);
         assertNull(exception.getMessage());
         assertEquals(cause, exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -57,7 +61,8 @@ void constructor_cause() {
     @Test
     void constructor_message_cause() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3DisconnectException exception = new Mqtt3DisconnectException("message", cause);
+        final Mqtt3DisconnectException exception =
+                new Mqtt3DisconnectException(Mqtt3DisconnectView.INSTANCE, "message", cause);
         assertEquals("message", exception.getMessage());
         assertEquals(cause, exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -67,7 +72,8 @@ void constructor_message_cause() {
     @Test
     void noStackTrace() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3DisconnectException exception = new Mqtt3DisconnectException("message", cause);
+        final Mqtt3DisconnectException exception =
+                new Mqtt3DisconnectException(Mqtt3DisconnectView.INSTANCE, "message", cause);
         assertEquals(0, exception.getStackTrace().length);
         final Mqtt3DisconnectException thrownException =
                 assertThrows(Mqtt3DisconnectException.class, () -> { throw exception; });
@@ -77,7 +83,8 @@ void noStackTrace() {
     @Test
     void fillInStackTrace_newStackTrace() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3DisconnectException exception = new Mqtt3DisconnectException("message", cause);
+        final Mqtt3DisconnectException exception =
+                new Mqtt3DisconnectException(Mqtt3DisconnectView.INSTANCE, "message", cause);
         assertEquals(0, exception.getStackTrace().length);
         final RuntimeException filledException = AsyncRuntimeException.fillInStackTrace(exception);
         assertTrue(filledException instanceof Mqtt3DisconnectException);
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubAckExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubAckExceptionTest.java
similarity index 86%
rename from src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubAckExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubAckExceptionTest.java
index 7fb8fc250..7f8bfc110 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubAckExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubAckExceptionTest.java
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubAckView;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
@@ -28,7 +29,7 @@ class Mqtt3PubAckExceptionTest {
 
     @Test
     void constructor() {
-        final Mqtt3PubAckException exception = new Mqtt3PubAckException(null, null);
+        final Mqtt3PubAckException exception = new Mqtt3PubAckException(Mqtt3PubAckView.INSTANCE, null, null);
         assertNull(exception.getMessage());
         assertNull(exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -37,7 +38,7 @@ void constructor() {
 
     @Test
     void constructor_message() {
-        final Mqtt3PubAckException exception = new Mqtt3PubAckException("message", null);
+        final Mqtt3PubAckException exception = new Mqtt3PubAckException(Mqtt3PubAckView.INSTANCE, "message", null);
         assertEquals("message", exception.getMessage());
         assertNull(exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -47,7 +48,7 @@ void constructor_message() {
     @Test
     void constructor_cause() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3PubAckException exception = new Mqtt3PubAckException(null, cause);
+        final Mqtt3PubAckException exception = new Mqtt3PubAckException(Mqtt3PubAckView.INSTANCE, null, cause);
         assertNull(exception.getMessage());
         assertEquals(cause, exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -57,7 +58,7 @@ void constructor_cause() {
     @Test
     void constructor_message_cause() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3PubAckException exception = new Mqtt3PubAckException("message", cause);
+        final Mqtt3PubAckException exception = new Mqtt3PubAckException(Mqtt3PubAckView.INSTANCE, "message", cause);
         assertEquals("message", exception.getMessage());
         assertEquals(cause, exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -67,7 +68,7 @@ void constructor_message_cause() {
     @Test
     void noStackTrace() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3PubAckException exception = new Mqtt3PubAckException("message", cause);
+        final Mqtt3PubAckException exception = new Mqtt3PubAckException(Mqtt3PubAckView.INSTANCE, "message", cause);
         assertEquals(0, exception.getStackTrace().length);
         final Mqtt3PubAckException thrownException =
                 assertThrows(Mqtt3PubAckException.class, () -> { throw exception; });
@@ -77,7 +78,7 @@ void noStackTrace() {
     @Test
     void fillInStackTrace_newStackTrace() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3PubAckException exception = new Mqtt3PubAckException("message", cause);
+        final Mqtt3PubAckException exception = new Mqtt3PubAckException(Mqtt3PubAckView.INSTANCE, "message", cause);
         assertEquals(0, exception.getStackTrace().length);
         final RuntimeException filledException = AsyncRuntimeException.fillInStackTrace(exception);
         assertTrue(filledException instanceof Mqtt3PubAckException);
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubRecExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubRecExceptionTest.java
similarity index 86%
rename from src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubRecExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubRecExceptionTest.java
index 1cc50469f..a7c684416 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3PubRecExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3PubRecExceptionTest.java
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.mqtt.message.publish.mqtt3.Mqtt3PubRecView;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
@@ -28,7 +29,7 @@ class Mqtt3PubRecExceptionTest {
 
     @Test
     void constructor() {
-        final Mqtt3PubRecException exception = new Mqtt3PubRecException(null, null);
+        final Mqtt3PubRecException exception = new Mqtt3PubRecException(Mqtt3PubRecView.INSTANCE, null, null);
         assertNull(exception.getMessage());
         assertNull(exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -37,7 +38,7 @@ void constructor() {
 
     @Test
     void constructor_message() {
-        final Mqtt3PubRecException exception = new Mqtt3PubRecException("message", null);
+        final Mqtt3PubRecException exception = new Mqtt3PubRecException(Mqtt3PubRecView.INSTANCE, "message", null);
         assertEquals("message", exception.getMessage());
         assertNull(exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -47,7 +48,7 @@ void constructor_message() {
     @Test
     void constructor_cause() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3PubRecException exception = new Mqtt3PubRecException(null, cause);
+        final Mqtt3PubRecException exception = new Mqtt3PubRecException(Mqtt3PubRecView.INSTANCE, null, cause);
         assertNull(exception.getMessage());
         assertEquals(cause, exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -57,7 +58,7 @@ void constructor_cause() {
     @Test
     void constructor_message_cause() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3PubRecException exception = new Mqtt3PubRecException("message", cause);
+        final Mqtt3PubRecException exception = new Mqtt3PubRecException(Mqtt3PubRecView.INSTANCE, "message", cause);
         assertEquals("message", exception.getMessage());
         assertEquals(cause, exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -67,7 +68,7 @@ void constructor_message_cause() {
     @Test
     void noStackTrace() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3PubRecException exception = new Mqtt3PubRecException("message", cause);
+        final Mqtt3PubRecException exception = new Mqtt3PubRecException(Mqtt3PubRecView.INSTANCE, "message", cause);
         assertEquals(0, exception.getStackTrace().length);
         final Mqtt3PubRecException thrownException =
                 assertThrows(Mqtt3PubRecException.class, () -> { throw exception; });
@@ -77,7 +78,7 @@ void noStackTrace() {
     @Test
     void fillInStackTrace_newStackTrace() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3PubRecException exception = new Mqtt3PubRecException("message", cause);
+        final Mqtt3PubRecException exception = new Mqtt3PubRecException(Mqtt3PubRecView.INSTANCE, "message", cause);
         assertEquals(0, exception.getStackTrace().length);
         final RuntimeException filledException = AsyncRuntimeException.fillInStackTrace(exception);
         assertTrue(filledException instanceof Mqtt3PubRecException);
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3SubAckExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3SubAckExceptionTest.java
similarity index 95%
rename from src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3SubAckExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3SubAckExceptionTest.java
index 53156b05b..86d5e9e04 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3SubAckExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3SubAckExceptionTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt3.message.subscribe.suback.Mqtt3SubAck;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3SubAck;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3UnsubAckExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3UnsubAckExceptionTest.java
similarity index 77%
rename from src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3UnsubAckExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3UnsubAckExceptionTest.java
index d2478e173..cbfb23c25 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt3/exceptions/Mqtt3UnsubAckExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt3/exceptions/Mqtt3UnsubAckExceptionTest.java
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.exceptions;
+package com.hivemq.client2.mqtt.mqtt3.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.internal.mqtt.message.unsubscribe.mqtt3.Mqtt3UnsubAckView;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
@@ -28,7 +29,7 @@ class Mqtt3UnsubAckExceptionTest {
 
     @Test
     void constructor() {
-        final Mqtt3UnsubAckException exception = new Mqtt3UnsubAckException(null, null);
+        final Mqtt3UnsubAckException exception = new Mqtt3UnsubAckException(Mqtt3UnsubAckView.INSTANCE, null, null);
         assertNull(exception.getMessage());
         assertNull(exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -37,7 +38,8 @@ void constructor() {
 
     @Test
     void constructor_message() {
-        final Mqtt3UnsubAckException exception = new Mqtt3UnsubAckException("message", null);
+        final Mqtt3UnsubAckException exception =
+                new Mqtt3UnsubAckException(Mqtt3UnsubAckView.INSTANCE, "message", null);
         assertEquals("message", exception.getMessage());
         assertNull(exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -47,7 +49,7 @@ void constructor_message() {
     @Test
     void constructor_cause() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3UnsubAckException exception = new Mqtt3UnsubAckException(null, cause);
+        final Mqtt3UnsubAckException exception = new Mqtt3UnsubAckException(Mqtt3UnsubAckView.INSTANCE, null, cause);
         assertNull(exception.getMessage());
         assertEquals(cause, exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -57,7 +59,8 @@ void constructor_cause() {
     @Test
     void constructor_message_cause() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3UnsubAckException exception = new Mqtt3UnsubAckException("message", cause);
+        final Mqtt3UnsubAckException exception =
+                new Mqtt3UnsubAckException(Mqtt3UnsubAckView.INSTANCE, "message", cause);
         assertEquals("message", exception.getMessage());
         assertEquals(cause, exception.getCause());
         assertNotNull(exception.getMqttMessage());
@@ -67,7 +70,8 @@ void constructor_message_cause() {
     @Test
     void noStackTrace() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3UnsubAckException exception = new Mqtt3UnsubAckException("message", cause);
+        final Mqtt3UnsubAckException exception =
+                new Mqtt3UnsubAckException(Mqtt3UnsubAckView.INSTANCE, "message", cause);
         assertEquals(0, exception.getStackTrace().length);
         final Mqtt3UnsubAckException thrownException =
                 assertThrows(Mqtt3UnsubAckException.class, () -> { throw exception; });
@@ -77,7 +81,8 @@ void noStackTrace() {
     @Test
     void fillInStackTrace_newStackTrace() {
         final RuntimeException cause = new RuntimeException("cause");
-        final Mqtt3UnsubAckException exception = new Mqtt3UnsubAckException("message", cause);
+        final Mqtt3UnsubAckException exception =
+                new Mqtt3UnsubAckException(Mqtt3UnsubAckView.INSTANCE, "message", cause);
         assertEquals(0, exception.getStackTrace().length);
         final RuntimeException filledException = AsyncRuntimeException.fillInStackTrace(exception);
         assertTrue(filledException instanceof Mqtt3UnsubAckException);
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3MessageTypeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3MessageTypeTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3MessageTypeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3MessageTypeTest.java
index 39c828ccc..2be99cb45 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt3/message/Mqtt3MessageTypeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt3/message/Mqtt3MessageTypeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message;
+package com.hivemq.client2.mqtt.mqtt3.message;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt3/message/connect/connack/Mqtt3ConnAckReturnCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnAckReturnCodeTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/mqtt/mqtt3/message/connect/connack/Mqtt3ConnAckReturnCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnAckReturnCodeTest.java
index 4db1217c5..b38f685b5 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt3/message/connect/connack/Mqtt3ConnAckReturnCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt3/message/connect/Mqtt3ConnAckReturnCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.connect.connack;
+package com.hivemq.client2.mqtt.mqtt3.message.connect;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/suback/Mqtt3SubAckReturnCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubAckReturnCodeTest.java
similarity index 97%
rename from src/test/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/suback/Mqtt3SubAckReturnCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubAckReturnCodeTest.java
index b2f05cafa..c8407d346 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt3/message/subscribe/suback/Mqtt3SubAckReturnCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt3/message/subscribe/Mqtt3SubAckReturnCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt3.message.subscribe.suback;
+package com.hivemq.client2.mqtt.mqtt3.message.subscribe;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5AuthExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5AuthExceptionTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5AuthExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5AuthExceptionTest.java
index e9adcfc62..c693c1590 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5AuthExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5AuthExceptionTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5Auth;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt5.message.auth.Mqtt5Auth;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5ConnAckExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5ConnAckExceptionTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5ConnAckExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5ConnAckExceptionTest.java
index 2073eba30..0f87b8b64 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5ConnAckExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5ConnAckExceptionTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt5.message.connect.Mqtt5ConnAck;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5DisconnectExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5DisconnectExceptionTest.java
similarity index 94%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5DisconnectExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5DisconnectExceptionTest.java
index 26c401636..0ee6fd91c 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5DisconnectExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5DisconnectExceptionTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubAckExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubAckExceptionTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubAckExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubAckExceptionTest.java
index 869412f45..d2b1f475a 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubAckExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubAckExceptionTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt5.message.publish.puback.Mqtt5PubAck;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubAck;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubRecExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubRecExceptionTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubRecExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubRecExceptionTest.java
index f06dcc351..500beeab8 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5PubRecExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5PubRecExceptionTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt5.message.publish.pubrec.Mqtt5PubRec;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt5.message.publish.Mqtt5PubRec;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5SubAckExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5SubAckExceptionTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5SubAckExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5SubAckExceptionTest.java
index d7a2c250e..744349f0a 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5SubAckExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5SubAckExceptionTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt5.message.subscribe.Mqtt5SubAck;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5UnsubAckExceptionTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5UnsubAckExceptionTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5UnsubAckExceptionTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5UnsubAckExceptionTest.java
index fd0c3334e..65266b2ee 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/exceptions/Mqtt5UnsubAckExceptionTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/exceptions/Mqtt5UnsubAckExceptionTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.exceptions;
+package com.hivemq.client2.mqtt.mqtt5.exceptions;
 
-import com.hivemq.client.internal.util.AsyncRuntimeException;
-import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck;
+import com.hivemq.client2.internal.util.AsyncRuntimeException;
+import com.hivemq.client2.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubAck;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5MessageTypeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5MessageTypeTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5MessageTypeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5MessageTypeTest.java
index 3e5086771..ac77b591f 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/Mqtt5MessageTypeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/Mqtt5MessageTypeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message;
+package com.hivemq.client2.mqtt.mqtt5.message;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCodeTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCodeTest.java
index 55aa73f87..d6d5f3406 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/auth/Mqtt5AuthReasonCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.auth;
+package com.hivemq.client2.mqtt.mqtt5.message.auth;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAckReasonCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAckReasonCodeTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAckReasonCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAckReasonCodeTest.java
index 35316e51f..fedf7c2ab 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/connect/connack/Mqtt5ConnAckReasonCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/connect/Mqtt5ConnAckReasonCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.connect.connack;
+package com.hivemq.client2.mqtt.mqtt5.message.connect;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCodeTest.java
similarity index 99%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCodeTest.java
index b6bb789a1..2f0c58a25 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/disconnect/Mqtt5DisconnectReasonCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.disconnect;
+package com.hivemq.client2.mqtt.mqtt5.message.disconnect;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicatorTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicatorTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicatorTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicatorTest.java
index 78008e3e4..98cb65896 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicatorTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PayloadFormatIndicatorTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAckReasonCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAckReasonCodeTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAckReasonCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAckReasonCodeTest.java
index 1a9bf4c03..1ce9ce41d 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/puback/Mqtt5PubAckReasonCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubAckReasonCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.puback;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubCompReasonCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubCompReasonCodeTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubCompReasonCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubCompReasonCodeTest.java
index 2361b727d..80283e9ce 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubcomp/Mqtt5PubCompReasonCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubCompReasonCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubcomp;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRecReasonCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRecReasonCodeTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRecReasonCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRecReasonCodeTest.java
index ff18d134d..f9b996cb2 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrec/Mqtt5PubRecReasonCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRecReasonCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubrec;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRelReasonCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRelReasonCodeTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRelReasonCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRelReasonCodeTest.java
index a8bab3ae0..8121fdd28 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/publish/pubrel/Mqtt5PubRelReasonCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/publish/Mqtt5PubRelReasonCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.publish.pubrel;
+package com.hivemq.client2.mqtt.mqtt5.message.publish;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandlingTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandlingTest.java
similarity index 92%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandlingTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandlingTest.java
index 627b06f24..9e7f56ef5 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandlingTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5RetainHandlingTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
@@ -37,7 +37,7 @@ void getCode_send() {
 
     @Test
     void getCode_sendIfSubscriptionDoesNotExist() {
-        assertEquals(0x01, Mqtt5RetainHandling.SEND_IF_SUBSCRIPTION_DOES_NOT_EXIST.getCode());
+        assertEquals(0x01, Mqtt5RetainHandling.SEND_IF_NEW_SUBSCRIPTION.getCode());
     }
 
     @Test
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/suback/Mqtt5SubAckReasonCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubAckReasonCodeTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/suback/Mqtt5SubAckReasonCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubAckReasonCodeTest.java
index 461e346a9..f048ec012 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/subscribe/suback/Mqtt5SubAckReasonCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/subscribe/Mqtt5SubAckReasonCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.subscribe.suback;
+package com.hivemq.client2.mqtt.mqtt5.message.subscribe;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/unsuback/Mqtt5UnsubAckReasonCodeTest.java b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubAckReasonCodeTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/unsuback/Mqtt5UnsubAckReasonCodeTest.java
rename to src/test/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubAckReasonCodeTest.java
index 1ed77b632..b0a3b5cdf 100644
--- a/src/test/java/com/hivemq/client/mqtt/mqtt5/message/unsubscribe/unsuback/Mqtt5UnsubAckReasonCodeTest.java
+++ b/src/test/java/com/hivemq/client2/mqtt/mqtt5/message/unsubscribe/Mqtt5UnsubAckReasonCodeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback;
+package com.hivemq.client2.mqtt.mqtt5.message.unsubscribe;
 
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/hivemq/client/rx/FlowableWithSingleItem.java b/src/test/java/com/hivemq/client2/rx/FlowableWithSingleItem.java
similarity index 94%
rename from src/test/java/com/hivemq/client/rx/FlowableWithSingleItem.java
rename to src/test/java/com/hivemq/client2/rx/FlowableWithSingleItem.java
index 2018e9d7e..366bd4b14 100644
--- a/src/test/java/com/hivemq/client/rx/FlowableWithSingleItem.java
+++ b/src/test/java/com/hivemq/client2/rx/FlowableWithSingleItem.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx;
+package com.hivemq.client2.rx;
 
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import io.reactivex.Flowable;
-import io.reactivex.FlowableSubscriber;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.core.FlowableSubscriber;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/src/test/java/com/hivemq/client/rx/FlowableWithSingleSplit.java b/src/test/java/com/hivemq/client2/rx/FlowableWithSingleSplit.java
similarity index 96%
rename from src/test/java/com/hivemq/client/rx/FlowableWithSingleSplit.java
rename to src/test/java/com/hivemq/client2/rx/FlowableWithSingleSplit.java
index f13683c92..3bf7f5d4c 100644
--- a/src/test/java/com/hivemq/client/rx/FlowableWithSingleSplit.java
+++ b/src/test/java/com/hivemq/client2/rx/FlowableWithSingleSplit.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx;
+package com.hivemq.client2.rx;
 
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import io.reactivex.Flowable;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import io.reactivex.rxjava3.core.Flowable;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.reactivestreams.Subscriber;
diff --git a/src/test/java/com/hivemq/client/rx/FlowableWithSingleTest.java b/src/test/java/com/hivemq/client2/rx/FlowableWithSingleTest.java
similarity index 96%
rename from src/test/java/com/hivemq/client/rx/FlowableWithSingleTest.java
rename to src/test/java/com/hivemq/client2/rx/FlowableWithSingleTest.java
index 1ea70e94d..f352b5c36 100644
--- a/src/test/java/com/hivemq/client/rx/FlowableWithSingleTest.java
+++ b/src/test/java/com/hivemq/client2/rx/FlowableWithSingleTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.rx;
+package com.hivemq.client2.rx;
 
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import com.hivemq.client.rx.reactivestreams.WithSingleSubscriber;
-import io.reactivex.BackpressureStrategy;
-import io.reactivex.Flowable;
-import io.reactivex.schedulers.Schedulers;
+import com.hivemq.client2.rx.reactivestreams.WithSingleSubscriber;
+import io.reactivex.rxjava3.core.BackpressureStrategy;
+import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.schedulers.Schedulers;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.function.ThrowingSupplier;
@@ -65,12 +65,12 @@ void doOnSingle(final @NotNull FlowableWithSingle<String, StringBuilder> flowabl
 
     @MethodSource("singleNext3")
     @ParameterizedTest
-    void observeOnBoth(final @NotNull FlowableWithSingle<String, StringBuilder> flowableWithSingle) {
+    void observeBothOn(final @NotNull FlowableWithSingle<String, StringBuilder> flowableWithSingle) {
         final ExecutorService executorService =
                 Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("test_thread").build());
 
         final AtomicInteger count = new AtomicInteger();
-        flowableWithSingle.observeOnBoth(Schedulers.from(executorService)).doOnSingle(stringBuilder -> {
+        flowableWithSingle.observeBothOn(Schedulers.from(executorService)).doOnSingle(stringBuilder -> {
             assertEquals("single", stringBuilder.toString());
             assertEquals("test_thread", Thread.currentThread().getName());
         }).doOnNext(string -> {
@@ -83,7 +83,7 @@ void observeOnBoth(final @NotNull FlowableWithSingle<String, StringBuilder> flow
     }
 
     @Test
-    void observeOnBoth_request() {
+    void observeBothOn_request() {
         final ExecutorService executorService =
                 Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("test_thread").build());
 
@@ -93,7 +93,7 @@ void observeOnBoth_request() {
 
         final AtomicInteger count = new AtomicInteger();
         // bufferSize 4 -> requests 3 -> checks if request for single item leads to request 2 upstream
-        flowableWithSingle.observeOnBoth(Schedulers.from(executorService), false, 4).doOnSingle(stringBuilder -> {
+        flowableWithSingle.observeBothOn(Schedulers.from(executorService), false, 4).doOnSingle(stringBuilder -> {
             assertEquals("single", stringBuilder.toString());
             assertEquals("test_thread", Thread.currentThread().getName());
         }).doOnNext(string -> {
@@ -125,7 +125,7 @@ void observeOn(final @NotNull FlowableWithSingle<String, StringBuilder> flowable
     }
 
     @Test
-    void observeOnBoth_delayError() throws InterruptedException {
+    void observeBothOn_delayError() throws InterruptedException {
         final Flowable<? extends CharSequence> flowable =
                 Flowable.fromArray(new StringBuilder("single"), "next0", "next1", "next2")
                         .concatWith(Flowable.error(new IllegalArgumentException("test")))
@@ -137,7 +137,7 @@ void observeOnBoth_delayError() throws InterruptedException {
                 Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("test_thread").build());
 
         final AtomicInteger count = new AtomicInteger();
-        flowableWithSingle.observeOnBoth(Schedulers.from(executorService), true)
+        flowableWithSingle.observeBothOn(Schedulers.from(executorService), true)
                 .doOnSingle(stringBuilder -> {
                     assertEquals("single", stringBuilder.toString());
                     assertEquals("test_thread", Thread.currentThread().getName());
@@ -156,14 +156,14 @@ void observeOnBoth_delayError() throws InterruptedException {
                 .awaitCount(3)
                 .assertValueAt(2, "next2")
                 .await()
-                .assertError(IllegalArgumentException.class)
-                .assertErrorMessage("test");
+                .assertError(throwable -> (throwable instanceof IllegalArgumentException) &&
+                        throwable.getMessage().equals("test"));
 
         executorService.shutdown();
     }
 
     @Test
-    void observeOnBoth_delayError_bufferSize() throws InterruptedException {
+    void observeBothOn_delayError_bufferSize() throws InterruptedException {
         final Flowable<? extends CharSequence> flowable =
                 Flowable.<CharSequence>just(new StringBuilder("single")).concatWith(
                         Flowable.range(0, 1024).zipWith(Flowable.just("next").repeat(1024), (i, s) -> s + i))
@@ -176,7 +176,7 @@ void observeOnBoth_delayError_bufferSize() throws InterruptedException {
                 Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("test_thread").build());
 
         final AtomicInteger count = new AtomicInteger();
-        flowableWithSingle.observeOnBoth(Schedulers.from(executorService), true, 1024)
+        flowableWithSingle.observeBothOn(Schedulers.from(executorService), true, 1024)
                 .doOnSingle(stringBuilder -> {
                     assertEquals("single", stringBuilder.toString());
                     assertEquals("test_thread", Thread.currentThread().getName());
@@ -195,14 +195,14 @@ void observeOnBoth_delayError_bufferSize() throws InterruptedException {
                 .awaitCount(1024)
                 .assertValueCount(1024)
                 .await()
-                .assertError(IllegalArgumentException.class)
-                .assertErrorMessage("test");
+                .assertError(throwable -> (throwable instanceof IllegalArgumentException) &&
+                        throwable.getMessage().equals("test"));
 
         executorService.shutdown();
     }
 
     @Test
-    void observeOnBoth_delayError_bufferSize_2() {
+    void observeBothOn_delayError_bufferSize_2() {
         final Flowable<? extends CharSequence> flowable =
                 Flowable.<CharSequence>just(new StringBuilder("single")).concatWith(
                         Flowable.range(0, 1024).zipWith(Flowable.just("next").repeat(1024), (i, s) -> s + i))
@@ -218,7 +218,7 @@ void observeOnBoth_delayError_bufferSize_2() {
         final AtomicReference<StringBuilder> single = new AtomicReference<>();
         final AtomicReference<Throwable> error = new AtomicReference<>();
         // @formatter:off
-        flowableWithSingle.observeOnBoth(Schedulers.from(executorService), true, 1024)
+        flowableWithSingle.observeBothOn(Schedulers.from(executorService), true, 1024)
                 .doOnSingle(stringBuilder -> {
                     single.set(stringBuilder);
                     assertEquals("test_thread", Thread.currentThread().getName());
@@ -284,12 +284,10 @@ void doOnSingle_multiple(final @NotNull FlowableWithSingle<String, StringBuilder
                 .doOnSingle(stringBuilder -> {
                     assertEquals(1, counter.incrementAndGet());
                     assertNotEquals("test_thread", Thread.currentThread().getName());
-                })
-                .doOnSingle(stringBuilder -> {
-                    assertEquals(2, counter.incrementAndGet());
-                    assertNotEquals("test_thread", Thread.currentThread().getName());
-                })
-                .observeOnBoth(Schedulers.from(executorService))
+                }).doOnSingle(stringBuilder -> {
+            assertEquals(2, counter.incrementAndGet());
+            assertNotEquals("test_thread", Thread.currentThread().getName());
+        }).observeBothOn(Schedulers.from(executorService))
                 .doOnSingle(stringBuilder -> {
                     assertEquals(3, counter.incrementAndGet());
                     assertEquals("test_thread", Thread.currentThread().getName());
@@ -329,7 +327,7 @@ void mapBoth_multiple(final @NotNull FlowableWithSingle<String, StringBuilder> f
             assertEquals(2, singleCounter.incrementAndGet());
             assertNotEquals("test_thread", Thread.currentThread().getName());
             return stringBuilder.append("-2");
-        }).observeOnBoth(Schedulers.from(executorService)).mapBoth(s -> {
+        }).observeBothOn(Schedulers.from(executorService)).mapBoth(s -> {
             nextCounter.incrementAndGet();
             assertEquals("test_thread", Thread.currentThread().getName());
             return s + "-3";
diff --git a/src/test/java/com/hivemq/client/util/KeyStoreUtilTest.java b/src/test/java/com/hivemq/client2/util/KeyStoreUtilTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/util/KeyStoreUtilTest.java
rename to src/test/java/com/hivemq/client2/util/KeyStoreUtilTest.java
index 852377df9..4a13e6da9 100644
--- a/src/test/java/com/hivemq/client/util/KeyStoreUtilTest.java
+++ b/src/test/java/com/hivemq/client2/util/KeyStoreUtilTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.util;
+package com.hivemq.client2.util;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/src/test/java/com/hivemq/client/util/TestKeyStoreGenerator.java b/src/test/java/com/hivemq/client2/util/TestKeyStoreGenerator.java
similarity index 99%
rename from src/test/java/com/hivemq/client/util/TestKeyStoreGenerator.java
rename to src/test/java/com/hivemq/client2/util/TestKeyStoreGenerator.java
index 2f8474508..5d1c65f38 100644
--- a/src/test/java/com/hivemq/client/util/TestKeyStoreGenerator.java
+++ b/src/test/java/com/hivemq/client2/util/TestKeyStoreGenerator.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.util;
+package com.hivemq.client2.util;
 
 import org.bouncycastle.asn1.x500.X500Name;
 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
diff --git a/src/test/java/com/hivemq/client/util/TypeSwitchTest.java b/src/test/java/com/hivemq/client2/util/TypeSwitchTest.java
similarity index 98%
rename from src/test/java/com/hivemq/client/util/TypeSwitchTest.java
rename to src/test/java/com/hivemq/client2/util/TypeSwitchTest.java
index 1426e2624..638b2c10a 100644
--- a/src/test/java/com/hivemq/client/util/TypeSwitchTest.java
+++ b/src/test/java/com/hivemq/client2/util/TypeSwitchTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.hivemq.client.util;
+package com.hivemq.client2.util;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/websocket/build.gradle.kts b/websocket/build.gradle.kts
index b0fc69c3e..1913891f0 100644
--- a/websocket/build.gradle.kts
+++ b/websocket/build.gradle.kts
@@ -8,7 +8,7 @@ plugins {
 description = "Adds dependencies for the HiveMQ MQTT Client websocket module"
 
 metadata {
-    moduleName.set("com.hivemq.client.mqtt.websocket")
+    moduleName.set("com.hivemq.client2.mqtt.websocket")
     readableName.set("HiveMQ MQTT Client websocket module")
 }