From 35bfe4ae7d168c0b3729c2327760e84950e62c33 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Wed, 6 Aug 2025 14:16:50 -0700 Subject: [PATCH 1/5] initial deprecation placements --- .../awssdk/iot/AwsIotMqttClientBuilder.java | 348 ++++++++++++++++++ .../iot/AwsIotMqttConnectionBuilder.java | 60 +++ 2 files changed, 408 insertions(+) create mode 100644 sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttClientBuilder.java diff --git a/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttClientBuilder.java b/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttClientBuilder.java new file mode 100644 index 000000000..8ea302350 --- /dev/null +++ b/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttClientBuilder.java @@ -0,0 +1,348 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package software.amazon.awssdk.iot; + +import java.security.KeyStore; +import java.util.Objects; +import java.util.UUID; + +import software.amazon.awssdk.crt.auth.credentials.CredentialsProvider; +import software.amazon.awssdk.crt.http.HttpProxyOptions; +import software.amazon.awssdk.crt.io.ExponentialBackoffRetryOptions.JitterMode; +import software.amazon.awssdk.crt.io.SocketOptions; +import software.amazon.awssdk.crt.io.TlsContext; +import software.amazon.awssdk.crt.io.TlsContextCustomKeyOperationOptions; +import software.amazon.awssdk.crt.io.TlsContextOptions; +import software.amazon.awssdk.crt.io.TlsContextPkcs11Options; +import software.amazon.awssdk.crt.mqtt5.Mqtt5Client; +import software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions; +import software.amazon.awssdk.crt.mqtt5.TopicAliasingOptions; +import software.amazon.awssdk.crt.mqtt5.packets.ConnectPacket; + +/** + *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * + * Builder for making MQTT5 Clients with different connection methods for AWS IoT Core. + */ +public final class AwsIotMqttClientBuilder { + + private static final int PORT_MQTT = 8883; + private static final int PORT_WS = 443; + + /** + * Creates a new MQTT5 Client Builder that uses mTLS to connect. + * @param endpoint - AWS IoT endpoint to connect to + * @return - a new AwsIotMqttClientBuilder + */ + public static Builder newMtls(String endpoint) { + return new Builder(endpoint, PORT_MQTT, false); + } + + /** + * Creates a new MQTT5 Client Builder that will use websockets and AWS Sigv4 signing to establish + * mutually-authenticated (mTLS) connections. + * @param endpoint - AWS IoT endpoint to connect to + * @return - a new AwsIotMqttClientBuilder + */ + public static Builder newWebsocketSigV4Auth(String endpoint) { + return new Builder(endpoint, PORT_WS, true); + } + + public static final class Builder { + private final String endpoint; + private final int port; + private final boolean websocket; + + private WebsocketSigV4Options sigv4; + private TlsBuilderOptions tlsOptionsBuilder; + private ConnectOptions connect = ConnectOptions.defaults(); + + private ReconnectStrategy reconnect = ReconnectStrategy.fullJitter(); + private HttpProxyOptions proxy; + private SocketOptions socketOptions; + private TopicAliasingOptions topicAliasing; + private Mqtt5ClientOptions.ExtendedValidationAndFlowControlOptions extValidation = + Mqtt5ClientOptions.ExtendedValidationAndFlowControlOptions.AWS_IOT_CORE_DEFAULTS; + + private Mqtt5ClientOptions.LifecycleEvents lifecycleEvents; + private Mqtt5ClientOptions.PublishEvents publishEvents; + + private Builder(String endpoint, int port, boolean websocket) { + this.endpoint = Objects.requireNonNull(endpoint, "endpoint"); + this.port = port; + this.websocket = websocket; + } + + public Builder tlsOptions(TlsBuilderOptions tlsBuilderOptions) { + this.tlsOptionsBuilder = tlsBuilderOptions; + return this; + } + + public ConnectBuilder connect() { + return new ConnectBuilder(this); + } + + public Builder reconnect(ReconnectStrategy s) { + this.reconnect = s; + return this; + } + + public Builder proxy(HttpProxyOptions p) { + this.proxy = p; + return this; + } + + public Builder socketOptions(SocketOptions s) { + this.socketOptions = s; + return this; + } + public Builder topicAliasing(TopicAliasingOptions o) { + this.topicAliasing = o; + return this; + } + + public Builder extendedValidation(Mqtt5ClientOptions.ExtendedValidationAndFlowControlOptions o) { + this.extValidation = o; + return this; + } + + public Builder websocketSigning(WebsocketSigV4Options o) { + this.sigv4 = o; + return this; + } + + public Builder lifecycleEvents(Mqtt5ClientOptions.LifecycleEvents e) { + this.lifecycleEvents = e; + return this; + } + + public Builder publishEvents(Mqtt5ClientOptions.PublishEvents p) { + this.publishEvents = p; + return this; + } + + public Mqtt5Client build() { + if (websocket) { + Objects.requireNonNull(sigv4, "WebSocket transport requires SigV4 signing options"); + } else { + Objects.requireNonNull(tlsOptionsBuilder, "Mutual‑TLS transport requires TLS material"); + } + + Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder crt = + new Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder(endpoint, (long) port); + + if (tlsOptionsBuilder != null) { + crt.withTlsContext(tlsOptionsBuilder.toContext()); + } + connect.apply(crt); + reconnect.apply(crt); + + if (proxy != null) crt.withHttpProxyOptions(proxy); + if (socketOptions != null) crt.withSocketOptions(socketOptions); + if (topicAliasing != null) crt.withTopicAliasingOptions(topicAliasing); + crt.withExtendedValidationAndFlowControlOptions(extValidation); + if (lifecycleEvents != null) crt.withLifecycleEvents(lifecycleEvents); + if (publishEvents != null) crt.withPublishEvents(publishEvents); + + if (websocket) { + sigv4.apply(crt, endpoint); + } + + return new Mqtt5Client(crt.build()); + } + } + + /* ----- CHILD BUILDERS ------------------------------------------------ */ + + public static final class ConnectBuilder { + private final Builder parent; + private String clientId = UUID.randomUUID().toString(); + private long keepAlive = 1200; + + private ConnectBuilder(Builder parent) { + this.parent = parent; + } + + public ConnectBuilder clientId(String id) { + this.clientId = id; + return this; + } + + public ConnectBuilder keepAliveSeconds(long s) { + this.keepAlive=s; + return this; + } + + public Builder done() { + parent.connect = new ConnectOptions(clientId, keepAlive); + return parent; + } + } + + /* ----- VALUE OBJECTS ------------------------------------------------- */ + + public interface TlsBuilderOptions { + /** create the raw TlsContextOptions for this TLS type (no ALPN yet) */ + TlsContextOptions newOptions(); + + /** common implementation shared by every TlsContext Type */ + default TlsContext toContext() { + TlsContextOptions tlsCtxOptions = newOptions(); + + if (TlsContextOptions.isAlpnSupported()){ + tlsCtxOptions.withAlpnList("x-amzn-mqtt-ca"); + } + + try { + return new TlsContext(tlsCtxOptions); + } finally { + // we don’t need the options object after the context is built + tlsCtxOptions.close(); + } + } + } + + public static final class MtlsFromPath implements TlsBuilderOptions { + private final String certPath; + private final String keyPath; + + public MtlsFromPath(String certificatePath, String privateKeyPath) { + certPath = certificatePath; + keyPath = privateKeyPath; + } + + public TlsContextOptions newOptions() { + return TlsContextOptions.createWithMtlsFromPath(certPath, keyPath); + } + } + + public static final class MtlsFromMemory implements TlsBuilderOptions { + private final String certPem; + private final String keyPem; + + public MtlsFromMemory(String certificate,String privateKey) { + certPem = certificate; + keyPem = privateKey; + } + + public TlsContextOptions newOptions() { + return TlsContextOptions.createWithMtls(certPem, keyPem); + } + } + + public static final class Pkcs11 implements TlsBuilderOptions { + private final TlsContextPkcs11Options pkcs11Options; + + public Pkcs11(TlsContextPkcs11Options pkcs11Options) { + this.pkcs11Options = pkcs11Options; + } + + public TlsContextOptions newOptions() { + return TlsContextOptions.createWithMtlsPkcs11(pkcs11Options); + } + } + + public static final class CustomKeyOps implements TlsBuilderOptions { + private final TlsContextCustomKeyOperationOptions operationOptions; + + public CustomKeyOps(TlsContextCustomKeyOperationOptions operationOptions) { + this.operationOptions = operationOptions; + } + + public TlsContextOptions newOptions() { + return TlsContextOptions.createWithMtlsCustomKeyOperations(operationOptions); + } + } + + public static final class WindowsCertStore implements TlsBuilderOptions { + private final String path; + public WindowsCertStore(String certificatePath) { + path = certificatePath; + } + + public TlsContextOptions newOptions() { + return TlsContextOptions.createWithMtlsWindowsCertStorePath(path); + } + } + + public static final class JavaKeystore implements TlsBuilderOptions { + private final KeyStore ks; + private final String alias; + private final String pwd; + public JavaKeystore(KeyStore k,String a, String p) { + ks = k; + alias = a; + pwd = p; + } + + public TlsContextOptions newOptions() { + return TlsContextOptions.createWithMtlsJavaKeystore(ks,alias,pwd); + } + } + + public static final class Pkcs12 implements TlsBuilderOptions { + private final String path; + private final String pwd; + public Pkcs12(String p, String w) { + path = p; + pwd = w; + } + + public TlsContextOptions newOptions() { + return TlsContextOptions.createWithMtlsPkcs12(path,pwd); + } + } + + + public static final class ConnectOptions { + private final String clientId; + private final long keepAliveSeconds; + + ConnectOptions(String clientId,long keepAliveSeconds) { + this.clientId = clientId; + this.keepAliveSeconds = keepAliveSeconds; + } + + static ConnectOptions defaults() { + return new ConnectOptions(null,1200); + } + + void apply(Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder clientOptionsBuilder) { + ConnectPacket.ConnectPacketBuilder connectPacket = new ConnectPacket.ConnectPacketBuilder(); + if(clientId != null) { + connectPacket.withClientId(clientId); + } + connectPacket.withKeepAliveIntervalSeconds(keepAliveSeconds); + clientOptionsBuilder.withConnectOptions(connectPacket.build()); + } + } + + public static final class ReconnectStrategy { + private final long minDelay; + private final long maxDelay; + private final JitterMode jitter; + ReconnectStrategy(long min,long max,JitterMode j) { + minDelay=min;maxDelay=max;jitter=j; + } + static ReconnectStrategy fullJitter() { + return new ReconnectStrategy(100,60_000,JitterMode.Full); + } + void apply(Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder b) { + b.withMinReconnectDelayMs(minDelay); + b.withMaxReconnectDelayMs(maxDelay); + b.withRetryJitterMode(jitter); + } + } + + public static final class WebsocketSigV4Options { + private final CredentialsProvider provider; private final String region; + public WebsocketSigV4Options(CredentialsProvider p,String r){provider=p;region=r;} + void apply(Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder crt,String endpoint){/* TODO */} + } +} diff --git a/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java b/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java index 085c3ae25..c4cb643ba 100644 --- a/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java +++ b/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java @@ -38,6 +38,12 @@ import software.amazon.awssdk.crt.mqtt.WebsocketHandshakeTransformArgs; /** +*

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * * A central class for building Mqtt connections without manually managing a large variety of native objects (some * still need to be created though). */ @@ -98,6 +104,12 @@ protected void releaseNativeHandle() {} /** + *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * * Create a new builder with mTLS file paths * * @param certPath - Path to certificate, in PEM format @@ -111,6 +123,12 @@ public static AwsIotMqttConnectionBuilder newMtlsBuilderFromPath(String certPath } /** + *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * * Create a new builder with mTLS cert pair in memory * * @param certificate - Certificate, in PEM format @@ -124,6 +142,12 @@ public static AwsIotMqttConnectionBuilder newMtlsBuilder(String certificate, Str } /** + *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * * Create a new builder with mTLS cert pair in memory * * @param certificate - Certificate, in PEM format @@ -137,6 +161,12 @@ public static AwsIotMqttConnectionBuilder newMtlsBuilder(byte[] certificate, byt } /** + *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * * Create a new builder with mTLS, using a PKCS#11 library for private key operations. * * NOTE: Unix only @@ -151,6 +181,12 @@ public static AwsIotMqttConnectionBuilder newMtlsPkcs11Builder(TlsContextPkcs11O } /** + *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * * Create a new builder with mTLS, using a custom handler for private key operations. * * @param operationOptions options for using a custom handler @@ -163,6 +199,12 @@ public static AwsIotMqttConnectionBuilder newMtlsCustomKeyOperationsBuilder(TlsC } /** + *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * * Create a new builder with mTLS, using a certificate in a Windows certificate store. * * NOTE: Windows only @@ -181,6 +223,12 @@ public static AwsIotMqttConnectionBuilder newMtlsWindowsCertStorePathBuilder(Str } /** + *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * * Create a new builder with mTLS, using a certificate and key stored in the passed-in Java keystore. * * Note: function assumes the passed keystore has already been loaded from a file by calling "keystore.load(file, password)" @@ -200,6 +248,12 @@ public static AwsIotMqttConnectionBuilder newJavaKeystoreBuilder( } /** + *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * * Create a new builder with mTLS, using a PKCS12 library for private key operations. * * NOTE: MacOS only @@ -216,6 +270,12 @@ public static AwsIotMqttConnectionBuilder newMtlsPkcs12Builder( } /** + *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

+ * + *

The MQTT 3.1.1 client remains fully supported, but migrating to + * MQTT 5 gives you a richer feature set, clearer error handling, and + * improved lifetime management.

+ * * Create a new builder with no default Tls options * * @return a new builder with default Tls options From 3d037c9b5660dfebf7ae125591c588b5d380b698 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Thu, 7 Aug 2025 10:22:08 -0700 Subject: [PATCH 2/5] add @Deprecated tag to AwsIotMqttConnectionBuilder --- .../software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java b/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java index c4cb643ba..70279909b 100644 --- a/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java +++ b/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java @@ -47,6 +47,7 @@ * A central class for building Mqtt connections without manually managing a large variety of native objects (some * still need to be created though). */ +@Deprecated public final class AwsIotMqttConnectionBuilder extends CrtResource { private static String IOT_SIGNING_SERVICE = "iotdevicegateway"; From fb39bf5ddc21923311b3e2944c5fea83eaeaf45d Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 11 Aug 2025 13:45:27 -0700 Subject: [PATCH 3/5] remove the WIP AwsIotMqttClientBuilder.java file --- .../awssdk/iot/AwsIotMqttClientBuilder.java | 348 ------------------ 1 file changed, 348 deletions(-) delete mode 100644 sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttClientBuilder.java diff --git a/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttClientBuilder.java b/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttClientBuilder.java deleted file mode 100644 index 8ea302350..000000000 --- a/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttClientBuilder.java +++ /dev/null @@ -1,348 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ -package software.amazon.awssdk.iot; - -import java.security.KeyStore; -import java.util.Objects; -import java.util.UUID; - -import software.amazon.awssdk.crt.auth.credentials.CredentialsProvider; -import software.amazon.awssdk.crt.http.HttpProxyOptions; -import software.amazon.awssdk.crt.io.ExponentialBackoffRetryOptions.JitterMode; -import software.amazon.awssdk.crt.io.SocketOptions; -import software.amazon.awssdk.crt.io.TlsContext; -import software.amazon.awssdk.crt.io.TlsContextCustomKeyOperationOptions; -import software.amazon.awssdk.crt.io.TlsContextOptions; -import software.amazon.awssdk.crt.io.TlsContextPkcs11Options; -import software.amazon.awssdk.crt.mqtt5.Mqtt5Client; -import software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions; -import software.amazon.awssdk.crt.mqtt5.TopicAliasingOptions; -import software.amazon.awssdk.crt.mqtt5.packets.ConnectPacket; - -/** - *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

- * - * Builder for making MQTT5 Clients with different connection methods for AWS IoT Core. - */ -public final class AwsIotMqttClientBuilder { - - private static final int PORT_MQTT = 8883; - private static final int PORT_WS = 443; - - /** - * Creates a new MQTT5 Client Builder that uses mTLS to connect. - * @param endpoint - AWS IoT endpoint to connect to - * @return - a new AwsIotMqttClientBuilder - */ - public static Builder newMtls(String endpoint) { - return new Builder(endpoint, PORT_MQTT, false); - } - - /** - * Creates a new MQTT5 Client Builder that will use websockets and AWS Sigv4 signing to establish - * mutually-authenticated (mTLS) connections. - * @param endpoint - AWS IoT endpoint to connect to - * @return - a new AwsIotMqttClientBuilder - */ - public static Builder newWebsocketSigV4Auth(String endpoint) { - return new Builder(endpoint, PORT_WS, true); - } - - public static final class Builder { - private final String endpoint; - private final int port; - private final boolean websocket; - - private WebsocketSigV4Options sigv4; - private TlsBuilderOptions tlsOptionsBuilder; - private ConnectOptions connect = ConnectOptions.defaults(); - - private ReconnectStrategy reconnect = ReconnectStrategy.fullJitter(); - private HttpProxyOptions proxy; - private SocketOptions socketOptions; - private TopicAliasingOptions topicAliasing; - private Mqtt5ClientOptions.ExtendedValidationAndFlowControlOptions extValidation = - Mqtt5ClientOptions.ExtendedValidationAndFlowControlOptions.AWS_IOT_CORE_DEFAULTS; - - private Mqtt5ClientOptions.LifecycleEvents lifecycleEvents; - private Mqtt5ClientOptions.PublishEvents publishEvents; - - private Builder(String endpoint, int port, boolean websocket) { - this.endpoint = Objects.requireNonNull(endpoint, "endpoint"); - this.port = port; - this.websocket = websocket; - } - - public Builder tlsOptions(TlsBuilderOptions tlsBuilderOptions) { - this.tlsOptionsBuilder = tlsBuilderOptions; - return this; - } - - public ConnectBuilder connect() { - return new ConnectBuilder(this); - } - - public Builder reconnect(ReconnectStrategy s) { - this.reconnect = s; - return this; - } - - public Builder proxy(HttpProxyOptions p) { - this.proxy = p; - return this; - } - - public Builder socketOptions(SocketOptions s) { - this.socketOptions = s; - return this; - } - public Builder topicAliasing(TopicAliasingOptions o) { - this.topicAliasing = o; - return this; - } - - public Builder extendedValidation(Mqtt5ClientOptions.ExtendedValidationAndFlowControlOptions o) { - this.extValidation = o; - return this; - } - - public Builder websocketSigning(WebsocketSigV4Options o) { - this.sigv4 = o; - return this; - } - - public Builder lifecycleEvents(Mqtt5ClientOptions.LifecycleEvents e) { - this.lifecycleEvents = e; - return this; - } - - public Builder publishEvents(Mqtt5ClientOptions.PublishEvents p) { - this.publishEvents = p; - return this; - } - - public Mqtt5Client build() { - if (websocket) { - Objects.requireNonNull(sigv4, "WebSocket transport requires SigV4 signing options"); - } else { - Objects.requireNonNull(tlsOptionsBuilder, "Mutual‑TLS transport requires TLS material"); - } - - Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder crt = - new Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder(endpoint, (long) port); - - if (tlsOptionsBuilder != null) { - crt.withTlsContext(tlsOptionsBuilder.toContext()); - } - connect.apply(crt); - reconnect.apply(crt); - - if (proxy != null) crt.withHttpProxyOptions(proxy); - if (socketOptions != null) crt.withSocketOptions(socketOptions); - if (topicAliasing != null) crt.withTopicAliasingOptions(topicAliasing); - crt.withExtendedValidationAndFlowControlOptions(extValidation); - if (lifecycleEvents != null) crt.withLifecycleEvents(lifecycleEvents); - if (publishEvents != null) crt.withPublishEvents(publishEvents); - - if (websocket) { - sigv4.apply(crt, endpoint); - } - - return new Mqtt5Client(crt.build()); - } - } - - /* ----- CHILD BUILDERS ------------------------------------------------ */ - - public static final class ConnectBuilder { - private final Builder parent; - private String clientId = UUID.randomUUID().toString(); - private long keepAlive = 1200; - - private ConnectBuilder(Builder parent) { - this.parent = parent; - } - - public ConnectBuilder clientId(String id) { - this.clientId = id; - return this; - } - - public ConnectBuilder keepAliveSeconds(long s) { - this.keepAlive=s; - return this; - } - - public Builder done() { - parent.connect = new ConnectOptions(clientId, keepAlive); - return parent; - } - } - - /* ----- VALUE OBJECTS ------------------------------------------------- */ - - public interface TlsBuilderOptions { - /** create the raw TlsContextOptions for this TLS type (no ALPN yet) */ - TlsContextOptions newOptions(); - - /** common implementation shared by every TlsContext Type */ - default TlsContext toContext() { - TlsContextOptions tlsCtxOptions = newOptions(); - - if (TlsContextOptions.isAlpnSupported()){ - tlsCtxOptions.withAlpnList("x-amzn-mqtt-ca"); - } - - try { - return new TlsContext(tlsCtxOptions); - } finally { - // we don’t need the options object after the context is built - tlsCtxOptions.close(); - } - } - } - - public static final class MtlsFromPath implements TlsBuilderOptions { - private final String certPath; - private final String keyPath; - - public MtlsFromPath(String certificatePath, String privateKeyPath) { - certPath = certificatePath; - keyPath = privateKeyPath; - } - - public TlsContextOptions newOptions() { - return TlsContextOptions.createWithMtlsFromPath(certPath, keyPath); - } - } - - public static final class MtlsFromMemory implements TlsBuilderOptions { - private final String certPem; - private final String keyPem; - - public MtlsFromMemory(String certificate,String privateKey) { - certPem = certificate; - keyPem = privateKey; - } - - public TlsContextOptions newOptions() { - return TlsContextOptions.createWithMtls(certPem, keyPem); - } - } - - public static final class Pkcs11 implements TlsBuilderOptions { - private final TlsContextPkcs11Options pkcs11Options; - - public Pkcs11(TlsContextPkcs11Options pkcs11Options) { - this.pkcs11Options = pkcs11Options; - } - - public TlsContextOptions newOptions() { - return TlsContextOptions.createWithMtlsPkcs11(pkcs11Options); - } - } - - public static final class CustomKeyOps implements TlsBuilderOptions { - private final TlsContextCustomKeyOperationOptions operationOptions; - - public CustomKeyOps(TlsContextCustomKeyOperationOptions operationOptions) { - this.operationOptions = operationOptions; - } - - public TlsContextOptions newOptions() { - return TlsContextOptions.createWithMtlsCustomKeyOperations(operationOptions); - } - } - - public static final class WindowsCertStore implements TlsBuilderOptions { - private final String path; - public WindowsCertStore(String certificatePath) { - path = certificatePath; - } - - public TlsContextOptions newOptions() { - return TlsContextOptions.createWithMtlsWindowsCertStorePath(path); - } - } - - public static final class JavaKeystore implements TlsBuilderOptions { - private final KeyStore ks; - private final String alias; - private final String pwd; - public JavaKeystore(KeyStore k,String a, String p) { - ks = k; - alias = a; - pwd = p; - } - - public TlsContextOptions newOptions() { - return TlsContextOptions.createWithMtlsJavaKeystore(ks,alias,pwd); - } - } - - public static final class Pkcs12 implements TlsBuilderOptions { - private final String path; - private final String pwd; - public Pkcs12(String p, String w) { - path = p; - pwd = w; - } - - public TlsContextOptions newOptions() { - return TlsContextOptions.createWithMtlsPkcs12(path,pwd); - } - } - - - public static final class ConnectOptions { - private final String clientId; - private final long keepAliveSeconds; - - ConnectOptions(String clientId,long keepAliveSeconds) { - this.clientId = clientId; - this.keepAliveSeconds = keepAliveSeconds; - } - - static ConnectOptions defaults() { - return new ConnectOptions(null,1200); - } - - void apply(Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder clientOptionsBuilder) { - ConnectPacket.ConnectPacketBuilder connectPacket = new ConnectPacket.ConnectPacketBuilder(); - if(clientId != null) { - connectPacket.withClientId(clientId); - } - connectPacket.withKeepAliveIntervalSeconds(keepAliveSeconds); - clientOptionsBuilder.withConnectOptions(connectPacket.build()); - } - } - - public static final class ReconnectStrategy { - private final long minDelay; - private final long maxDelay; - private final JitterMode jitter; - ReconnectStrategy(long min,long max,JitterMode j) { - minDelay=min;maxDelay=max;jitter=j; - } - static ReconnectStrategy fullJitter() { - return new ReconnectStrategy(100,60_000,JitterMode.Full); - } - void apply(Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder b) { - b.withMinReconnectDelayMs(minDelay); - b.withMaxReconnectDelayMs(maxDelay); - b.withRetryJitterMode(jitter); - } - } - - public static final class WebsocketSigV4Options { - private final CredentialsProvider provider; private final String region; - public WebsocketSigV4Options(CredentialsProvider p,String r){provider=p;region=r;} - void apply(Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder crt,String endpoint){/* TODO */} - } -} From 7c5e6e6cca71314da31f8dffeb502c2c6280279a Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Wed, 13 Aug 2025 08:38:48 -0700 Subject: [PATCH 4/5] update deprecation text --- .../iot/AwsIotMqttConnectionBuilder.java | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java b/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java index 70279909b..8a7d9436c 100644 --- a/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java +++ b/sdk/src/main/java/software/amazon/awssdk/iot/AwsIotMqttConnectionBuilder.java @@ -38,11 +38,11 @@ import software.amazon.awssdk.crt.mqtt.WebsocketHandshakeTransformArgs; /** -*

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

+ *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder}.

+ * + *

There are no current plans to fully deprecate the MQTT 3.1.1 client but it is highly recommended + * customers migrate to the MQTT5 client to access a more robust feature set, clearer error handling, + * and lifetime management. More details can be found in the GitHub Repo FAQ

* * A central class for building Mqtt connections without manually managing a large variety of native objects (some * still need to be created though). @@ -105,11 +105,11 @@ protected void releaseNativeHandle() {} /** - *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

+ *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder}.

+ * + *

There are no current plans to fully deprecate the MQTT 3.1.1 client but it is highly recommended + * customers migrate to the MQTT5 client to access a more robust feature set, clearer error handling, + * and lifetime management. More details can be found in the GitHub Repo FAQ

* * Create a new builder with mTLS file paths * @@ -124,11 +124,11 @@ public static AwsIotMqttConnectionBuilder newMtlsBuilderFromPath(String certPath } /** - *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

+ *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder}.

+ * + *

There are no current plans to fully deprecate the MQTT 3.1.1 client but it is highly recommended + * customers migrate to the MQTT5 client to access a more robust feature set, clearer error handling, + * and lifetime management. More details can be found in the GitHub Repo FAQ

* * Create a new builder with mTLS cert pair in memory * @@ -143,11 +143,11 @@ public static AwsIotMqttConnectionBuilder newMtlsBuilder(String certificate, Str } /** - *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

+ *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder}.

+ * + *

There are no current plans to fully deprecate the MQTT 3.1.1 client but it is highly recommended + * customers migrate to the MQTT5 client to access a more robust feature set, clearer error handling, + * and lifetime management. More details can be found in the GitHub Repo FAQ

* * Create a new builder with mTLS cert pair in memory * @@ -162,11 +162,11 @@ public static AwsIotMqttConnectionBuilder newMtlsBuilder(byte[] certificate, byt } /** - *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

+ *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder}.

+ * + *

There are no current plans to fully deprecate the MQTT 3.1.1 client but it is highly recommended + * customers migrate to the MQTT5 client to access a more robust feature set, clearer error handling, + * and lifetime management. More details can be found in the GitHub Repo FAQ

* * Create a new builder with mTLS, using a PKCS#11 library for private key operations. * @@ -182,11 +182,11 @@ public static AwsIotMqttConnectionBuilder newMtlsPkcs11Builder(TlsContextPkcs11O } /** - *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

+ *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder}.

+ * + *

There are no current plans to fully deprecate the MQTT 3.1.1 client but it is highly recommended + * customers migrate to the MQTT5 client to access a more robust feature set, clearer error handling, + * and lifetime management. More details can be found in the GitHub Repo FAQ

* * Create a new builder with mTLS, using a custom handler for private key operations. * @@ -200,11 +200,11 @@ public static AwsIotMqttConnectionBuilder newMtlsCustomKeyOperationsBuilder(TlsC } /** - *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

+ *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder}.

+ * + *

There are no current plans to fully deprecate the MQTT 3.1.1 client but it is highly recommended + * customers migrate to the MQTT5 client to access a more robust feature set, clearer error handling, + * and lifetime management. More details can be found in the GitHub Repo FAQ

* * Create a new builder with mTLS, using a certificate in a Windows certificate store. * @@ -224,11 +224,11 @@ public static AwsIotMqttConnectionBuilder newMtlsWindowsCertStorePathBuilder(Str } /** - *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

+ *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder}.

+ * + *

There are no current plans to fully deprecate the MQTT 3.1.1 client but it is highly recommended + * customers migrate to the MQTT5 client to access a more robust feature set, clearer error handling, + * and lifetime management. More details can be found in the GitHub Repo FAQ

* * Create a new builder with mTLS, using a certificate and key stored in the passed-in Java keystore. * @@ -249,11 +249,11 @@ public static AwsIotMqttConnectionBuilder newJavaKeystoreBuilder( } /** - *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

+ *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder}.

+ * + *

There are no current plans to fully deprecate the MQTT 3.1.1 client but it is highly recommended + * customers migrate to the MQTT5 client to access a more robust feature set, clearer error handling, + * and lifetime management. More details can be found in the GitHub Repo FAQ

* * Create a new builder with mTLS, using a PKCS12 library for private key operations. * @@ -271,11 +271,11 @@ public static AwsIotMqttConnectionBuilder newMtlsPkcs12Builder( } /** - *

Deprecated. Use {@link software.amazon.awssdk.crt.mqtt5.Mqtt5Client} instead.

- * - *

The MQTT 3.1.1 client remains fully supported, but migrating to - * MQTT 5 gives you a richer feature set, clearer error handling, and - * improved lifetime management.

+ *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder}.

+ * + *

There are no current plans to fully deprecate the MQTT 3.1.1 client but it is highly recommended + * customers migrate to the MQTT5 client to access a more robust feature set, clearer error handling, + * and lifetime management. More details can be found in the GitHub Repo FAQ

* * Create a new builder with no default Tls options * From cb39158153019dfcd3f0db5c9c2675b1f3ec1045 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Thu, 14 Aug 2025 14:30:33 -0700 Subject: [PATCH 5/5] service client deprecation --- .../amazon/awssdk/iot/iotidentity/IotIdentityClient.java | 6 ++++++ .../software/amazon/awssdk/iot/iotjobs/IotJobsClient.java | 6 ++++++ .../amazon/awssdk/iot/iotshadow/IotShadowClient.java | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/sdk/src/main/java/software/amazon/awssdk/iot/iotidentity/IotIdentityClient.java b/sdk/src/main/java/software/amazon/awssdk/iot/iotidentity/IotIdentityClient.java index 15642f55b..cde478b06 100644 --- a/sdk/src/main/java/software/amazon/awssdk/iot/iotidentity/IotIdentityClient.java +++ b/sdk/src/main/java/software/amazon/awssdk/iot/iotidentity/IotIdentityClient.java @@ -38,11 +38,17 @@ import java.util.function.Consumer; /** + *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.iotidentity.IotIdentityV2Client }.

+ * + *

There are no current plans to ully deprecate IotIdentityClient but it is highly recommended customers + * migrate to IotIdentityV2Client. More details can be found in the GitHub Repo FAQ.

+ * * An AWS IoT service that assists with provisioning a device and installing unique client certificates on it * * AWS documentation: https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html * */ +@Deprecated public class IotIdentityClient { private MqttClientConnection connection = null; private final Gson gson = getGson(); diff --git a/sdk/src/main/java/software/amazon/awssdk/iot/iotjobs/IotJobsClient.java b/sdk/src/main/java/software/amazon/awssdk/iot/iotjobs/IotJobsClient.java index d0acac1ec..02583ec7b 100644 --- a/sdk/src/main/java/software/amazon/awssdk/iot/iotjobs/IotJobsClient.java +++ b/sdk/src/main/java/software/amazon/awssdk/iot/iotjobs/IotJobsClient.java @@ -50,11 +50,17 @@ import java.util.function.Consumer; /** + *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.iotjobs.IotJobsV2Client }.

+ * + *

There are no current plans to ully deprecate IotJobsClient but it is highly recommended customers + * migrate to IotJobsV2Client. More details can be found in the GitHub Repo FAQ.

+ * * The AWS IoT jobs service can be used to define a set of remote operations that are sent to and executed on one or more devices connected to AWS IoT. * * AWS documentation: https://docs.aws.amazon.com/iot/latest/developerguide/jobs-api.html#jobs-mqtt-api * */ +@Deprecated public class IotJobsClient { private MqttClientConnection connection = null; private final Gson gson = getGson(); diff --git a/sdk/src/main/java/software/amazon/awssdk/iot/iotshadow/IotShadowClient.java b/sdk/src/main/java/software/amazon/awssdk/iot/iotshadow/IotShadowClient.java index fd441dfab..03f64a854 100644 --- a/sdk/src/main/java/software/amazon/awssdk/iot/iotshadow/IotShadowClient.java +++ b/sdk/src/main/java/software/amazon/awssdk/iot/iotshadow/IotShadowClient.java @@ -56,11 +56,17 @@ import java.util.function.Consumer; /** + *

Deprecated. We strongly recommend using {@link software.amazon.awssdk.iot.iotshadow.IotShadowV2Client }.

+ * + *

There are no current plans to ully deprecate IotShadowClient but it is highly recommended customers + * migrate to IotShadowV2Client. More details can be found in the GitHub Repo FAQ.

+ * * The AWS IoT Device Shadow service adds shadows to AWS IoT thing objects. Shadows are a simple data store for device properties and state. Shadows can make a device’s state available to apps and other services whether the device is connected to AWS IoT or not. * * AWS documentation: https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html * */ +@Deprecated public class IotShadowClient { private MqttClientConnection connection = null; private final Gson gson = getGson();