Skip to content

Commit 71c29a4

Browse files
authored
Merge pull request #56 from bosch-io/feature/e2e_ack
End-2-end acks for Ditto Java Client
2 parents e9d3720 + a978976 commit 71c29a4

File tree

79 files changed

+2037
-790
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+2037
-790
lines changed

java/pom.xml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@
330330
<plugin>
331331
<groupId>org.apache.maven.plugins</groupId>
332332
<artifactId>maven-surefire-plugin</artifactId>
333-
<version>3.0.0-M1</version>
333+
<version>3.0.0-M4</version>
334334
<configuration>
335335
<systemProperties>
336336
<kamon.auto-start>true</kamon.auto-start>
@@ -345,7 +345,7 @@
345345
<plugin>
346346
<groupId>org.apache.maven.plugins</groupId>
347347
<artifactId>maven-failsafe-plugin</artifactId>
348-
<version>3.0.0-M1</version>
348+
<version>3.0.0-M4</version>
349349
<executions>
350350
<execution>
351351
<id>integration-test</id>
@@ -445,6 +445,8 @@
445445
<exclude>org.eclipse.ditto.client.messaging.internal</exclude>
446446
<exclude>org.eclipse.ditto.client.options.internal</exclude>
447447
<exclude>org.eclipse.ditto.client.twin.internal</exclude>
448+
<!-- this builder is an internal implementation of a builder interface and should not be handled as API: -->
449+
<exclude>org.eclipse.ditto.client.configuration.ClientCredentialsAuthenticationConfiguration$ClientCredentialsAuthenticationConfigurationBuilder</exclude>
448450
</excludes>
449451
</parameter>
450452
</configuration>
@@ -825,6 +827,11 @@
825827
<artifactId>ditto-signals-base</artifactId>
826828
<version>${ditto.version}</version>
827829
</dependency>
830+
<dependency>
831+
<groupId>org.eclipse.ditto</groupId>
832+
<artifactId>ditto-signals-acks-things</artifactId>
833+
<version>${ditto.version}</version>
834+
</dependency>
828835
<dependency>
829836
<groupId>org.eclipse.ditto</groupId>
830837
<artifactId>ditto-signals-commands-base</artifactId>

java/src/main/assembly/assembly.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
<include>org.eclipse.ditto:ditto-model-things</include>
4141
<include>org.eclipse.ditto:ditto-model-thingsearch</include>
4242
<include>org.eclipse.ditto:ditto-signals-base</include>
43+
<include>org.eclipse.ditto:ditto-signals-acks-base</include>
44+
<include>org.eclipse.ditto:ditto-signals-acks-things</include>
4345
<include>org.eclipse.ditto:ditto-signals-commands-base</include>
4446
<include>org.eclipse.ditto:ditto-signals-commands-thingsearch</include>
4547
<include>org.eclipse.ditto:ditto-signals-commands-things</include>
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2020 Contributors to the Eclipse Foundation
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information regarding copyright ownership.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.eclipse.ditto.client.changes;
14+
15+
import javax.annotation.Nullable;
16+
import javax.annotation.concurrent.Immutable;
17+
18+
import org.eclipse.ditto.json.JsonValue;
19+
import org.eclipse.ditto.model.base.acks.AcknowledgementLabel;
20+
import org.eclipse.ditto.model.base.common.HttpStatusCode;
21+
import org.eclipse.ditto.model.base.entity.id.EntityIdWithType;
22+
import org.eclipse.ditto.model.base.headers.WithDittoHeaders;
23+
import org.eclipse.ditto.signals.acks.base.Acknowledgement;
24+
25+
/**
26+
* Abstraction for handling {@code AcknowledgementRequest}s issued by the Ditto backend together with e.g.
27+
* {@code Event}s. This handle provides means to {@code acknowledge} such acknowledgement requests with a custom
28+
* {@code HttpStatusCode}, an optional {@code payload} or - alternatively - with a self built {@code Acknowledgement}.
29+
*
30+
* @since 1.1.0
31+
*/
32+
@Immutable
33+
public interface AcknowledgementRequestHandle extends WithDittoHeaders<AcknowledgementRequestHandle> {
34+
35+
/**
36+
* Returns the {@code AcknowledgementLabel} this handle was created for.
37+
*
38+
* @return the acknowledgement label to handle.
39+
*/
40+
AcknowledgementLabel getAcknowledgementLabel();
41+
42+
/**
43+
* Returns the entity ID containing the entity type this handle was created for.
44+
*
45+
* @return the entity id to handle.
46+
*/
47+
EntityIdWithType getEntityId();
48+
49+
/**
50+
* Builds and sends an {@code Acknowledgement} to the Ditto backend based on the information this handle instance
51+
* already has, combined with the passed {@code statusCode} and no {@code payload}.
52+
*
53+
* @param statusCode the http status code to apply for the acknowledgement to send: use a range between 200 and 300
54+
* in order to declare a successful acknowledgement and a status code above 400 to declare a not successful one.
55+
*/
56+
void acknowledge(HttpStatusCode statusCode);
57+
58+
/**
59+
* Builds and sends an {@code Acknowledgement} to the Ditto backend based on the information this handle instance
60+
* already has, combined with the passed {@code statusCode} and the passed {@code payload}.
61+
*
62+
* @param statusCode the http status code to apply for the acknowledgement to send: use a range between 200 and 300
63+
* in order to declare a successful acknowledgement and a status code above 400 to declare a not successful one.
64+
* @param payload the payload as {@code JsonValue} to include in the sent acknowledgement.
65+
*/
66+
void acknowledge(HttpStatusCode statusCode, @Nullable JsonValue payload);
67+
68+
/**
69+
* Sends the passed {@code acknowledgement} to the Ditto backend.
70+
*
71+
* @param acknowledgement the already built {@code Acknowledgement} to send to the Ditto backend.
72+
*/
73+
void acknowledge(Acknowledgement acknowledgement);
74+
75+
}

java/src/main/java/org/eclipse/ditto/client/changes/Change.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,26 @@
1313
package org.eclipse.ditto.client.changes;
1414

1515
import java.time.Instant;
16+
import java.util.Collection;
1617
import java.util.Optional;
18+
import java.util.function.Consumer;
1719

1820
import javax.annotation.Nullable;
1921

2022
import org.eclipse.ditto.json.JsonObject;
2123
import org.eclipse.ditto.json.JsonPointer;
2224
import org.eclipse.ditto.json.JsonValue;
25+
import org.eclipse.ditto.model.base.acks.AcknowledgementLabel;
26+
import org.eclipse.ditto.model.base.entity.type.WithEntityType;
27+
import org.eclipse.ditto.model.base.headers.WithDittoHeaders;
2328
import org.eclipse.ditto.signals.base.WithId;
2429

2530
/**
2631
* Common interface for all Thing related changes.
2732
*
2833
* @since 1.0.0
2934
*/
30-
public interface Change extends WithId {
35+
public interface Change extends WithId, WithEntityType, WithDittoHeaders<Change> {
3136

3237
/**
3338
* Returns the {@link ChangeAction} which caused this change.
@@ -88,19 +93,55 @@ default boolean isFull() {
8893
/**
8994
* Returns the extra information which enriches the actual value of this change.
9095
*
91-
* @since 1.1.0
9296
* @return the extra data or an empty Optional.
97+
* @since 1.1.0
9398
*/
9499
Optional<JsonObject> getExtra();
95100

96101
/**
97102
* Sets the given extra information which enriches the actual value of the change.
98103
* Previously set extra is replaced.
99104
*
100-
* @since 1.1.0
101105
* @param extra the extra data information or {@code null}.
102106
* @return a new instance of this change with the added {@code extra} data.
107+
* @since 1.1.0
103108
*/
104109
Change withExtra(@Nullable JsonObject extra);
105110

111+
/**
112+
* Sets the given {@code path} and {@code value} into the change.
113+
*
114+
* @param path the relative path of the changed JSON field.
115+
* @param value the optional value of the changed JSON field.
116+
* @return a new instance of this change with the added data.
117+
* @since 1.1.0
118+
*/
119+
Change withPathAndValue(JsonPointer path, @Nullable JsonValue value);
120+
121+
/**
122+
* Handles {@code AcknowledgementRequest}s issued by the Ditto backend for a received event translated into this
123+
* change by invoking the passed {@code acknowledgementHandles} consumer with client side
124+
* {@code AcknowledgementHandle}s.
125+
*
126+
* @param acknowledgementHandles the consumer to invoke with a collection of {@code AcknowledgementHandle}s used to
127+
* send back {@code Acknowledgements}.
128+
* @since 1.1.0
129+
*/
130+
void handleAcknowledgementRequests(Consumer<Collection<AcknowledgementRequestHandle>> acknowledgementHandles);
131+
132+
/**
133+
* Handles an {@code AcknowledgementRequest} identified by the passed {@code acknowledgementLabel} issued by the
134+
* Ditto backend for a received event translated into this change by invoking the passed
135+
* {@code acknowledgementHandle} consumer with a client side {@code AcknowledgementHandle} - if the passed
136+
* acknowledgementLabel was present in the requested acknowledgements.
137+
*
138+
* @param acknowledgementLabel the {@code AcknowledgementLabel} which should be handled - if present - by the passed
139+
* {@code acknowledgementHandle}.
140+
* @param acknowledgementHandle the consumer to invoke with a {@code AcknowledgementHandle} used to
141+
* send back an {@code Acknowledgement}.
142+
* @since 1.1.0
143+
*/
144+
void handleAcknowledgementRequest(AcknowledgementLabel acknowledgementLabel,
145+
Consumer<AcknowledgementRequestHandle> acknowledgementHandle);
146+
106147
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright (c) 2020 Contributors to the Eclipse Foundation
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information regarding copyright ownership.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.eclipse.ditto.client.changes.internal;
14+
15+
import static org.eclipse.ditto.model.base.common.ConditionChecker.checkNotNull;
16+
17+
import java.util.Objects;
18+
import java.util.function.Consumer;
19+
20+
import javax.annotation.Nullable;
21+
import javax.annotation.concurrent.Immutable;
22+
23+
import org.eclipse.ditto.client.changes.AcknowledgementRequestHandle;
24+
import org.eclipse.ditto.json.JsonValue;
25+
import org.eclipse.ditto.model.base.acks.AcknowledgementLabel;
26+
import org.eclipse.ditto.model.base.common.HttpStatusCode;
27+
import org.eclipse.ditto.model.base.entity.id.EntityIdWithType;
28+
import org.eclipse.ditto.model.base.headers.DittoHeaders;
29+
import org.eclipse.ditto.model.base.headers.DittoHeadersBuilder;
30+
import org.eclipse.ditto.signals.acks.base.Acknowledgement;
31+
32+
/**
33+
* An immutable implementation of {@link AcknowledgementRequestHandle}.
34+
*
35+
* @since 1.1.0
36+
*/
37+
@Immutable
38+
final class ImmutableAcknowledgementRequestHandle implements AcknowledgementRequestHandle {
39+
40+
private final AcknowledgementLabel acknowledgementLabel;
41+
private final EntityIdWithType entityId;
42+
private final DittoHeaders dittoHeaders;
43+
private final Consumer<Acknowledgement> acknowledgementPublisher;
44+
45+
/**
46+
* Creates a new ImmutableAcknowledgementRequestHandle instance.
47+
*
48+
* @param acknowledgementLabel the acknowledgement label to handle.
49+
* @param entityId the entity id to handle.
50+
* @param dittoHeaders the ditto headers which were contained in the acknowledgement request to handle.
51+
* @param acknowledgementPublisher the consumer for publishing built acknowledgements to the Ditto backend.
52+
*/
53+
ImmutableAcknowledgementRequestHandle(final AcknowledgementLabel acknowledgementLabel,
54+
final EntityIdWithType entityId,
55+
final DittoHeaders dittoHeaders,
56+
final Consumer<Acknowledgement> acknowledgementPublisher) {
57+
58+
this.acknowledgementLabel = checkNotNull(acknowledgementLabel, "acknowledgementLabel");
59+
this.entityId = checkNotNull(entityId, "entityId");
60+
this.dittoHeaders = checkNotNull(dittoHeaders, "dittoHeaders");
61+
this.acknowledgementPublisher = checkNotNull(acknowledgementPublisher, "acknowledgementPublisher");
62+
}
63+
64+
@Override
65+
public AcknowledgementLabel getAcknowledgementLabel() {
66+
return acknowledgementLabel;
67+
}
68+
69+
@Override
70+
public EntityIdWithType getEntityId() {
71+
return entityId;
72+
}
73+
74+
@Override
75+
public DittoHeaders getDittoHeaders() {
76+
return dittoHeaders;
77+
}
78+
79+
@Override
80+
public AcknowledgementRequestHandle setDittoHeaders(final DittoHeaders dittoHeaders) {
81+
return new ImmutableAcknowledgementRequestHandle(acknowledgementLabel, entityId, dittoHeaders,
82+
acknowledgementPublisher);
83+
}
84+
85+
@Override
86+
public void acknowledge(final HttpStatusCode statusCode) {
87+
acknowledge(statusCode, null);
88+
}
89+
90+
@Override
91+
public void acknowledge(final HttpStatusCode statusCode, @Nullable final JsonValue payload) {
92+
// only retain the bare minimum of received DittoHeaders by default:
93+
final DittoHeadersBuilder<?, ?> dittoHeadersBuilder = DittoHeaders.newBuilder();
94+
dittoHeaders.getCorrelationId().ifPresent(dittoHeadersBuilder::correlationId);
95+
final DittoHeaders minimizedDittoHeaders = dittoHeadersBuilder.build();
96+
acknowledge(Acknowledgement.of(acknowledgementLabel, entityId, statusCode, minimizedDittoHeaders, payload));
97+
}
98+
99+
@Override
100+
public void acknowledge(final Acknowledgement acknowledgement) {
101+
acknowledgementPublisher.accept(acknowledgement);
102+
}
103+
104+
@Override
105+
public boolean equals(@Nullable final Object o) {
106+
if (this == o) {
107+
return true;
108+
}
109+
if (o == null || getClass() != o.getClass()) {
110+
return false;
111+
}
112+
final ImmutableAcknowledgementRequestHandle that = (ImmutableAcknowledgementRequestHandle) o;
113+
return Objects.equals(acknowledgementLabel, that.acknowledgementLabel) &&
114+
Objects.equals(entityId, that.entityId) &&
115+
Objects.equals(dittoHeaders, that.dittoHeaders);
116+
}
117+
118+
@Override
119+
public int hashCode() {
120+
return Objects.hash(acknowledgementLabel, entityId, dittoHeaders);
121+
}
122+
123+
@Override
124+
public String toString() {
125+
return getClass().getSimpleName() + " [" +
126+
"acknowledgementLabel=" + acknowledgementLabel +
127+
", entityId=" + entityId +
128+
", dittoHeaders=" + dittoHeaders +
129+
"]";
130+
}
131+
}

0 commit comments

Comments
 (0)