Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request response binding #852

Open
wants to merge 13 commits into
base: RequestResponseWorkspace
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

package software.amazon.awssdk.crt.iot;

/**
* Encapsulates a response to an AWS IoT Core MQTT-based service request
*/
public class MqttRequestResponse {

private String topic;
private byte[] payload;

private MqttRequestResponse() {
}

/**
* Gets the MQTT topic that the response was received on.
*
* Different topics map to different types within the
* service model, so we need this value in order to know what to deserialize the payload into.
*
* @return the MQTT topic that the response was received on
*/
public String getTopic() {
return topic;
}

/**
* Gets the payload of the response that correlates to a submitted request.
*
* @return Payload of the response that correlates to a submitted request.
*/
public byte[] getPayload() {
return payload;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import software.amazon.awssdk.crt.mqtt.MqttClientConnection;
import software.amazon.awssdk.crt.mqtt5.Mqtt5Client;

import java.util.concurrent.CompletableFuture;

/**
* A helper class for AWS service clients that use MQTT as the transport protocol.
*
Expand All @@ -20,7 +22,13 @@
*/
public class MqttRequestResponseClient extends CrtResource {

public MqttRequestResponseClient(Mqtt5Client client, MqttRequestResponseClientBuilder.MqttRequestResponseClientOptions options) throws CrtRuntimeException {
/**
* MQTT5-based constructor for request-response service clients
*
* @param client MQTT5 client that the request-response client should use as transport
* @param options request-response client configuration options
*/
public MqttRequestResponseClient(Mqtt5Client client, MqttRequestResponseClientBuilder.MqttRequestResponseClientOptions options) {
acquireNativeHandle(mqttRequestResponseClientNewFrom5(
this,
client.getNativeHandle(),
Expand All @@ -30,7 +38,13 @@ public MqttRequestResponseClient(Mqtt5Client client, MqttRequestResponseClientBu
));
}

public MqttRequestResponseClient(MqttClientConnection client, MqttRequestResponseClientBuilder.MqttRequestResponseClientOptions options) throws CrtRuntimeException {
/**
* MQTT311-based constructor for request-response service clients
*
* @param client MQTT311 client that the request-response client should use as transport
* @param options request-response client configuration options
*/
public MqttRequestResponseClient(MqttClientConnection client, MqttRequestResponseClientBuilder.MqttRequestResponseClientOptions options) {
acquireNativeHandle(mqttRequestResponseClientNewFrom311(
this,
client.getNativeHandle(),
Expand All @@ -40,6 +54,21 @@ public MqttRequestResponseClient(MqttClientConnection client, MqttRequestRespons
));
}

/**
* Submits a request to the request-response client.
*
* @param request description of the request to perform
*
* @return future that completes with the result of performing the request
*/
public CompletableFuture<MqttRequestResponse> submitRequest(RequestResponseOperation request) {
CompletableFuture<MqttRequestResponse> future = new CompletableFuture<>();

mqttRequestResponseClientSubmitRequest(getNativeHandle(), request, future);

return future;
}

/**
* Cleans up the native resources associated with this client. The client is unusable after this call
*/
Expand Down Expand Up @@ -78,4 +107,7 @@ private static native long mqttRequestResponseClientNewFrom311(
) throws CrtRuntimeException;

private static native void mqttRequestResponseClientDestroy(long client);

private static native void mqttRequestResponseClientSubmitRequest(long client, RequestResponseOperation request, CompletableFuture<MqttRequestResponse> future);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

package software.amazon.awssdk.crt.iot;

import java.util.ArrayList;

/**
* Configuration options for an MQTT-based request-response operation.
*/
public class RequestResponseOperation {

/**
* Builder class for RequestResponseOperation instances
*/
public static class RequestResponseOperationBuilder {

private RequestResponseOperation request = new RequestResponseOperation();

private RequestResponseOperationBuilder() {}

/**
* Adds a response path to the set of all possible response paths associated with this request.
*
* @param path response paths to associate with this request
*
* @return the builder object
*/
public RequestResponseOperationBuilder withResponsePath(ResponsePath path) {
request.responsePaths.add(path);
return this;
}

/**
* Adds a topic filter to the set of topic filters that should be subscribed to in order to cover all possible
* response paths. Sometimes using wildcards can cut down on the subscriptions needed; other times that isn't
* possible to do correctly.
*
* @param topicFilter topic filter to subscribe to in order to cover one or more response paths
*
* @return the builder object
*/
public RequestResponseOperationBuilder withSubscription(String topicFilter) {
request.subscriptions.add(topicFilter);
return this;
}

/**
* Sets the topic to publish the request to once response subscriptions have been established.
*
* @param publishTopic topic to publish the request to once response subscriptions have been established
*
* @return the builder object
*/
public RequestResponseOperationBuilder withPublishTopic(String publishTopic) {
request.publishTopic = publishTopic;
return this;
}

/**
* Sets the payload to publish to 'publishTopic' in order to initiate the request.
*
* @param payload payload to publish to 'publishTopic' in order to initiate the request
*
* @return the builder object
*/
public RequestResponseOperationBuilder withPayload(byte[] payload) {
request.payload = payload;
return this;
}

/**
* Sets the correlation token embedded in the request that must be found in a response message.
*
* This can be null to support certain services which don't use correlation tokens. In that case, the client
* only allows one token-less request at a time.
*
* @param correlationToken the correlation token embedded in the request that must be found in a response message
*
* @return the builder object
*/
public RequestResponseOperationBuilder withCorrelationToken(String correlationToken) {
request.correlationToken = correlationToken;
return this;
}

/**
* Creates a new RequestResponseOperation instance based on the builder's configuration.
*
* @return a new RequestResponseOperation instance based on the builder's configuration
*/
public RequestResponseOperation build() {
return new RequestResponseOperation(request);
}
}

private ArrayList<ResponsePath> responsePaths = new ArrayList<>();
private ArrayList<String> subscriptions = new ArrayList<>();
private String publishTopic;
private String correlationToken;
private byte[] payload;

private RequestResponseOperation() {
}

private RequestResponseOperation(RequestResponseOperation request) {
this.responsePaths.addAll(request.responsePaths);
this.subscriptions.addAll(request.subscriptions);
this.publishTopic = request.publishTopic;
this.correlationToken = request.correlationToken;
this.payload = request.payload;
}

/**
* Creates a new builder for RequestResponseOperations objects
*
* @return a new builder instance for RequestResponseOperations objects
*/
public static RequestResponseOperationBuilder builder() {
return new RequestResponseOperationBuilder();
}

}
77 changes: 77 additions & 0 deletions src/main/java/software/amazon/awssdk/crt/iot/ResponsePath.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

package software.amazon.awssdk.crt.iot;

/**
* A response path is a pair of values - MQTT topic and a JSON path - that describe how a response to
* an MQTT-based request may arrive. For a given request type, there may be multiple response paths and each
* one is associated with a separate JSON schema for the response body.
*/
public class ResponsePath {

/**
* Builder type for ResponsePath instances
*/
public static class ResponsePathBuilder {

private ResponsePath path = new ResponsePath();

private ResponsePathBuilder() {}

/**
* Fluent setter for the MQTT topic associated with this response path.
*
* @param responseTopic MQTT topic associated with this response path
*
* @return the builder object
*/
public ResponsePathBuilder withResponseTopic(String responseTopic) {
path.responseTopic = responseTopic;
return this;
}

/**
* Fluent setter for the JSON path for finding correlation tokens within payloads that arrive on this response path's topic.
*
* @param correlationTokenJsonPath JSON path for finding correlation tokens within payloads that arrive on this response path's topic
*
* @return the builder object
*/
public ResponsePathBuilder withCorrelationTokenJsonPath(String correlationTokenJsonPath) {
path.correlationTokenJsonPath = correlationTokenJsonPath;
return this;
}

/**
* Creates a new ResponsePath instance based on the builder's configuration.
*
* @return a new ResponsePath instance based on the builder's configuration
*/
public ResponsePath build() {
return new ResponsePath(path);
}
}

private String responseTopic;
private String correlationTokenJsonPath;

private ResponsePath() {
}

private ResponsePath(ResponsePath path) {
this.responseTopic = path.responseTopic;
this.correlationTokenJsonPath = path.correlationTokenJsonPath;
}

/**
* Creates a new builder instance for ResponsePath instances.
*
* @return a new builder instance for ResponsePath instances
*/
public static ResponsePathBuilder builder() {
return new ResponsePathBuilder();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,16 @@
{
"name": "<init>",
"parameterTypes": []
},
{
"name": "get",
"parameterTypes": [
"int"
]
},
{
"name": "size",
"parameterTypes": []
}
]
},
Expand Down Expand Up @@ -956,6 +966,54 @@
}
]
},
{
"name": "software.amazon.awssdk.crt.iot.MqttRequestResponse",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
],
"fields": [
{
"name": "topic"
},
{
"name": "payload"
}
]
},
{
"name": "software.amazon.awssdk.crt.iot.RequestResponseOperation",
"fields": [
{
"name": "responsePaths"
},
{
"name": "subscriptions"
},
{
"name": "publishTopic"
},
{
"name": "payload"
},
{
"name": "correlationToken"
}
]
},
{
"name": "software.amazon.awssdk.crt.iot.ResponsePath",
"fields": [
{
"name": "responseTopic"
},
{
"name": "correlationTokenJsonPath"
}
]
},
{
"name": "software.amazon.awssdk.crt.mqtt.MqttClientConnection",
"methods": [
Expand Down
Loading
Loading