From 3aad4eb6b7089744d6cc16cb6e134f131455b097 Mon Sep 17 00:00:00 2001
From: Thomas Jaeckle <thomas.jaeckle@bosch.io>
Date: Fri, 21 Feb 2020 13:36:12 +0100
Subject: [PATCH 01/17] update Ditto version to 1.0.0-M2

---
 java/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/java/pom.xml b/java/pom.xml
index ba873ba8..91dc1314 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -190,7 +190,7 @@
         <revision>0-SNAPSHOT</revision>
 
         <!-- ### Compile dependencies versions -->
-        <ditto.version>${revision}</ditto.version>
+        <ditto.version>1.0.0-M2</ditto.version>
         <minimal-json.version>0.9.5</minimal-json.version>
         <nv-websocket-client.version>2.9</nv-websocket-client.version>
         <classindex.version>3.8</classindex.version>

From 1c02e04c58af354e05cbe5aee775b687bd751742 Mon Sep 17 00:00:00 2001
From: Thomas Jaeckle <thomas.jaeckle@bosch.io>
Date: Fri, 21 Feb 2020 14:17:05 +0100
Subject: [PATCH 02/17] Fixed used Ditto version: 1.1.0-M2

---
 java/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/java/pom.xml b/java/pom.xml
index 91dc1314..b30e4777 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -190,7 +190,7 @@
         <revision>0-SNAPSHOT</revision>
 
         <!-- ### Compile dependencies versions -->
-        <ditto.version>1.0.0-M2</ditto.version>
+        <ditto.version>1.1.0-M2</ditto.version>
         <minimal-json.version>0.9.5</minimal-json.version>
         <nv-websocket-client.version>2.9</nv-websocket-client.version>
         <classindex.version>3.8</classindex.version>

From 43eeb95d4f11f11f3b9204e230a681a5ea476a65 Mon Sep 17 00:00:00 2001
From: Thomas Jaeckle <thomas.jaeckle@bosch.io>
Date: Fri, 21 Feb 2020 16:56:32 +0100
Subject: [PATCH 03/17] added mandatory configuration for gpg plugin

for release on JIRO
---
 java/pom.xml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/java/pom.xml b/java/pom.xml
index b30e4777..ede06f34 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -1166,6 +1166,12 @@
                                 <goals>
                                     <goal>sign</goal>
                                 </goals>
+                                <configuration>
+                                  <gpgArguments>
+                                    <arg>--pinentry-mode</arg>
+                                    <arg>loopback</arg>
+                                  </gpgArguments>
+                                </configuration>
                             </execution>
                         </executions>
                     </plugin>

From b84ea1abe4b09bd8398246d5c90bd08ac12e7bf4 Mon Sep 17 00:00:00 2001
From: Thomas Jaeckle <thomas.jaeckle@bosch.io>
Date: Thu, 27 Feb 2020 18:33:30 +0100
Subject: [PATCH 04/17] use actions/checkout@v2

---
 .github/workflows/maven.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 95efac6c..9afa5e17 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -23,7 +23,7 @@ jobs:
         java: [ '1.8' ]
 
     steps:
-    - uses: actions/checkout@v1
+    - uses: actions/checkout@v2
     - name: set up JDK ${{ matrix.java }}
       uses: actions/setup-java@v1
       with:

From 9010d3dcc06a881d7dca43aa752edcc8fd89e561 Mon Sep 17 00:00:00 2001
From: Thomas Jaeckle <thomas.jaeckle@bosch.io>
Date: Thu, 27 Feb 2020 18:33:53 +0100
Subject: [PATCH 05/17] use actions/checkout@v2 for node

---
 .github/workflows/nodejs.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml
index 883361a7..37c3eadb 100644
--- a/.github/workflows/nodejs.yml
+++ b/.github/workflows/nodejs.yml
@@ -24,7 +24,7 @@ jobs:
         node-version: [10.x, 12.x]
 
     steps:
-    - uses: actions/checkout@v1
+    - uses: actions/checkout@v2
     - name: Use Node.js ${{ matrix.node-version }}
       uses: actions/setup-node@v1
       with:

From e5dd921bb0a3ffc1b7590e7f5ff4d768031b2f27 Mon Sep 17 00:00:00 2001
From: Florian Fendt <Florian.Fendt@bosch.io>
Date: Fri, 28 Feb 2020 10:51:07 +0100
Subject: [PATCH 06/17] Don't box instances of AuthenticationException into
 each other. This happens because #safeGet is called twice on #initialize.

Signed-off-by: Florian Fendt <Florian.Fendt@bosch.io>
---
 .../messaging/internal/WebSocketMessagingProvider.java      | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/java/src/main/java/org/eclipse/ditto/client/messaging/internal/WebSocketMessagingProvider.java b/java/src/main/java/org/eclipse/ditto/client/messaging/internal/WebSocketMessagingProvider.java
index 780e07ae..4a28e0e2 100644
--- a/java/src/main/java/org/eclipse/ditto/client/messaging/internal/WebSocketMessagingProvider.java
+++ b/java/src/main/java/org/eclipse/ditto/client/messaging/internal/WebSocketMessagingProvider.java
@@ -286,7 +286,10 @@ private <T> T handleTimeoutException(final TimeoutException e) {
 
     private <T> T handleExecutionException(final ExecutionException e) {
         final Throwable cause = e.getCause();
-        if (cause instanceof WebSocketException) {
+        if (cause instanceof AuthenticationException) {
+            // no unneccessary boxing of AuthenticationException
+            throw ((AuthenticationException) cause);
+        } else if (cause instanceof WebSocketException) {
             LOGGER.error("Got exception: {}", cause.getMessage());
 
             if (isAuthenticationException((WebSocketException) cause)) {
@@ -295,6 +298,7 @@ private <T> T handleExecutionException(final ExecutionException e) {
                 throw AuthenticationException.forbidden(sessionId, cause);
             }
         }
+
         throw AuthenticationException.of(sessionId, e);
     }
 

From 12b21624c0e9141c4f8466471489515e45ba19ca Mon Sep 17 00:00:00 2001
From: Florian Fendt <Florian.Fendt@bosch.io>
Date: Fri, 28 Feb 2020 10:52:32 +0100
Subject: [PATCH 07/17] Add specific exception message for
 AuthenticationExceptions when we know the status and the reason of the
 connection failure.

Signed-off-by: Florian Fendt <Florian.Fendt@bosch.io>
---
 .../messaging/AuthenticationException.java    | 19 +++++++++++++++++++
 .../internal/WebSocketMessagingProvider.java  |  4 ++++
 2 files changed, 23 insertions(+)

diff --git a/java/src/main/java/org/eclipse/ditto/client/messaging/AuthenticationException.java b/java/src/main/java/org/eclipse/ditto/client/messaging/AuthenticationException.java
index 64c48742..1d7225bc 100755
--- a/java/src/main/java/org/eclipse/ditto/client/messaging/AuthenticationException.java
+++ b/java/src/main/java/org/eclipse/ditto/client/messaging/AuthenticationException.java
@@ -30,6 +30,9 @@ public class AuthenticationException extends RuntimeException {
     private static final String FORBIDDEN_MESSAGE_TEMPLATE =
             "Authentication of session <%s> failed because of insufficient permissions.";
 
+    private static final String STATUS_MESSAGE_TEMPLATE =
+            "Authentication of session <%s> failed with status <%d> and reason: %s";
+
     private static final long serialVersionUID = 4405868587578425044L;
 
     private AuthenticationException(final String message, final Throwable cause) {
@@ -48,4 +51,20 @@ public static AuthenticationException forbidden(final String sessionId, final Th
         return new AuthenticationException(String.format(FORBIDDEN_MESSAGE_TEMPLATE, sessionId), cause);
     }
 
+    /**
+     * Creates an AutenticationException for the {@code status code its {@code reason}.
+     * @param sessionId the sessionId that failed to authenticate.
+     * @param cause the cause of the failure.
+     * @param status the status code of the failure.
+     * @param reason a reason message for the failure.
+     * @return the AuthenticationException with the provided information.
+     * @since 1.1.0
+     */
+    public static AuthenticationException withStatus(final String sessionId, final Throwable cause,
+            final int status, final String reason) {
+        return new AuthenticationException(
+                String.format(STATUS_MESSAGE_TEMPLATE, sessionId, status, reason),
+                cause);
+    }
+
 }
diff --git a/java/src/main/java/org/eclipse/ditto/client/messaging/internal/WebSocketMessagingProvider.java b/java/src/main/java/org/eclipse/ditto/client/messaging/internal/WebSocketMessagingProvider.java
index 4a28e0e2..0eda9c2a 100644
--- a/java/src/main/java/org/eclipse/ditto/client/messaging/internal/WebSocketMessagingProvider.java
+++ b/java/src/main/java/org/eclipse/ditto/client/messaging/internal/WebSocketMessagingProvider.java
@@ -296,6 +296,10 @@ private <T> T handleExecutionException(final ExecutionException e) {
                 throw AuthenticationException.unauthorized(sessionId, cause);
             } else if (isForbidden((WebSocketException) cause)) {
                 throw AuthenticationException.forbidden(sessionId, cause);
+            } else if (cause instanceof OpeningHandshakeException) {
+                final StatusLine statusLine = ((OpeningHandshakeException) cause).getStatusLine();
+                throw AuthenticationException.withStatus(sessionId, cause, statusLine.getStatusCode(),
+                        statusLine.getReasonPhrase());
             }
         }
 

From 49c309b0f86d1fc9c8fe761f6b1ca3577b489ab3 Mon Sep 17 00:00:00 2001
From: Florian Fendt <Florian.Fendt@bosch.io>
Date: Fri, 28 Feb 2020 10:57:06 +0100
Subject: [PATCH 08/17] set JsonSchemaVersion to V_2 in README.md

Signed-off-by: Florian Fendt <Florian.Fendt@bosch.io>
---
 java/README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/java/README.md b/java/README.md
index a2533e3b..b6f4cd24 100644
--- a/java/README.md
+++ b/java/README.md
@@ -71,7 +71,7 @@ AuthenticationProvider authenticationProvider =
 ```java
 MessagingProvider messagingProvider = MessagingProviders.webSocket(WebSocketMessagingConfiguration.newBuilder()
     .endpoint("wss://ditto.eclipse.org")
-    .jsonSchemaVersion(JsonSchemaVersion.V_1)
+    .jsonSchemaVersion(JsonSchemaVersion.V_2)
     .proxyConfiguration(proxyConfig) // optionally configure a proxy server
     // optionally configure a truststore containing the trusted CAs for SSL connection establishment
     .trustStoreConfiguration(TrustStoreConfiguration.newBuilder()

From 2ba45bd634988961a9df52c36e61c65476ac8d30 Mon Sep 17 00:00:00 2001
From: Florian Fendt <Florian.Fendt@bosch.io>
Date: Fri, 28 Feb 2020 11:23:33 +0100
Subject: [PATCH 09/17] fix javadoc failure

Signed-off-by: Florian Fendt <Florian.Fendt@bosch.io>
---
 .../eclipse/ditto/client/messaging/AuthenticationException.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/java/src/main/java/org/eclipse/ditto/client/messaging/AuthenticationException.java b/java/src/main/java/org/eclipse/ditto/client/messaging/AuthenticationException.java
index 1d7225bc..7f5f5d51 100755
--- a/java/src/main/java/org/eclipse/ditto/client/messaging/AuthenticationException.java
+++ b/java/src/main/java/org/eclipse/ditto/client/messaging/AuthenticationException.java
@@ -52,7 +52,7 @@ public static AuthenticationException forbidden(final String sessionId, final Th
     }
 
     /**
-     * Creates an AutenticationException for the {@code status code its {@code reason}.
+     * Creates an AutenticationException for the {@code status} code its {@code reason}.
      * @param sessionId the sessionId that failed to authenticate.
      * @param cause the cause of the failure.
      * @param status the status code of the failure.

From c12dee9eb9891b079bbebc582ad328d175a49d33 Mon Sep 17 00:00:00 2001
From: Michael Gantert <michael.gantert@bosch.io>
Date: Thu, 5 Mar 2020 12:57:29 +0100
Subject: [PATCH 10/17] JaCoCo: Switch from binary (deprecated) to xml report.

Signed-off-by: Michael Gantert <michael.gantert@bosch.io>
---
 java/pom.xml | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/java/pom.xml b/java/pom.xml
index ba873ba8..5343571e 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -240,6 +240,8 @@
         <ditto.thirdPartyLicences.excludedGroups>
             (org\.eclipse\.ditto.*)
         </ditto.thirdPartyLicences.excludedGroups>
+        
+        <sonar.coverage.jacoco.xmlReportPaths>${project.basedir}/target/site/jacoco/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
     </properties>
 
     <build>
@@ -376,7 +378,7 @@
                 <plugin>
                     <groupId>org.jacoco</groupId>
                     <artifactId>jacoco-maven-plugin</artifactId>
-                    <version>0.8.3</version>
+                    <version>0.8.5</version>
                 </plugin>
                 <plugin>
                     <groupId>com.github.siom79.japicmp</groupId>
@@ -704,7 +706,7 @@
                 <artifactId>jacoco-maven-plugin</artifactId>
                 <executions>
                     <execution>
-                        <id>prepare</id>
+                        <id>prepare-agent</id>
                         <goals>
                             <goal>prepare-agent</goal>
                         </goals>
@@ -712,7 +714,7 @@
                     <execution>
                         <id>report</id>
                         <goals>
-                            <goal>report-aggregate</goal>
+                            <goal>report</goal>
                         </goals>
                     </execution>
                 </executions>

From 6e1996d42051806450386d658c05d343998bf494 Mon Sep 17 00:00:00 2001
From: Florian Fendt <Florian.Fendt@bosch.io>
Date: Mon, 16 Mar 2020 08:35:07 +0100
Subject: [PATCH 11/17] add missing argument not null assertions and update
 binary compatibility check version to 1.1.0-M2

Signed-off-by: Florian Fendt <Florian.Fendt@bosch.io>
---
 java/pom.xml                                  |  2 +-
 .../client/internal/CommonManagementImpl.java | 71 ++++++++++++-------
 .../client/management/CommonManagement.java   | 26 ++++---
 .../ditto/client/DittoClientThingTest.java    | 30 +++++++-
 4 files changed, 89 insertions(+), 40 deletions(-)

diff --git a/java/pom.xml b/java/pom.xml
index ba873ba8..6fd8d62e 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -233,7 +233,7 @@
         <!-- globally set version for checking binary compatibility against -->
         <!-- whoever changes this to ${revision} or ${project.version} is responsible for API breakage caused by this! -->
         <!-- in other words: never do that here! exclude the 'breakages' locally in the japicmp maven plugin if you intentionally break something -->
-        <binary-compatibility-check.version>1.0.0</binary-compatibility-check.version>
+        <binary-compatibility-check.version>1.1.0-M2</binary-compatibility-check.version>
         <!-- skip until first release: -->
         <binary-compatibility-check.skip>false</binary-compatibility-check.skip>
 
diff --git a/java/src/main/java/org/eclipse/ditto/client/internal/CommonManagementImpl.java b/java/src/main/java/org/eclipse/ditto/client/internal/CommonManagementImpl.java
index 9e232c49..488b7719 100755
--- a/java/src/main/java/org/eclipse/ditto/client/internal/CommonManagementImpl.java
+++ b/java/src/main/java/org/eclipse/ditto/client/internal/CommonManagementImpl.java
@@ -75,6 +75,9 @@
 public abstract class CommonManagementImpl<T extends ThingHandle<F>, F extends FeatureHandle> implements
         CommonManagement<T, F> {
 
+    private static final String ARGUMENT_THING_ID = "thingId";
+    private static final String ARGUMENT_THING = "thing";
+    private static final String ARGUMENT_INITIAL_POLICY = "initialPolicy";
     private static final Logger LOGGER = LoggerFactory.getLogger(CommonManagementImpl.class);
 
     private final TopicPath.Channel channel;
@@ -280,20 +283,21 @@ public CompletableFuture<Thing> create(final JsonObject jsonObject, final Option
     }
 
     @Override
-    public CompletableFuture<Thing> create(final Policy policy, final Option<?>... options) {
+    public CompletableFuture<Thing> create(final Policy initialPolicy, final Option<?>... options) {
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
         // as the backend adds the default namespace, we can here simply use the empty namespace.
         final Thing thing = ThingsModelFactory.newThingBuilder()
                 .setId(ThingId.generateRandom())
                 .build();
-        return processCreate(thing, policy.toJson(), options);
+        return processCreate(thing, initialPolicy.toJson(), options);
     }
 
     @Override
     public CompletableFuture<Thing> create(final ThingId thingId, final JsonObject initialPolicy,
             final Option<?>... options) {
-        argumentNotNull(thingId);
+        argumentNotNull(thingId, ARGUMENT_THING_ID);
         argumentNotEmpty(thingId);
-        argumentNotNull(initialPolicy);
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
 
         final Thing thing = ThingsModelFactory.newThingBuilder()
                 .setId(ThingId.of(thingId))
@@ -305,9 +309,9 @@ public CompletableFuture<Thing> create(final ThingId thingId, final JsonObject i
     @Override
     public CompletableFuture<Thing> create(final ThingId thingId, final Policy initialPolicy,
             final Option<?>... options) {
-        argumentNotNull(thingId);
+        argumentNotNull(thingId, ARGUMENT_THING_ID);
         argumentNotEmpty(thingId);
-        argumentNotNull(initialPolicy);
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
 
         final Thing thing = ThingsModelFactory.newThingBuilder()
                 .setId(ThingId.of(thingId))
@@ -316,37 +320,40 @@ public CompletableFuture<Thing> create(final ThingId thingId, final Policy initi
     }
 
     @Override
-    public CompletableFuture<Thing> create(final JsonObject jsonObject, final JsonObject initialPolicy,
+    public CompletableFuture<Thing> create(final JsonObject thing, final JsonObject initialPolicy,
             final Option<?>... options) {
-        argumentNotNull(jsonObject);
-        argumentNotNull(initialPolicy);
+        argumentNotNull(thing, ARGUMENT_THING);
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
 
-        final Thing thing = ThingsModelFactory.newThing(jsonObject);
-
-        return processCreate(thing, initialPolicy, options);
+        return processCreate(ThingsModelFactory.newThing(thing), initialPolicy, options);
     }
 
     @Override
-    public CompletableFuture<Thing> create(final JsonObject jsonObject, final Policy initialPolicy,
+    public CompletableFuture<Thing> create(final JsonObject thing, final Policy initialPolicy,
             final Option<?>... options) {
-        argumentNotNull(jsonObject);
-        argumentNotNull(initialPolicy);
-
-        final Thing thing = ThingsModelFactory.newThing(jsonObject);
+        argumentNotNull(thing, ARGUMENT_THING);
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
 
-        return processCreate(thing, initialPolicy.toJson(), options);
+        return processCreate(ThingsModelFactory.newThing(thing), initialPolicy.toJson(), options);
     }
 
     @Override
     public CompletableFuture<Thing> create(final Thing thing, final JsonObject initialPolicy,
             final Option<?>... options) {
+        argumentNotNull(thing, ARGUMENT_THING);
+        assertThatThingHasId(thing);
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
+
         return processCreate(thing, initialPolicy, options);
     }
 
-
     @Override
     public CompletableFuture<Thing> create(final Thing thing, final Policy initialPolicy,
             final Option<?>... options) {
+        argumentNotNull(thing, ARGUMENT_THING);
+        assertThatThingHasId(thing);
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
+
         return processCreate(thing, initialPolicy.toJson(), options);
     }
 
@@ -370,6 +377,8 @@ private CompletableFuture<Thing> processCreate(final Thing thing, @Nullable fina
 
     @Override
     public CompletableFuture<Optional<Thing>> put(final Thing thing, final Option<?>... options) {
+        argumentNotNull(thing, ARGUMENT_THING);
+        assertThatThingHasId(thing);
         return processPut(thing, null, options);
     }
 
@@ -384,32 +393,40 @@ public CompletableFuture<Optional<Thing>> put(final JsonObject jsonObject, final
     }
 
     @Override
-    public CompletableFuture<Optional<Thing>> put(final JsonObject jsonObject, final JsonObject initialPolicy,
+    public CompletableFuture<Optional<Thing>> put(final JsonObject thing, final JsonObject initialPolicy,
             final Option<?>... options) {
-        argumentNotNull(jsonObject);
+        argumentNotNull(thing, ARGUMENT_THING);
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
 
-        final Thing thing = ThingsModelFactory.newThing(jsonObject);
-        return processPut(thing, initialPolicy, options);
+        return processPut(ThingsModelFactory.newThing(thing), initialPolicy, options);
     }
 
     @Override
-    public CompletableFuture<Optional<Thing>> put(final JsonObject jsonObject, final Policy initialPolicy,
+    public CompletableFuture<Optional<Thing>> put(final JsonObject thing, final Policy initialPolicy,
             final Option<?>... options) {
-        argumentNotNull(jsonObject);
+        argumentNotNull(thing, ARGUMENT_THING);
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
 
-        final Thing thing = ThingsModelFactory.newThing(jsonObject);
-        return processPut(thing, initialPolicy.toJson(), options);
+        return processPut(ThingsModelFactory.newThing(thing), initialPolicy.toJson(), options);
     }
 
     @Override
     public CompletableFuture<Optional<Thing>> put(final Thing thing, final JsonObject initialPolicy,
             final Option<?>... options) {
+        argumentNotNull(thing, ARGUMENT_THING);
+        assertThatThingHasId(thing);
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
+
         return processPut(thing, initialPolicy, options);
     }
 
     @Override
     public CompletableFuture<Optional<Thing>> put(final Thing thing, final Policy initialPolicy,
             final Option<?>... options) {
+        argumentNotNull(thing, ARGUMENT_THING);
+        assertThatThingHasId(thing);
+        argumentNotNull(initialPolicy, ARGUMENT_INITIAL_POLICY);
+
         return processPut(thing, initialPolicy.toJson(), options);
     }
 
diff --git a/java/src/main/java/org/eclipse/ditto/client/management/CommonManagement.java b/java/src/main/java/org/eclipse/ditto/client/management/CommonManagement.java
index d7170ff8..85a820d2 100755
--- a/java/src/main/java/org/eclipse/ditto/client/management/CommonManagement.java
+++ b/java/src/main/java/org/eclipse/ditto/client/management/CommonManagement.java
@@ -204,7 +204,8 @@ public interface CommonManagement<T extends ThingHandle, F extends FeatureHandle
      * org.eclipse.ditto.client.options.Options}.
      * @return completable future providing the created Thing object or a specific {@link
      * org.eclipse.ditto.model.base.exceptions.DittoRuntimeException} if the operation failed
-     * @throws IllegalArgumentException if {@code thing} is {@code null} or has no identifier.
+     * @throws IllegalArgumentException if {@code thing} is {@code null} or has no identifier, or if
+     * {@code initialPolicy} is {@code null}.
      * @throws org.eclipse.ditto.model.things.ThingIdInvalidException if the {@code thingId} was invalid.
      * @since 1.1.0
      */
@@ -220,7 +221,8 @@ public interface CommonManagement<T extends ThingHandle, F extends FeatureHandle
      * org.eclipse.ditto.client.options.Options}.
      * @return completable future providing the created Thing object or a specific {@link
      * org.eclipse.ditto.model.base.exceptions.DittoRuntimeException} if the operation failed
-     * @throws IllegalArgumentException if {@code thingId} is {@code null} or empty.
+     * @throws IllegalArgumentException if {@code thingId} is {@code null} or empty, or if {@code initialPolicy} is
+     * {@code null}.
      * @throws org.eclipse.ditto.model.things.ThingIdInvalidException if the {@code thingId} was invalid.
      * @since 1.1.0
      */
@@ -238,7 +240,7 @@ public interface CommonManagement<T extends ThingHandle, F extends FeatureHandle
      * @return completable future providing the created Thing object or a specific {@link
      * org.eclipse.ditto.model.base.exceptions.DittoRuntimeException} if the operation failed
      * @throws IllegalArgumentException if {@code thing} is {@code null} or if it does not contain the field named
-     * {@code "thingId"}.
+     * {@code "thingId"}, or if {@code initialPolicy} is {@code null}.
      * @throws org.eclipse.ditto.model.base.exceptions.DittoJsonException if {@code thing} cannot be parsed to a {@link
      * Thing}.
      * @throws org.eclipse.ditto.model.things.ThingIdInvalidException if the {@code thingId} was invalid.
@@ -255,7 +257,8 @@ public interface CommonManagement<T extends ThingHandle, F extends FeatureHandle
      * org.eclipse.ditto.client.options.Options}.
      * @return completable future providing the created Thing object or a specific {@link
      * org.eclipse.ditto.model.base.exceptions.DittoRuntimeException} if the operation failed
-     * @throws IllegalArgumentException if {@code thing} is {@code null} or has no identifier.
+     * @throws IllegalArgumentException if {@code thing} is {@code null} or has no identifier, or if
+     * {@code initialPolicy} is {@code null}.
      * @throws org.eclipse.ditto.model.things.ThingIdInvalidException if the {@code thingId} was invalid.
      * @since 1.1.0
      */
@@ -271,7 +274,8 @@ public interface CommonManagement<T extends ThingHandle, F extends FeatureHandle
      * org.eclipse.ditto.client.options.Options}.
      * @return completable future providing the created Thing object or a specific {@link
      * org.eclipse.ditto.model.base.exceptions.DittoRuntimeException} if the operation failed
-     * @throws IllegalArgumentException if {@code thingId} is {@code null} or empty.
+     * @throws IllegalArgumentException if {@code thingId} is {@code null} or empty, or if {@code initialPolicy} is
+     * {@code null}.
      * @throws org.eclipse.ditto.model.things.ThingIdInvalidException if the {@code thingId} was invalid.
      * @since 1.1.0
      */
@@ -289,7 +293,7 @@ public interface CommonManagement<T extends ThingHandle, F extends FeatureHandle
      * @return completable future providing the created Thing object or a specific {@link
      * org.eclipse.ditto.model.base.exceptions.DittoRuntimeException} if the operation failed
      * @throws IllegalArgumentException if {@code thing} is {@code null} or if it does not contain the field named
-     * {@code "thingId"}.
+     * {@code "thingId"}, or if {@code initialPolicy} is {@code null}.
      * @throws org.eclipse.ditto.model.base.exceptions.DittoJsonException if {@code thing} cannot be parsed to a {@link
      * Thing}.
      * @throws org.eclipse.ditto.model.things.ThingIdInvalidException if the {@code thingId} was invalid.
@@ -344,7 +348,8 @@ public interface CommonManagement<T extends ThingHandle, F extends FeatureHandle
      * @return completable future providing an {@link Optional} containing the created Thing object, in case the Thing
      * has been created, or an empty Optional, in case the Thing has been updated. Provides a {@link
      * org.eclipse.ditto.model.base.exceptions.DittoRuntimeException} if the operation failed.
-     * @throws IllegalArgumentException if {@code thing} is {@code null} or has no identifier.
+     * @throws IllegalArgumentException if {@code thing} is {@code null} or has no identifier, or if
+     * {@code initialPolicy} is {@code null}.
      * @since 1.1.0
      */
     CompletableFuture<Optional<Thing>> put(Thing thing, JsonObject initialPolicy, Option<?>... options);
@@ -364,7 +369,7 @@ public interface CommonManagement<T extends ThingHandle, F extends FeatureHandle
      * has been created, or an empty Optional, in case the Thing has been updated. Provides a {@link
      * org.eclipse.ditto.model.base.exceptions.DittoRuntimeException} if the operation failed.
      * @throws IllegalArgumentException if {@code thing} is {@code null} or if it does not contain the field named
-     * {@code "thingId"}.
+     * {@code "thingId"}, or if {@code initialPolicy} is {@code null}.
      * @throws org.eclipse.ditto.model.base.exceptions.DittoJsonException if {@code thing} cannot be parsed to a {@link
      * Thing}.
      * @since 1.1.0
@@ -383,7 +388,8 @@ public interface CommonManagement<T extends ThingHandle, F extends FeatureHandle
      * @return completable future providing an {@link Optional} containing the created Thing object, in case the Thing
      * has been created, or an empty Optional, in case the Thing has been updated. Provides a {@link
      * org.eclipse.ditto.model.base.exceptions.DittoRuntimeException} if the operation failed.
-     * @throws IllegalArgumentException if {@code thing} is {@code null} or has no identifier.
+     * @throws IllegalArgumentException if {@code thing} is {@code null} or has no identifier, or if
+     * {@code initialPolicy} is {@code null}.
      * @since 1.1.0
      */
     CompletableFuture<Optional<Thing>> put(Thing thing, Policy initialPolicy, Option<?>... options);
@@ -403,7 +409,7 @@ public interface CommonManagement<T extends ThingHandle, F extends FeatureHandle
      * has been created, or an empty Optional, in case the Thing has been updated. Provides a {@link
      * org.eclipse.ditto.model.base.exceptions.DittoRuntimeException} if the operation failed.
      * @throws IllegalArgumentException if {@code thing} is {@code null} or if it does not contain the field named
-     * {@code "thingId"}.
+     * {@code "thingId"}, or if {@code initialPolicy} is {@code null}.
      * @throws org.eclipse.ditto.model.base.exceptions.DittoJsonException if {@code thing} cannot be parsed to a {@link
      * Thing}.
      * @since 1.1.0
diff --git a/java/src/test/java/org/eclipse/ditto/client/DittoClientThingTest.java b/java/src/test/java/org/eclipse/ditto/client/DittoClientThingTest.java
index faf358ca..761b4470 100644
--- a/java/src/test/java/org/eclipse/ditto/client/DittoClientThingTest.java
+++ b/java/src/test/java/org/eclipse/ditto/client/DittoClientThingTest.java
@@ -31,6 +31,7 @@
 import org.eclipse.ditto.client.options.Options;
 import org.eclipse.ditto.client.registration.DuplicateRegistrationIdException;
 import org.eclipse.ditto.json.JsonFactory;
+import org.eclipse.ditto.json.JsonObject;
 import org.eclipse.ditto.json.JsonPointer;
 import org.eclipse.ditto.model.base.auth.AuthorizationModelFactory;
 import org.eclipse.ditto.model.base.auth.AuthorizationSubject;
@@ -39,6 +40,7 @@
 import org.eclipse.ditto.model.messages.MessageDirection;
 import org.eclipse.ditto.model.messages.MessageHeaders;
 import org.eclipse.ditto.model.messages.MessagesModelFactory;
+import org.eclipse.ditto.model.policies.Policy;
 import org.eclipse.ditto.model.policies.PolicyId;
 import org.eclipse.ditto.model.things.Feature;
 import org.eclipse.ditto.model.things.Thing;
@@ -371,7 +373,7 @@ public void testCreateThingWithInlinePolicy() throws InterruptedException {
     }
 
     @Test
-    public void testCreateThingWithInitialJSONPolicy() throws InterruptedException {
+    public void testCreateThingWithInitialPolicyJson() throws InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
 
         messaging.onSend(m -> {
@@ -388,6 +390,12 @@ public void testCreateThingWithInitialJSONPolicy() throws InterruptedException {
         Assertions.assertThat(latch.await(TIMEOUT, TIME_UNIT)).isTrue();
     }
 
+    @Test
+    public void testCreateThingWithInitialPolicyJsonNullable() {
+        assertThatExceptionOfType(IllegalArgumentException.class)
+                .isThrownBy(() -> client.twin().create(THING_ID, (JsonObject) null));
+    }
+
     @Test
     public void testCreateThingWithInitialPolicy() throws InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
@@ -406,6 +414,12 @@ public void testCreateThingWithInitialPolicy() throws InterruptedException {
         Assertions.assertThat(latch.await(TIMEOUT, TIME_UNIT)).isTrue();
     }
 
+    @Test
+    public void testCreateThingWithInitialPolicyNull() {
+        assertThatExceptionOfType(IllegalArgumentException.class)
+                .isThrownBy(() -> client.twin().create(THING_ID, (Policy) null));
+    }
+
     @Test
     public void testPutThingWithInlinePolicy() throws InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
@@ -425,7 +439,7 @@ public void testPutThingWithInlinePolicy() throws InterruptedException {
     }
 
     @Test
-    public void testPutThingWithInitialJSONPolicy() throws InterruptedException {
+    public void testPutThingWithInitialPolicyJson() throws InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
 
         messaging.onSend(m -> {
@@ -442,6 +456,12 @@ public void testPutThingWithInitialJSONPolicy() throws InterruptedException {
         Assertions.assertThat(latch.await(TIMEOUT, TIME_UNIT)).isTrue();
     }
 
+    @Test
+    public void testPutThingWithInitialPolicyJsonNull() {
+        assertThatExceptionOfType(IllegalArgumentException.class)
+                .isThrownBy(() -> client.twin().put(THING, (JsonObject) null));
+    }
+
     @Test
     public void testPutThingWithInitialPolicy() throws InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
@@ -460,6 +480,12 @@ public void testPutThingWithInitialPolicy() throws InterruptedException {
         Assertions.assertThat(latch.await(TIMEOUT, TIME_UNIT)).isTrue();
     }
 
+    @Test
+    public void testPutThingWithInitialPolicyNull() {
+        assertThatExceptionOfType(IllegalArgumentException.class)
+                .isThrownBy(() -> client.twin().put(THING, (Policy) null));
+    }
+
     @Test
     public void testCreateThingWithOptionCopyPolicy() throws InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);

From 4e6ecdc6fbcd8c8630e11bfbf0b3d9126f1fa810 Mon Sep 17 00:00:00 2001
From: Florian Fendt <Florian.Fendt@bosch.io>
Date: Mon, 16 Mar 2020 08:54:42 +0100
Subject: [PATCH 12/17] revert updating binary compatibility check version to
 1.1.0-M2 as the check should only be done against real releases

Signed-off-by: Florian Fendt <Florian.Fendt@bosch.io>
---
 java/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/java/pom.xml b/java/pom.xml
index 6fd8d62e..ba873ba8 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -233,7 +233,7 @@
         <!-- globally set version for checking binary compatibility against -->
         <!-- whoever changes this to ${revision} or ${project.version} is responsible for API breakage caused by this! -->
         <!-- in other words: never do that here! exclude the 'breakages' locally in the japicmp maven plugin if you intentionally break something -->
-        <binary-compatibility-check.version>1.1.0-M2</binary-compatibility-check.version>
+        <binary-compatibility-check.version>1.0.0</binary-compatibility-check.version>
         <!-- skip until first release: -->
         <binary-compatibility-check.skip>false</binary-compatibility-check.skip>
 

From 7cc1b8bd8505b0a70142e73a4efed2bd7067052c Mon Sep 17 00:00:00 2001
From: Florian Fendt <Florian.Fendt@bosch.io>
Date: Tue, 17 Mar 2020 10:38:32 +0100
Subject: [PATCH 13/17] use github action checkout@v2 to fix bug "fatal:
 reference is not a tree"

Signed-off-by: Florian Fendt <Florian.Fendt@bosch.io>
---
 .github/workflows/maven.yml  | 2 +-
 .github/workflows/nodejs.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 95efac6c..9afa5e17 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -23,7 +23,7 @@ jobs:
         java: [ '1.8' ]
 
     steps:
-    - uses: actions/checkout@v1
+    - uses: actions/checkout@v2
     - name: set up JDK ${{ matrix.java }}
       uses: actions/setup-java@v1
       with:
diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml
index 883361a7..37c3eadb 100644
--- a/.github/workflows/nodejs.yml
+++ b/.github/workflows/nodejs.yml
@@ -24,7 +24,7 @@ jobs:
         node-version: [10.x, 12.x]
 
     steps:
-    - uses: actions/checkout@v1
+    - uses: actions/checkout@v2
     - name: Use Node.js ${{ matrix.node-version }}
       uses: actions/setup-node@v1
       with:

From 33269b0b3f236bd1655a64a0120524c0e7067d01 Mon Sep 17 00:00:00 2001
From: Florian Fendt <Florian.Fendt@bosch.io>
Date: Tue, 17 Mar 2020 11:25:04 +0100
Subject: [PATCH 14/17] set ditto.version to ${revision}

Signed-off-by: Florian Fendt <Florian.Fendt@bosch.io>
---
 java/pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/java/pom.xml b/java/pom.xml
index b9174cae..41284a25 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -190,7 +190,7 @@
         <revision>0-SNAPSHOT</revision>
 
         <!-- ### Compile dependencies versions -->
-        <ditto.version>1.1.0-M2</ditto.version>
+        <ditto.version>${revision}</ditto.version>
         <minimal-json.version>0.9.5</minimal-json.version>
         <nv-websocket-client.version>2.9</nv-websocket-client.version>
         <classindex.version>3.8</classindex.version>
@@ -240,7 +240,7 @@
         <ditto.thirdPartyLicences.excludedGroups>
             (org\.eclipse\.ditto.*)
         </ditto.thirdPartyLicences.excludedGroups>
-        
+
         <sonar.coverage.jacoco.xmlReportPaths>${project.basedir}/target/site/jacoco/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
     </properties>
 

From 9a67b5c4a927ae3f207927d904dc1b7e00ef1f4c Mon Sep 17 00:00:00 2001
From: stmaute <stefan.maute@bosch.io>
Date: Tue, 7 Apr 2020 12:29:24 +0200
Subject: [PATCH 15/17] append ws path only if it isn't already appended;

Signed-off-by: stmaute <stefan.maute@bosch.io>
---
 .../WebSocketMessagingConfiguration.java      | 23 +++++++++++++++----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java b/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java
index 50cf7ae2..6b9f25ab 100755
--- a/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java
+++ b/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java
@@ -20,6 +20,8 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.annotation.Nullable;
 
@@ -81,6 +83,7 @@ private static final class WebSocketMessagingConfigurationBuilder implements Mes
 
         private static final List<String> ALLOWED_URI_SCHEME = Arrays.asList("wss", "ws");
         private static final String WS_PATH = "/ws/";
+        private static final String WS_URL_TEMPLATE = "/ws/%d";
 
         private JsonSchemaVersion jsonSchemaVersion = JsonSchemaVersion.LATEST;
         private URI endpointUri;
@@ -128,15 +131,25 @@ public MessagingConfiguration.Builder trustStoreConfiguration(
 
         @Override
         public MessagingConfiguration build() {
-            final URI wsEndpointUri = appendWsPath(this.endpointUri, jsonSchemaVersion);
+            final URI wsEndpointUri= appendWsPathIfNecessary(this.endpointUri, jsonSchemaVersion);
             return new WebSocketMessagingConfiguration(jsonSchemaVersion, wsEndpointUri, reconnectEnabled,
                     proxyConfiguration, trustStoreConfiguration);
         }
 
-        private static URI appendWsPath(final URI baseUri, final JsonSchemaVersion schemaVersion) {
-            final String pathWithoutTrailingSlashes = baseUri.getPath().replaceFirst("/+$", "");
-            final String newPath = pathWithoutTrailingSlashes + WS_PATH + schemaVersion.toString();
-            return baseUri.resolve(newPath);
+        private static URI appendWsPathIfNecessary(final URI baseUri, final JsonSchemaVersion schemaVersion) {
+            if (needToAppendWsPath(baseUri, schemaVersion)) {
+                final String pathWithoutTrailingSlashes = baseUri.getPath().replaceFirst("/+$", "");
+                final String newPath = pathWithoutTrailingSlashes + WS_PATH + schemaVersion.toString();
+                return baseUri.resolve(newPath);
+            } else {
+                return baseUri;
+            }
+        }
+
+        private static boolean needToAppendWsPath(final URI baseUri, final JsonSchemaVersion schemaVersion) {
+            final Pattern pattern = Pattern.compile(String.format(WS_URL_TEMPLATE, schemaVersion.toInt()));
+            final Matcher matcher = pattern.matcher(baseUri.toString());
+            return !matcher.find();
         }
 
     }

From 20a7449d9f80542f092adafb3cac80fd387a6bbb Mon Sep 17 00:00:00 2001
From: stmaute <stefan.maute@bosch.io>
Date: Tue, 7 Apr 2020 14:27:35 +0200
Subject: [PATCH 16/17] improved regex for ws path check;

Signed-off-by: stmaute <stefan.maute@bosch.io>
---
 .../configuration/WebSocketMessagingConfiguration.java    | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java b/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java
index 6b9f25ab..64406704 100755
--- a/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java
+++ b/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java
@@ -83,7 +83,7 @@ private static final class WebSocketMessagingConfigurationBuilder implements Mes
 
         private static final List<String> ALLOWED_URI_SCHEME = Arrays.asList("wss", "ws");
         private static final String WS_PATH = "/ws/";
-        private static final String WS_URL_TEMPLATE = "/ws/%d";
+        private static final String WS_PATH_REGEX = "/ws/(1|2)/?";
 
         private JsonSchemaVersion jsonSchemaVersion = JsonSchemaVersion.LATEST;
         private URI endpointUri;
@@ -137,7 +137,7 @@ public MessagingConfiguration build() {
         }
 
         private static URI appendWsPathIfNecessary(final URI baseUri, final JsonSchemaVersion schemaVersion) {
-            if (needToAppendWsPath(baseUri, schemaVersion)) {
+            if (needToAppendWsPath(baseUri)) {
                 final String pathWithoutTrailingSlashes = baseUri.getPath().replaceFirst("/+$", "");
                 final String newPath = pathWithoutTrailingSlashes + WS_PATH + schemaVersion.toString();
                 return baseUri.resolve(newPath);
@@ -146,8 +146,8 @@ private static URI appendWsPathIfNecessary(final URI baseUri, final JsonSchemaVe
             }
         }
 
-        private static boolean needToAppendWsPath(final URI baseUri, final JsonSchemaVersion schemaVersion) {
-            final Pattern pattern = Pattern.compile(String.format(WS_URL_TEMPLATE, schemaVersion.toInt()));
+        private static boolean needToAppendWsPath(final URI baseUri) {
+            final Pattern pattern = Pattern.compile(WS_PATH_REGEX);
             final Matcher matcher = pattern.matcher(baseUri.toString());
             return !matcher.find();
         }

From 892c59397ed9e2ff3d2c8f1ce4561eff57bb4574 Mon Sep 17 00:00:00 2001
From: stmaute <stefan.maute@bosch.io>
Date: Wed, 8 Apr 2020 09:59:42 +0200
Subject: [PATCH 17/17] check if schemaVerison and apiVersion in ws path match
 and throw IllegalArgumentException if not;

Signed-off-by: stmaute <stefan.maute@bosch.io>
---
 .../WebSocketMessagingConfiguration.java      | 26 ++++++++++++++-----
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java b/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java
index 64406704..849556c9 100755
--- a/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java
+++ b/java/src/main/java/org/eclipse/ditto/client/configuration/WebSocketMessagingConfiguration.java
@@ -12,9 +12,9 @@
  */
 package org.eclipse.ditto.client.configuration;
 
-import static org.eclipse.ditto.model.base.common.ConditionChecker.checkArgument;
-import static org.eclipse.ditto.model.base.common.ConditionChecker.checkNotNull;
+import org.eclipse.ditto.model.base.json.JsonSchemaVersion;
 
+import javax.annotation.Nullable;
 import java.net.URI;
 import java.text.MessageFormat;
 import java.util.Arrays;
@@ -23,9 +23,8 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import javax.annotation.Nullable;
-
-import org.eclipse.ditto.model.base.json.JsonSchemaVersion;
+import static org.eclipse.ditto.model.base.common.ConditionChecker.checkArgument;
+import static org.eclipse.ditto.model.base.common.ConditionChecker.checkNotNull;
 
 /**
  * Provides Ditto WebSocket messaging specific configuration.
@@ -138,10 +137,11 @@ public MessagingConfiguration build() {
 
         private static URI appendWsPathIfNecessary(final URI baseUri, final JsonSchemaVersion schemaVersion) {
             if (needToAppendWsPath(baseUri)) {
-                final String pathWithoutTrailingSlashes = baseUri.getPath().replaceFirst("/+$", "");
+                final String pathWithoutTrailingSlashes = removeTrailingSlashFromPath(baseUri.getPath());
                 final String newPath = pathWithoutTrailingSlashes + WS_PATH + schemaVersion.toString();
                 return baseUri.resolve(newPath);
             } else {
+                checkIfBaseUriAndSchemaVersionMatch(baseUri, schemaVersion);
                 return baseUri;
             }
         }
@@ -152,6 +152,20 @@ private static boolean needToAppendWsPath(final URI baseUri) {
             return !matcher.find();
         }
 
+        private static void checkIfBaseUriAndSchemaVersionMatch(final URI baseUri, final JsonSchemaVersion schemaVersion) {
+            final String path = removeTrailingSlashFromPath(baseUri.getPath());
+            final String apiVersion = path.substring(path.length() - 1, path.length());
+            if (!schemaVersion.toString().equals(apiVersion)) {
+                throw new IllegalArgumentException("The jsonSchemaVersion and apiVersion of the endpoint do not match. " +
+                        "Either remove the ws path from the endpoint or " +
+                        "use the same jsonSchemaVersion as in the ws path of the endpoint.");
+            }
+        }
+
+        private static String removeTrailingSlashFromPath(final String path) {
+            return path.replaceFirst("/+$", "");
+        }
+
     }
 
 }