Skip to content

Commit a2887f7

Browse files
authored
Merge pull request #2097 from beyonnex-io/bugfix/entity-id-wrong-format
#2096: fix entityId header was added in the wrong format
2 parents d4bf9a8 + 0628ca0 commit a2887f7

File tree

10 files changed

+54
-13
lines changed

10 files changed

+54
-13
lines changed

documentation/src/main/resources/_data/sidebars/ditto_sidebar.yml

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ entries:
2323
- title: Release Notes
2424
output: web
2525
folderitems:
26+
- title: 3.6.9
27+
url: /release_notes_369.html
28+
output: web
2629
- title: 3.6.8
2730
url: /release_notes_368.html
2831
output: web
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title: Release notes 3.6.9
3+
tags: [release_notes]
4+
published: true
5+
keywords: release notes, announcements, changelog
6+
summary: "Version 3.6.9 of Eclipse Ditto, released on 16.01.2025"
7+
permalink: release_notes_369.html
8+
---
9+
10+
This is a bugfix release, no new features since [3.6.8](release_notes_368.html) were added.
11+
12+
## Changelog
13+
14+
Compared to the latest release [3.6.8](release_notes_368.html), the following changes and bugfixes were added.
15+
16+
### Bugfixes
17+
This is a complete list of the
18+
[merged pull requests](https://github.com/eclipse-ditto/ditto/pulls?q=is%3Apr+milestone%3A3.6.9).
19+
20+
#### Fix exceptions in WebSocket due to wrongly formatted added "EntityId" header
21+
22+
Ditto release [3.6.5](release_notes_365.html) introduced an improved log messages for errors in WoT validations, adding
23+
the Thing's ID to the log message. Internally, a change was needed to always provide the thing's ID as internal header.
24+
This added header had however the wrong format, which caused exceptions e.g. in the Ditto WebSocket handling.
25+
26+
This was reported in issue [#2096](https://github.com/eclipse-ditto/ditto/issues/2096) and was fixed via PR
27+
[#2097](https://github.com/eclipse-ditto/ditto/pull/2097).
28+
29+
As this is a very critical bug, a bugfix release containing just this one fix is provided: `3.6.9`.
30+

things/service/src/main/java/org/eclipse/ditto/things/service/enforcement/ThingEnforcerActor.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ protected CompletionStage<Signal<?>> performWotBasedSignalValidation(final Signa
200200
return performWotBasedMessageCommandValidation(messageCommand.setDittoHeaders(
201201
DittoHeaders.of(startedSpan.propagateContext(messageCommand.getDittoHeaders()))
202202
.toBuilder()
203-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), entityId.toString())
203+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(),
204+
entityId.getEntityType() + ":" + entityId)
204205
.build()
205206
)).whenComplete((result, error) -> {
206207
if (error instanceof DittoRuntimeException dre) {
@@ -243,7 +244,8 @@ protected CompletionStage<CommandResponse<?>> performWotBasedResponseValidation(
243244
messageCommandResponse.setDittoHeaders(
244245
DittoHeaders.of(startedSpan.propagateContext(messageCommandResponse.getDittoHeaders()))
245246
.toBuilder()
246-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), entityId.toString())
247+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(),
248+
entityId.getEntityType() + ":" + entityId)
247249
.build()
248250
)
249251
)

things/service/src/main/java/org/eclipse/ditto/things/service/persistence/actors/strategies/commands/AbstractThingCommandStrategy.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ public Result<ThingEvent<?>> apply(final Context<ThingId> context, @Nullable fin
9595
final long nextRevision, final C command) {
9696

9797
final var dittoHeaders = command.getDittoHeaders();
98+
final ThingId thingId = context.getState();
9899
final var dittoHeadersBuilder = dittoHeaders.toBuilder()
99-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), context.getState().toString());
100+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.getEntityType() + ":" + thingId);
100101
final var loggerWithCorrelationId = context.getLog().withCorrelationId(command);
101102
final var thingConditionFailed = dittoHeaders.getCondition()
102103
.flatMap(condition -> ThingConditionValidator.validate(command, condition, entity));

things/service/src/test/java/org/eclipse/ditto/things/service/persistence/actors/ETagTestUtils.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ protected static DittoHeaders appendEntityIdAndETagToDittoHeaders(final ThingId
367367
final DittoHeaders dittoHeaders
368368
) {
369369
return dittoHeaders.toBuilder()
370-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.toString())
370+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.getEntityType() + ":" + thingId)
371371
.eTag(EntityTag.fromEntity(object).get())
372372
.build();
373373
}

things/service/src/test/java/org/eclipse/ditto/things/service/persistence/actors/ThingPersistenceActorCleanupTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,9 @@ private EventsourcedEvent<?> sendModifyThing(final Thing modifiedThing, final Ac
131131
modifiedThing, null, dittoHeadersV2);
132132
underTest.tell(modifyThingCommand, getRef());
133133

134+
final ThingId thingId = modifiedThing.getEntityId().get();
134135
expectMsgEquals(modifyThingResponse(modifiedThing, dittoHeadersV2.toBuilder().putHeader(
135-
DittoHeaderDefinition.ENTITY_ID.getKey(), modifiedThing.getEntityId().get().toString())
136+
DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.getEntityType() + ":" + thingId)
136137
.build()
137138
));
138139

things/service/src/test/java/org/eclipse/ditto/things/service/persistence/actors/ThingPersistenceActorSnapshottingTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public void deletedThingIsSnapshotWithCorrectDataAndCanBeRecreated() {
102102
final DeleteThing deleteThing = DeleteThing.of(thingId, dittoHeadersV2);
103103
underTest.tell(deleteThing, getRef());
104104
expectMsgEquals(DeleteThingResponse.of(thingId, dittoHeadersV2.toBuilder()
105-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.toString())
105+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.getEntityType() + ":" + thingId)
106106
.build()));
107107

108108
final Thing expectedDeletedSnapshot = toDeletedThing(2);

things/service/src/test/java/org/eclipse/ditto/things/service/persistence/actors/ThingPersistenceActorTest.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -595,8 +595,9 @@ public void deleteThingV2() {
595595

596596
final DeleteThing deleteThing = DeleteThing.of(getIdOrThrow(thing), dittoHeadersV2);
597597
underTest.tell(deleteThing, getRef());
598+
final ThingId thingId = thing.getEntityId().get();
598599
expectMsgEquals(DeleteThingResponse.of(getIdOrThrow(thing), dittoHeadersV2.toBuilder()
599-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thing.getEntityId().get().toString())
600+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.getEntityType() + ":" + thingId)
600601
.build()));
601602
}
602603
};
@@ -623,7 +624,7 @@ public void deleteAndRecreateThingWithMinimumData() {
623624
final DeleteThing deleteThing = DeleteThing.of(thingId, dittoHeadersV2);
624625
underTest.tell(deleteThing, getRef());
625626
expectMsgEquals(DeleteThingResponse.of(thingId, dittoHeadersV2.toBuilder()
626-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.toString())
627+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.getEntityType() + ":" + thingId)
627628
.build()));
628629

629630
final Thing minimalThing = Thing.newBuilder()
@@ -839,7 +840,7 @@ public void deleteAttribute() {
839840
final ThingCommand authorizedCommand = DeleteAttribute.of(thingId, attributeKey, dittoHeadersV2);
840841
underTest.tell(authorizedCommand, getRef());
841842
expectMsgEquals(DeleteAttributeResponse.of(thingId, attributeKey, dittoHeadersV2.toBuilder()
842-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.toString())
843+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.getEntityType() + ":" + thingId)
843844
.build()));
844845
}
845846
};
@@ -864,7 +865,7 @@ public void tryToRetrieveThingAfterDeletion() {
864865

865866
underTest.tell(deleteThingCommand, getRef());
866867
expectMsgEquals(DeleteThingResponse.of(thingId, dittoHeadersV2.toBuilder()
867-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.toString())
868+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.getEntityType() + ":" + thingId)
868869
.build()));
869870

870871
underTest.tell(retrieveThingCommand, getRef());
@@ -926,7 +927,7 @@ public void recoverThingDeleted() {
926927
final DeleteThing deleteThing = DeleteThing.of(thingId, dittoHeadersV2);
927928
underTest.tell(deleteThing, getRef());
928929
expectMsgEquals(DeleteThingResponse.of(thingId, dittoHeadersV2.toBuilder()
929-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.toString())
930+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.getEntityType() + ":" + thingId)
930931
.build()));
931932

932933
// restart actor to recover thing state

things/service/src/test/java/org/eclipse/ditto/things/service/persistence/actors/strategies/commands/AbstractCommandStrategyTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,9 @@ protected static <C extends Command<?>> void assertUnhandledResult(
179179
}
180180

181181
protected static DittoHeaders provideHeaders(final CommandStrategy.Context<ThingId> context) {
182+
final ThingId thingId = context.getState();
182183
return DittoHeaders.newBuilder()
183-
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), context.getState().toString())
184+
.putHeader(DittoHeaderDefinition.ENTITY_ID.getKey(), thingId.getEntityType() + ":" + thingId)
184185
.build();
185186
}
186187

wot/validation/src/main/java/org/eclipse/ditto/wot/validation/ValidationContext.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ public static ValidationContext buildValidationContext(final DittoHeaders dittoH
5454
}
5555

5656
private static Optional<ThingId> extractThingId(final DittoHeaders dittoHeaders) {
57-
return Optional.ofNullable(dittoHeaders.get(DittoHeaderDefinition.ENTITY_ID.getKey()))
57+
final String nullableEntityId = dittoHeaders.get(DittoHeaderDefinition.ENTITY_ID.getKey());
58+
return Optional.ofNullable(nullableEntityId)
59+
.map(entityId -> entityId.substring(entityId.indexOf(":") + 1)) // starts with "thing:" - cut that off!
5860
.map(ThingId::of);
5961
}
6062
}

0 commit comments

Comments
 (0)