Skip to content

Commit

Permalink
[CE] An NPE is thrown if port 1883 is in use when HiveMQ CE is started (
Browse files Browse the repository at this point in the history
#424)

Co-authored-by: Henning Lohse <[email protected]>
  • Loading branch information
tgracchus and hlohse authored Oct 6, 2023
1 parent 79801d6 commit adeba14
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 106 deletions.
12 changes: 5 additions & 7 deletions src/main/java/com/hivemq/bootstrap/HiveMQNettyBootstrap.java
Original file line number Diff line number Diff line change
Expand Up @@ -289,16 +289,14 @@ private static class UpdateGivenFutureListener implements ChannelFutureListener
}

@Override
public void operationComplete(final @NotNull ChannelFuture future) throws Exception {
public void operationComplete(final @NotNull ChannelFuture future) {
final Listener listener = bindInformation.getListener();
final int bindPort = ((InetSocketAddress) future.channel().localAddress()).getPort();
listener.setPort(bindPort);
if (future.isSuccess()) {
settableFuture.set(ListenerStartupInformation.successfulListenerStartup(bindPort, listener));
final int bindPort = ((InetSocketAddress) future.channel().localAddress()).getPort();
listener.setPort(bindPort);
settableFuture.set(ListenerStartupInformation.successfulListenerStartup(listener));
} else {
settableFuture.set(ListenerStartupInformation.failedListenerStartup(bindPort,
listener,
future.cause()));
settableFuture.set(ListenerStartupInformation.failedListenerStartup(listener, future.cause()));
}
}
}
Expand Down
40 changes: 14 additions & 26 deletions src/main/java/com/hivemq/bootstrap/ListenerStartupInformation.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,50 +27,38 @@
@Immutable
public class ListenerStartupInformation {

private final int port;

private final boolean successful;
private final Listener originalListener;

private final Optional<Throwable> exception;
private final @NotNull Listener listener;
private final @Nullable Throwable exception;

private ListenerStartupInformation(
final int port,
final boolean successful,
@NotNull final Listener originalListener,
@Nullable final Throwable exception) {
final boolean successful, final @NotNull Listener listener, final @Nullable Throwable exception) {

checkNotNull(originalListener, "Original Listener must not be null");
checkNotNull(listener, "Original Listener must not be null");

this.port = port;
this.successful = successful;
this.originalListener = originalListener;
this.exception = Optional.ofNullable(exception);
}

public int getPort() {
return port;
this.listener = listener;
this.exception = exception;
}

public boolean isSuccessful() {
return successful;
}

public Optional<Throwable> getException() {
return exception;
public @NotNull Listener getListener() {
return listener;
}

public Listener getOriginalListener() {
return originalListener;
public @NotNull Optional<Throwable> getException() {
return Optional.ofNullable(exception);
}

public static ListenerStartupInformation successfulListenerStartup(
final int port, @NotNull final Listener originalListener) {
return new ListenerStartupInformation(port, true, originalListener, null);
public static ListenerStartupInformation successfulListenerStartup(final @NotNull Listener listener) {
return new ListenerStartupInformation(true, listener, null);
}

public static ListenerStartupInformation failedListenerStartup(
final int port, @NotNull final Listener originalListener, @Nullable final Throwable exception) {
return new ListenerStartupInformation(port, false, originalListener, exception);
final @NotNull Listener listener, final @Nullable Throwable exception) {
return new ListenerStartupInformation(false, listener, exception);
}
}
41 changes: 12 additions & 29 deletions src/main/java/com/hivemq/bootstrap/StartupListenerVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,36 +74,19 @@ public void verifyAndPrint() throws UnrecoverableException {
}
}

private String getSuccessfulStartedString(final ListenerStartupInformation startupInfo) {
final StringBuilder builder = new StringBuilder();

final Listener listener = startupInfo.getOriginalListener();

builder.append("Started ");
builder.append(listener.readableName());
builder.append(" ");
builder.append("on address ");
builder.append(listener.getBindAddress());
builder.append(" and on port ");
builder.append(startupInfo.getPort());

return builder.toString();
private @NotNull String getSuccessfulStartedString(final @NotNull ListenerStartupInformation startupInfo) {
final Listener listener = startupInfo.getListener();
return String.format("Started %s on address %s and on port %s.",
listener.readableName(),
listener.getBindAddress(),
listener.getPort());
}

private String getNotSuccessfulStartedString(final ListenerStartupInformation startupInfo) {
final StringBuilder builder = new StringBuilder();

final Listener listener = startupInfo.getOriginalListener();

builder.append("Could not start ");
builder.append(listener.readableName());
builder.append(" ");
builder.append("on port ");
builder.append(startupInfo.getPort());
builder.append(" and address ");
builder.append(listener.getBindAddress());
builder.append(". Is it already in use?");

return builder.toString();
private @NotNull String getNotSuccessfulStartedString(final @NotNull ListenerStartupInformation startupInfo) {
final Listener listener = startupInfo.getListener();
return String.format("Could not start %s on port %s and address %s. Is it already in use?",
listener.readableName(),
listener.getPort(),
listener.getBindAddress());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,57 +19,51 @@
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

public class ListenerStartupInformationTest {


@Test(expected = NullPointerException.class)
public void test_successful_listener_startup_original_listener_null() throws Exception {
ListenerStartupInformation.successfulListenerStartup(1883, null);
public void test_successful_listener_startup_listener_null() throws Exception {
ListenerStartupInformation.successfulListenerStartup(null);
}

@Test
public void test_successful_listener() throws Exception {
final TcpListener listener = new TcpListener(1883, "0.0.0.0");
final ListenerStartupInformation info =
ListenerStartupInformation.successfulListenerStartup(listener.getPort(), listener);
final ListenerStartupInformation info = ListenerStartupInformation.successfulListenerStartup(listener);

assertEquals(true, info.isSuccessful());
assertEquals(1883, info.getPort());
assertSame(listener, info.getOriginalListener());
assertEquals(false, info.getException().isPresent());
assertTrue(info.isSuccessful());
assertSame(listener, info.getListener());
assertFalse(info.getException().isPresent());
}

@Test(expected = NullPointerException.class)
public void test_failed_listener_startup_original_listener_null() throws Exception {
ListenerStartupInformation.failedListenerStartup(1883, null, null);
public void test_failed_listener_startup_listener_null() throws Exception {
ListenerStartupInformation.failedListenerStartup(null, null);
}

@Test
public void test_failed_listener_no_exception() throws Exception {
final TcpListener listener = new TcpListener(1883, "0.0.0.0");
final ListenerStartupInformation info =
ListenerStartupInformation.failedListenerStartup(listener.getPort(), listener, null);
final ListenerStartupInformation info = ListenerStartupInformation.failedListenerStartup(listener, null);

assertEquals(false, info.isSuccessful());
assertEquals(1883, info.getPort());
assertSame(listener, info.getOriginalListener());
assertEquals(false, info.getException().isPresent());
assertFalse(info.isSuccessful());
assertSame(listener, info.getListener());
assertFalse(info.getException().isPresent());
}

@Test
public void test_failed_listener_exception() throws Exception {
final TcpListener listener = new TcpListener(1883, "0.0.0.0");
final ListenerStartupInformation info = ListenerStartupInformation.failedListenerStartup(listener.getPort(),
listener,
new IllegalArgumentException("illegal"));
final ListenerStartupInformation info =
ListenerStartupInformation.failedListenerStartup(listener, new IllegalArgumentException("illegal"));

assertEquals(false, info.isSuccessful());
assertEquals(1883, info.getPort());
assertSame(listener, info.getOriginalListener());
assertEquals(true, info.getException().isPresent());
assertFalse(info.isSuccessful());
assertSame(listener, info.getListener());
assertTrue(info.getException().isPresent());
assertEquals(IllegalArgumentException.class, info.getException().get().getClass());
}

}
36 changes: 17 additions & 19 deletions src/test/java/com/hivemq/bootstrap/StartupListenerVerifierTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,48 +15,47 @@
*/
package com.hivemq.bootstrap;

import com.google.common.collect.Lists;
import com.hivemq.configuration.service.entity.TcpListener;
import com.hivemq.exceptions.UnrecoverableException;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
* @author Dominik Obermaier
*/
public class StartupListenerVerifierTest {


@Test(expected = UnrecoverableException.class)
public void test_verifier_verify_only_listener_failed() throws Exception {
final ListenerStartupInformation failed = ListenerStartupInformation.failedListenerStartup(2000,
new TcpListener(2000, "0.0.0.0"),
new RuntimeException("reason"));
new StartupListenerVerifier(Lists.newArrayList(failed)).verifyAndPrint();
final ListenerStartupInformation failed =
ListenerStartupInformation.failedListenerStartup(new TcpListener(2000, "0.0.0.0"),
new RuntimeException("reason"));
new StartupListenerVerifier(List.of(failed)).verifyAndPrint();
}

@Test(expected = UnrecoverableException.class)
public void test_verifier_verify_all_listeners_failed() throws Exception {
final ListenerStartupInformation failed = ListenerStartupInformation.failedListenerStartup(2000,
new TcpListener(2000, "0.0.0.0"),
new RuntimeException("reason"));
final ListenerStartupInformation failed2 = ListenerStartupInformation.failedListenerStartup(1234,
new TcpListener(1234, "0.0.0.0"),
new RuntimeException("anotherreason"));
final ListenerStartupInformation failed =
ListenerStartupInformation.failedListenerStartup(new TcpListener(2000, "0.0.0.0"),
new RuntimeException("reason"));
final ListenerStartupInformation failed2 =
ListenerStartupInformation.failedListenerStartup(new TcpListener(1234, "0.0.0.0"),
new RuntimeException("anotherreason"));

new StartupListenerVerifier(Lists.newArrayList(failed, failed2)).verifyAndPrint();
new StartupListenerVerifier(List.of(failed, failed2)).verifyAndPrint();
}

@Test
public void test_verifier_verify_some_listeners_failed() throws Exception {
final ListenerStartupInformation failed = ListenerStartupInformation.failedListenerStartup(2000,
new TcpListener(2000, "0.0.0.0"),
new RuntimeException("reason"));
final ListenerStartupInformation failed =
ListenerStartupInformation.failedListenerStartup(new TcpListener(2000, "0.0.0.0"),
new RuntimeException("reason"));
final ListenerStartupInformation success =
ListenerStartupInformation.successfulListenerStartup(1234, new TcpListener(1234, "0.0.0.0"));
ListenerStartupInformation.successfulListenerStartup(new TcpListener(1234, "0.0.0.0"));

new StartupListenerVerifier(Lists.newArrayList(failed, success)).verifyAndPrint();
new StartupListenerVerifier(List.of(failed, success)).verifyAndPrint();

//We don't receive an exception so everything is good
}
Expand All @@ -70,5 +69,4 @@ public void test_verifier_verify_empty_listeners() throws Exception {
public void test_verifier_doesnt_accept_null() throws Exception {
new StartupListenerVerifier(null);
}

}

0 comments on commit adeba14

Please sign in to comment.