Skip to content

Commit 36b3a37

Browse files
authored
fix: Remove nillable = true from messageHandlingOptions in NorthboundMappingEntity (#1255)
1 parent 34b7696 commit 36b3a37

File tree

2 files changed

+104
-1
lines changed

2 files changed

+104
-1
lines changed

hivemq-edge/src/main/java/com/hivemq/configuration/entity/adapter/NorthboundMappingEntity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class NorthboundMappingEntity implements EntityValidatable {
4747
@XmlElement(name = "maxQos", required = true)
4848
private final int maxQoS;
4949

50-
@XmlElement(name = "messageHandlingOptions", defaultValue = "MQTTMessagePerTag", nillable = true)
50+
@XmlElement(name = "messageHandlingOptions", defaultValue = "MQTTMessagePerTag")
5151
private final @Nullable MessageHandlingOptions messageHandlingOptions;
5252

5353
@XmlElement(name = "includeTagNames", required = true)

hivemq-edge/src/test/java/com/hivemq/configuration/reader/ProtocolAdapterExtractorTest.java

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.junit.jupiter.params.provider.CsvSource;
3333

3434
import java.io.File;
35+
import java.io.FileWriter;
3536
import java.io.IOException;
3637
import java.nio.file.Files;
3738
import java.util.List;
@@ -71,6 +72,78 @@ public void whenAdapterIdIsAbsent_thenApplyConfigShouldFail() throws IOException
7172
assertThatThrownBy(configFileReader::applyConfig).isInstanceOf(UnrecoverableException.class);
7273
}
7374

75+
@Test
76+
public void whenMessageHandlingOptionsInNorthboundMappingIsAbsent_thenApplyConfigShouldPass() throws IOException {
77+
final ConfigFileReaderWriter configFileReader = getConfigFileReaderWriter("""
78+
<hivemq>
79+
<protocol-adapters>
80+
<protocol-adapter>
81+
<adapterId>simInvalid</adapterId>
82+
<protocolId>simulation</protocolId>
83+
<configVersion>1</configVersion>
84+
<config>
85+
<pollingIntervalMillis>123</pollingIntervalMillis>
86+
<timeout>10000</timeout>
87+
<minDelay>0</minDelay>
88+
<maxDelay>0</maxDelay>
89+
</config>
90+
<northboundMappings>
91+
<northboundMapping>
92+
<tagName>tag1</tagName>
93+
<topic>MTConnect/my-steams</topic>
94+
<maxQos>1</maxQos>
95+
<messageHandlingOptions/>
96+
<includeTagNames>false</includeTagNames>
97+
<includeTimestamp>true</includeTimestamp>
98+
<mqttUserProperties/>
99+
<messageExpiryInterval>9223372036854775807</messageExpiryInterval>
100+
</northboundMapping>
101+
</northboundMappings>
102+
<tags>
103+
<tag>
104+
<name>tag1</name>
105+
<description>description1</description>
106+
</tag>
107+
</tags>
108+
</protocol-adapter>
109+
</protocol-adapters>
110+
</hivemq>
111+
""");
112+
assertThat(configFileReader.applyConfig()).isNotNull();
113+
final ProtocolAdapterExtractor protocolAdapterExtractor = configFileReader.getProtocolAdapterExtractor();
114+
assertThat(protocolAdapterExtractor.getAllConfigs()).hasSize(1);
115+
final ProtocolAdapterEntity protocolAdapterEntity = protocolAdapterExtractor.getAllConfigs().getFirst();
116+
assertThat(protocolAdapterEntity.getAdapterId()).isEqualTo("simInvalid");
117+
assertThat(protocolAdapterEntity.getProtocolId()).isEqualTo("simulation");
118+
assertThat(protocolAdapterEntity.getNorthboundMappings()).hasSize(1);
119+
final NorthboundMappingEntity northboundMappingEntity =
120+
protocolAdapterEntity.getNorthboundMappings().getFirst();
121+
assertThat(northboundMappingEntity.getTopic()).isEqualTo("MTConnect/my-steams");
122+
assertThat(northboundMappingEntity.getTagName()).isEqualTo("tag1");
123+
assertThat(northboundMappingEntity.getMessageHandlingOptions()).isEqualTo(MessageHandlingOptions.MQTTMessagePerTag);
124+
protocolAdapterEntity.getNorthboundMappings().clear();
125+
protocolAdapterEntity.getNorthboundMappings()
126+
.add(new NorthboundMappingEntity(northboundMappingEntity.getTagName(),
127+
northboundMappingEntity.getTopic(),
128+
northboundMappingEntity.getMaxQoS(),
129+
null,
130+
northboundMappingEntity.isIncludeTagNames(),
131+
northboundMappingEntity.isIncludeTimestamp(),
132+
northboundMappingEntity.getUserProperties(),
133+
northboundMappingEntity.getMessageExpiryInterval()));
134+
final File newConfigFile = new File(tempDir, "new-conf.xml");
135+
try (final FileWriter fileWriter = new FileWriter(newConfigFile)) {
136+
configFileReader.writeConfigToXML(fileWriter);
137+
}
138+
final String newConfigString = Files.readString(newConfigFile.toPath());
139+
// If nillable = true is set on messageHandlingOptions, the output XML would contain xsi:nil="true".
140+
// This is a bug that can cause the config to be invalid.
141+
// @XmlElement(name = "messageHandlingOptions", defaultValue = "MQTTMessagePerTag", nillable = true)
142+
// private final @Nullable MessageHandlingOptions messageHandlingOptions;
143+
assertThat(newConfigString).as("<messageHandlingOptions/> shouldn't contain xsi:nil=\"true\"")
144+
.doesNotContain("<messageHandlingOptions xsi:nil=\"true\"/>");
145+
}
146+
74147
@ParameterizedTest
75148
@CsvSource({"true,0", "true,1", "true,2", "false,-1", "false,3", "false,abc"})
76149
public void whenNorthboundMappingQoSIsProvided_thenApplyConfigShouldWorkAsExpected(
@@ -321,6 +394,36 @@ public void whenNoTags_thenApplyConfigShouldFail() throws IOException {
321394
assertThatThrownBy(configFileReader::applyConfig).isInstanceOf(UnrecoverableException.class);
322395
}
323396

397+
@Test
398+
public void whenMessageHandlingOptionsIsNillable_thenApplyConfigShouldFail() throws IOException {
399+
final ConfigFileReaderWriter configFileReader = getConfigFileReaderWriter("""
400+
<hivemq>
401+
<protocol-adapters>
402+
<protocol-adapter>
403+
<adapterId>simInvalid</adapterId>
404+
<protocolId>simulation</protocolId>
405+
<configVersion>1</configVersion>
406+
<config>
407+
<pollingIntervalMillis>123</pollingIntervalMillis>
408+
<timeout>10000</timeout>
409+
<minDelay>0</minDelay>
410+
<maxDelay>0</maxDelay>
411+
</config>
412+
<northboundMappings>
413+
<northboundMapping>
414+
<topic>MTConnect/my-steams</topic>
415+
<messageHandlingOptions xsi:nil="true"/>
416+
</northboundMapping>
417+
</northboundMappings>
418+
</protocol-adapter>
419+
</protocol-adapters>
420+
</hivemq>
421+
""");
422+
// XML schema violation in line '16' and column '51' caused by:
423+
// "The prefix "xsi" for attribute "xsi:nil" associated with an element type "messageHandlingOptions" is not bound."
424+
assertThatThrownBy(configFileReader::applyConfig).isInstanceOf(UnrecoverableException.class);
425+
}
426+
324427
@Test
325428
public void whenUnexpectedXmlElementIsUnderHivemq_thenApplyConfigShouldFail() throws IOException {
326429
final ConfigFileReaderWriter configFileReader = getConfigFileReaderWriter("""

0 commit comments

Comments
 (0)