Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CE] An NPE is thrown if port 1883 is in use when HiveMQ CE is started #424

Merged
merged 5 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
mchernyakov marked this conversation as resolved.
Show resolved Hide resolved
}

@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);
}

}
Loading