Skip to content

Commit 90a9da5

Browse files
committed
Fix: Remove that EqualsAndHashCode of Message only uses the name, Change MessageHelper to not expose the TreeSet that is used for deduplication because a TreeSet breaks equals
1 parent 2b49e7f commit 90a9da5

File tree

7 files changed

+79
-11
lines changed

7 files changed

+79
-11
lines changed

springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/MessageHelper.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.Message;
55
import lombok.extern.slf4j.Slf4j;
66

7-
import java.util.*;
7+
import java.util.Arrays;
8+
import java.util.Collections;
9+
import java.util.Comparator;
10+
import java.util.HashSet;
11+
import java.util.Map;
12+
import java.util.Set;
13+
import java.util.TreeSet;
814
import java.util.function.Supplier;
915
import java.util.stream.Collectors;
1016

@@ -13,6 +19,10 @@ public class MessageHelper {
1319
private static final String ONE_OF = "oneOf";
1420

1521
private static final Comparator<Message> byMessageName = Comparator.comparing(Message::getName);
22+
23+
// TODO Why do we need a SortedSet here? Using a comparator with only the message name will break deep equals on the Set
24+
// Unfortunately there are Tests relying on deep equals
25+
// see https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html
1626
private static final Supplier<Set<Message>> messageSupplier = () -> new TreeSet<>(byMessageName);
1727

1828
public static Object toMessageObjectOrComposition(Set<Message> messages) {
@@ -22,14 +32,14 @@ public static Object toMessageObjectOrComposition(Set<Message> messages) {
2232
case 1:
2333
return messages.toArray()[0];
2434
default:
25-
return ImmutableMap.of(ONE_OF, messages.stream().collect(Collectors.toCollection(messageSupplier)));
35+
return ImmutableMap.of(ONE_OF, new HashSet<>(messages.stream().collect(Collectors.toCollection(messageSupplier))));
2636
}
2737
}
2838

2939
@SuppressWarnings("unchecked")
3040
public static Set<Message> messageObjectToSet(Object messageObject) {
3141
if (messageObject instanceof Message) {
32-
return new HashSet<>(Arrays.asList((Message) messageObject));
42+
return new HashSet<>(Collections.singletonList((Message) messageObject));
3343
}
3444

3545
if (messageObject instanceof Map) {

springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/types/channel/operation/message/Message.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
*/
1111
@Data
1212
@Builder
13-
@EqualsAndHashCode(of = {"name"})
13+
// TODO Why ignore other fields?
14+
//@EqualsAndHashCode(of = {"name"})
1415
@NoArgsConstructor
1516
@AllArgsConstructor
1617
public class Message {

springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/MessageHelperTest.java

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,60 @@ public void toMessageObjectOrComposition_multipleMessages() {
5353
.isEqualTo(ImmutableMap.of("oneOf", ImmutableSet.of(message1, message2)));
5454
}
5555

56+
@Test
57+
public void toMessageObjectOrComposition_multipleMessages_remove_duplicates() {
58+
Message message1 = Message.builder()
59+
.name("foo")
60+
.description("This is message 1")
61+
.build();
62+
63+
Message message2 = Message.builder()
64+
.name("bar")
65+
.description("This is message 2")
66+
.build();
67+
68+
Message message3 = Message.builder()
69+
.name("bar")
70+
.description("This is message 3, but in essence the same payload type as message 2")
71+
.build();
72+
73+
Object asObject = toMessageObjectOrComposition(ImmutableSet.of(message1, message2, message3));
74+
75+
// Message3 is not included as it is identical in terms of payload type (Message#name) to message 2
76+
assertThat(asObject)
77+
.isInstanceOf(Map.class)
78+
.isEqualTo(ImmutableMap.of("oneOf", ImmutableSet.of(message1, message2)));
79+
}
80+
81+
@Test
82+
public void toMessageObjectOrComposition_multipleMessages_should_not_break_deep_equals() {
83+
Message actualMessage1 = Message.builder()
84+
.name("foo")
85+
.description("This is actual message 1")
86+
.build();
87+
88+
Message actualMessage2 = Message.builder()
89+
.name("bar")
90+
.description("This is actual message 2")
91+
.build();
92+
93+
Object actualObject = toMessageObjectOrComposition(ImmutableSet.of(actualMessage1, actualMessage2));
94+
95+
Message expectedMessage1 = Message.builder()
96+
.name("foo")
97+
.description("This is expected message 1")
98+
.build();
99+
100+
Message expectedMessage2 = Message.builder()
101+
.name("bar")
102+
.description("This is expected message 2")
103+
.build();
104+
105+
Object expectedObject = toMessageObjectOrComposition(ImmutableSet.of(expectedMessage1, expectedMessage2));
106+
107+
assertThat(actualObject).isNotEqualTo(expectedObject);
108+
}
109+
56110
@Test
57111
public void messageObjectToSet_notAMessageOrAMap() {
58112
Object string = "foo";
@@ -94,4 +148,4 @@ public void messageObjectToSet_SetOfMessage() {
94148
.containsExactlyInAnyOrder(message1, message2);
95149
}
96150

97-
}
151+
}

springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelMergerTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,12 @@ public void shouldMergeDifferentMessageForSameOperation() {
110110

111111
// then expectedMessage only includes message1 and message2.
112112
// Message3 is not included as it is identical in terms of payload type (Message#name) to message 2
113-
Object expectedMessages = MessageHelper.toMessageObjectOrComposition(Sets.newHashSet(message1, message2));
113+
// TODO Is it really expected that the first occurrence is used? (no test in Message Helper...)
114+
Object expectedMessages = MessageHelper.toMessageObjectOrComposition(Sets.newHashSet(message1, message3));
114115
assertThat(mergedChannels).hasSize(1)
115116
.hasEntrySatisfying(channelName, it -> {
116117
assertThat(it.getPublish()).isEqualTo(Operation.builder().operationId("publisher1").message(expectedMessages).build());
117118
assertThat(it.getSubscribe()).isNull();
118119
});
119120
}
120-
}
121+
}

springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/operationdata/annotation/AsyncListenerAnnotationScannerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void scan_componentHasListenerMethod() {
6666
Message message = Message.builder()
6767
.name(SimpleFoo.class.getName())
6868
.title(SimpleFoo.class.getSimpleName())
69-
.description(null)
69+
.description("")
7070
.payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName()))
7171
.headers(HeaderReference.fromModelName(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))
7272
.build();
@@ -164,4 +164,4 @@ private static class SimpleFoo {
164164
private String s;
165165
private boolean b;
166166
}
167-
}
167+
}

springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/operationdata/annotation/AsyncPublisherAnnotationScannerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void scan_componentHasPublisherMethod() {
6666
Message message = Message.builder()
6767
.name(SimpleFoo.class.getName())
6868
.title(SimpleFoo.class.getSimpleName())
69-
.description(null)
69+
.description("")
7070
.payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName()))
7171
.headers(HeaderReference.fromModelName(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))
7272
.build();
@@ -164,4 +164,4 @@ private static class SimpleFoo {
164164
private String s;
165165
private boolean b;
166166
}
167-
}
167+
}

springwolf-plugins/springwolf-kafka-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelKafkaListenerScannerTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,14 @@ public void scan_componentWithMultipleKafkaListenersAndHandlers() {
7777
.name(SimpleFoo.class.getName())
7878
.title(SimpleFoo.class.getSimpleName())
7979
.payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName()))
80+
.headers(HeaderReference.fromModelName("SpringKafkaDefaultHeaders-" + SimpleFoo.class.getSimpleName()))
8081
.build();
8182

8283
Message barMessage = Message.builder()
8384
.name(SimpleBar.class.getName())
8485
.title(SimpleBar.class.getSimpleName())
8586
.payload(PayloadReference.fromModelName(SimpleBar.class.getSimpleName()))
87+
.headers(HeaderReference.fromModelName("SpringKafkaDefaultHeaders-" + SimpleBar.class.getSimpleName()))
8688
.build();
8789

8890
Operation operation = Operation.builder()

0 commit comments

Comments
 (0)