diff --git a/application.properties b/application.properties
index ba586de..b7a94e1 100644
--- a/application.properties
+++ b/application.properties
@@ -1 +1,3 @@
+#logging.level.de.ph87=DEBUG
+#-
server.port=8083
\ No newline at end of file
diff --git a/src/main/angular/public/minecraft.svg b/src/main/angular/public/minecraft.svg
new file mode 100644
index 0000000..62ad6b9
--- /dev/null
+++ b/src/main/angular/public/minecraft.svg
@@ -0,0 +1,189 @@
+
+
diff --git a/src/main/angular/src/app/server-list/Server.ts b/src/main/angular/src/app/server-list/Server.ts
index ed61c8e..3b91d8a 100644
--- a/src/main/angular/src/app/server-list/Server.ts
+++ b/src/main/angular/src/app/server-list/Server.ts
@@ -7,9 +7,9 @@ export class Server {
readonly name: string,
readonly motd: string,
readonly mode: Mode,
- readonly serverPort: number,
+ readonly port: number,
readonly running: boolean,
- readonly hasIcon: boolean,
+ readonly icon: boolean,
) {
//
}
@@ -19,9 +19,9 @@ export class Server {
validateString(json.name),
validateString(json.motd),
validateString(json.mode) as Mode,
- validateNumber(json.serverPort),
+ validateNumber(json.port),
validateBoolean(json.running),
- validateBoolean(json.hasIcon),
+ validateBoolean(json.icon),
);
}
diff --git a/src/main/angular/src/app/server-list/server-list.component.html b/src/main/angular/src/app/server-list/server-list.component.html
index fa41cd3..d0c1a48 100644
--- a/src/main/angular/src/app/server-list/server-list.component.html
+++ b/src/main/angular/src/app/server-list/server-list.component.html
@@ -1,22 +1,17 @@
- Serverliste
-
-
-
-

- Beim Starten eines Servers werden alle anderen gestoppt.
+
{{ server.motd }}
- 10.255.0.1:{{ server.serverPort }}
+ 10.255.0.1:{{ server.port }}
@@ -32,3 +27,8 @@
+
+
+

+ Beim Starten eines Servers werden alle anderen gestoppt.
+
diff --git a/src/main/angular/src/app/server-list/server-list.component.less b/src/main/angular/src/app/server-list/server-list.component.less
index 2538322..d0fe915 100644
--- a/src/main/angular/src/app/server-list/server-list.component.less
+++ b/src/main/angular/src/app/server-list/server-list.component.less
@@ -18,6 +18,7 @@
}
.name {
+ color: #c8dddd;
flex-grow: 1;
font-weight: bold;
}
diff --git a/src/main/angular/src/app/server-list/server-list.component.ts b/src/main/angular/src/app/server-list/server-list.component.ts
index 5634870..1712474 100644
--- a/src/main/angular/src/app/server-list/server-list.component.ts
+++ b/src/main/angular/src/app/server-list/server-list.component.ts
@@ -33,7 +33,7 @@ export class ServerListComponent extends CrudListComponent a.serverPort - b.serverPort);
+ return this.list.sort((a, b) => a.port - b.port);
}
}
diff --git a/src/main/angular/src/styles.less b/src/main/angular/src/styles.less
index 3ed8064..44f41a7 100644
--- a/src/main/angular/src/styles.less
+++ b/src/main/angular/src/styles.less
@@ -2,23 +2,26 @@ body {
font-family: sans-serif;
margin: 0;
font-size: 5vw;
+ background-color: #2b3939;
}
.heading {
padding: 0.25em;
font-weight: bold;
+ text-align: center;
+ text-decoration: underline;
}
.hint {
background-color: lightyellow;
border: 0.1em solid yellow;
- margin: 0.25em;
+ margin: 0.5em;
padding: 0.25em;
font-size: 60%;
border-radius: 0.25em;
img {
- height: 1.7em;
- vertical-align: middle;
+ height: 1.4em;
+ vertical-align: bottom;
}
}
diff --git a/src/main/java/de/ph87/mc/server/NoMinecraftServer.java b/src/main/java/de/ph87/mc/server/NoMinecraftServer.java
new file mode 100644
index 0000000..0f4ccd7
--- /dev/null
+++ b/src/main/java/de/ph87/mc/server/NoMinecraftServer.java
@@ -0,0 +1,17 @@
+package de.ph87.mc.server;
+
+import lombok.NonNull;
+
+import java.io.File;
+
+public class NoMinecraftServer extends Exception {
+
+ public NoMinecraftServer(final @NonNull File directory, final String string) {
+ super("Not a minecraft server: directory=%s, reason=%s".formatted(directory, string));
+ }
+
+ public NoMinecraftServer(final @NonNull File directory, final Exception e) {
+ super("Not a minecraft server: directory=%s".formatted(directory), e);
+ }
+
+}
diff --git a/src/main/java/de/ph87/mc/server/Properties.java b/src/main/java/de/ph87/mc/server/Properties.java
new file mode 100644
index 0000000..fcdc4a1
--- /dev/null
+++ b/src/main/java/de/ph87/mc/server/Properties.java
@@ -0,0 +1,45 @@
+package de.ph87.mc.server;
+
+import lombok.Data;
+import lombok.NonNull;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Locale;
+
+@Data
+public class Properties {
+
+ public final String name;
+
+ public final String motd;
+
+ public final Mode mode;
+
+ public final int port;
+
+ public final int rconPort;
+
+ public final String rconPassword;
+
+ public Properties(final @NonNull File directory) throws NoMinecraftServer {
+ final File file = new File(directory, "server.properties");
+ if (!file.exists()) {
+ throw new NoMinecraftServer(directory, "server.properties not found");
+ }
+ final java.util.Properties properties = new java.util.Properties();
+ try (final FileReader reader = new FileReader(file)) {
+ properties.load(reader);
+ name = properties.getProperty("level-name");
+ motd = properties.getProperty("motd");
+ mode = Mode.valueOf(properties.getProperty("gamemode").toUpperCase(Locale.ROOT));
+ port = Integer.parseInt(properties.getProperty("server-port"));
+ rconPort = Integer.parseInt(properties.getProperty("rcon.port"));
+ rconPassword = properties.getProperty("rcon.password");
+ } catch (IOException | NumberFormatException e) {
+ throw new NoMinecraftServer(directory, e);
+ }
+ }
+
+}
diff --git a/src/main/java/de/ph87/mc/server/Server.java b/src/main/java/de/ph87/mc/server/Server.java
index d596b75..d36783e 100644
--- a/src/main/java/de/ph87/mc/server/Server.java
+++ b/src/main/java/de/ph87/mc/server/Server.java
@@ -1,79 +1,55 @@
package de.ph87.mc.server;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import de.ph87.mc.websocket.IWebsocketMessage;
import jakarta.annotation.Nullable;
import lombok.Data;
import lombok.NonNull;
+import lombok.extern.slf4j.Slf4j;
import java.io.File;
@Data
-public class Server implements IWebsocketMessage {
+@Slf4j
+public class Server {
@NonNull
- @JsonIgnore
public final File directory;
@NonNull
- @JsonIgnore
- public final File propertyFile;
-
- @NonNull
- @JsonIgnore
public final File pidFile;
@NonNull
- public final String name;
-
- @NonNull
- public final String motd;
-
- @NonNull
- public final Mode mode;
-
- public final int serverPort;
-
- @JsonIgnore
- public final int rconPort;
-
- @NonNull
- @JsonIgnore
- public final String rconPassword;
-
- @JsonIgnore
- public final int queryPort;
-
- @JsonIgnore
public final File iconFile;
- public final boolean hasIcon;
+ @NonNull
+ public final Properties properties;
+
+ public final Object lock = new Object();
@Nullable
- private Long pid;
+ public Process process = null;
- public Server(@NonNull final File directory, @NonNull final String name, @NonNull final String motd, @NonNull final Mode mode, final int serverPort, final int rconPort, final String rconPassword, final int queryPort) {
+ public boolean shutdown = false;
+
+ public Server(@NonNull final File directory) throws NoMinecraftServer {
this.directory = directory;
- this.propertyFile = new File(directory, "server.properties");
this.pidFile = new File(directory, "pid");
this.iconFile = new File(directory, "McManagerIcon.png");
- this.name = name;
- this.motd = motd;
- this.mode = mode;
- this.serverPort = serverPort;
- this.rconPort = rconPort;
- this.rconPassword = rconPassword;
- this.queryPort = queryPort;
- this.hasIcon = iconFile.isFile();
+ this.properties = new Properties(directory);
+ }
+
+ public boolean isRunning() {
+ synchronized (lock) {
+ return process != null && process.isAlive();
+ }
}
@Override
public String toString() {
- return "Server(%s, \"%s\", %s)".formatted(mode, motd, isRunning() ? "RUNNING" : "stopped");
+ return "Server(%s, \"%s\", %s)".formatted(properties.mode, properties.motd, isRunning() ? "RUNNING" : "stopped");
}
- public boolean isRunning() {
- return pid != null;
+ public boolean eq(@NonNull final Server other) {
+ return properties.name.equals(other.properties.name);
}
}
diff --git a/src/main/java/de/ph87/mc/server/ServerController.java b/src/main/java/de/ph87/mc/server/ServerController.java
index 619bfb9..c8e7a51 100644
--- a/src/main/java/de/ph87/mc/server/ServerController.java
+++ b/src/main/java/de/ph87/mc/server/ServerController.java
@@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
+import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
@@ -21,27 +22,28 @@ public class ServerController {
private final ServerService serverService;
- private final ServerRepository serverRepository;
-
+ @NonNull
@GetMapping("findAll")
- public List findAll() {
- return serverRepository.findAll();
+ public List findAll() {
+ return serverService.findAll();
}
+ @NonNull
@GetMapping("{name}/start")
- public Server start(@NonNull @PathVariable final String name) {
+ public ServerDto start(@NonNull @PathVariable final String name) {
return serverService.start(name);
}
+ @NonNull
@GetMapping("{name}/stop")
- public Server stop(@NonNull @PathVariable final String name) {
+ public ServerDto stop(@NonNull @PathVariable final String name) {
return serverService.stop(name);
}
@GetMapping("{name}/icon")
public void icon(@NonNull @PathVariable final String name, @NonNull final HttpServletResponse response) throws IOException {
- final Server server = serverRepository.getByName(name);
- try (final FileInputStream inputStream = new FileInputStream(server.iconFile)) {
+ final File iconFile = serverService.getIconFileByName(name);
+ try (final FileInputStream inputStream = new FileInputStream(iconFile)) {
response.getOutputStream().write(inputStream.readAllBytes());
}
response.getOutputStream().flush();
diff --git a/src/main/java/de/ph87/mc/server/ServerDto.java b/src/main/java/de/ph87/mc/server/ServerDto.java
new file mode 100644
index 0000000..58c10c0
--- /dev/null
+++ b/src/main/java/de/ph87/mc/server/ServerDto.java
@@ -0,0 +1,31 @@
+package de.ph87.mc.server;
+
+import de.ph87.mc.websocket.IWebsocketMessage;
+import lombok.Data;
+import lombok.NonNull;
+
+@Data
+public class ServerDto implements IWebsocketMessage {
+
+ public final String name;
+
+ public final String motd;
+
+ public final Mode mode;
+
+ public final int port;
+
+ public final boolean running;
+
+ public boolean icon;
+
+ public ServerDto(final @NonNull Server server) {
+ this.name = server.properties.name;
+ this.motd = server.properties.motd;
+ this.mode = server.properties.mode;
+ this.port = server.properties.port;
+ this.running = server.isRunning();
+ this.icon = server.iconFile.isFile();
+ }
+
+}
diff --git a/src/main/java/de/ph87/mc/server/ServerProcessHelper.java b/src/main/java/de/ph87/mc/server/ServerProcessHelper.java
deleted file mode 100644
index 3269235..0000000
--- a/src/main/java/de/ph87/mc/server/ServerProcessHelper.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package de.ph87.mc.server;
-
-import jakarta.annotation.Nullable;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.stereotype.Service;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class ServerProcessHelper {
-
- public static final String[] CMDLINE = {"java", "-jar", "server.jar"};
-
- public static final String CMDLINE_STR = String.join(" ", CMDLINE);
-
- private final ApplicationEventPublisher applicationEventPublisher;
-
- public void updatePid(@NonNull final Server server) {
- server.setPid(_readAndVerifyPid(server));
- if (server.getPid() == null) {
- deletePidFile(server);
- }
- }
-
- @Nullable
- private Long _readAndVerifyPid(@NonNull final Server server) {
- if (!server.pidFile.exists()) {
- return null;
- }
-
- final long pid;
- try (final FileInputStream stream = new FileInputStream(server.pidFile)) {
- pid = Long.parseLong(new String(stream.readAllBytes(), StandardCharsets.UTF_8));
- } catch (IOException | NumberFormatException e) {
- log.error("Failed to read pid-file: file={}, error={}", server.pidFile, e.getMessage());
- return null;
- }
-
- if (!validateProcFile(server, pid)) {
- return null;
- }
-
- return pid;
- }
-
- private static boolean validateProcFile(@NonNull final Server server, final long pid) {
- final File procFile = new File("/proc/%d/cmdline".formatted(pid));
- if (!procFile.exists()) {
- log.warn("Server not running: {}", server.name);
- return false;
- }
-
- try (final FileInputStream stream = new FileInputStream(procFile)) {
- final String cmdline = new String(stream.readAllBytes(), StandardCharsets.UTF_8).replace((char) 0, ' ').trim();
- if (!CMDLINE_STR.equals(cmdline)) {
- log.error("cmdline of running Server does not match: pid={}, running={}, expected={}", pid, cmdline, CMDLINE_STR);
- return false;
- }
- } catch (IOException | NumberFormatException e) {
- log.error("Failed to read proc-file: file={}, error={}", procFile, e.getMessage());
- return false;
- }
-
- return true;
- }
-
- private void deletePidFile(@NonNull final Server server) {
- server.setPid(null);
- if (server.pidFile.delete()) {
- log.info("PID-file removed: {}", server.pidFile);
- applicationEventPublisher.publishEvent(server);
- }
- }
-
- public void startProcess(@NonNull final Server server) {
- if (server.isRunning()) {
- return;
- }
- log.info("Starting Server: {}", server.name);
- final ProcessBuilder builder = new ProcessBuilder(CMDLINE);
- builder.directory(server.directory);
- try {
- final Process process = builder.start();
- server.setPid(process.pid());
- writePid(server, process.pid());
- } catch (IOException e) {
- log.error("Failed to start server: error={}, name={}", e.getMessage(), server.name);
- }
- }
-
- public void stopProcess(@NonNull final Server server) {
- if (!server.isRunning()) {
- return;
- }
- new Thread(() -> {
- try {
- log.info("Stopping Server: {}", server.name);
- new ProcessBuilder("kill", "-15", server.getPid() + "").start();
- while (server.getPid() != null && validateProcFile(server, server.getPid())) {
- //noinspection BusyWait
- Thread.sleep(1000);
- }
- deletePidFile(server);
- } catch (IOException | InterruptedException e) {
- log.error("Failed to stop server: error={}, name={}", e.getMessage(), server.name);
- }
- }).start();
- }
-
- private void writePid(@NonNull final Server server, final long pid) throws IOException {
- final File file = server.pidFile;
- try (final FileOutputStream stream = new FileOutputStream(file)) {
- stream.write("%d".formatted(pid).getBytes(StandardCharsets.UTF_8));
- }
- log.info("PID-file written: file={} = {}", server.pidFile, pid);
- applicationEventPublisher.publishEvent(server);
- }
-
-}
diff --git a/src/main/java/de/ph87/mc/server/ServerRepository.java b/src/main/java/de/ph87/mc/server/ServerRepository.java
deleted file mode 100644
index b297e1c..0000000
--- a/src/main/java/de/ph87/mc/server/ServerRepository.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package de.ph87.mc.server;
-
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.http.HttpStatus;
-import org.springframework.stereotype.Service;
-import org.springframework.web.server.ResponseStatusException;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Properties;
-
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class ServerRepository {
-
- private final ApplicationEventPublisher applicationEventPublisher;
-
- private final ServerProcessHelper serverProcessHelper;
-
- private final ServerConfig serverConfig;
-
- @NonNull
- public List findAll() {
- final File ROOT = new File(serverConfig.getPath());
- return Arrays.stream(Objects.requireNonNull(ROOT.listFiles())).map(this::_tryLoadingFromDir).filter(Optional::isPresent).map(Optional::get).toList();
- }
-
- @NonNull
- private Optional _tryLoadingFromDir(@NonNull final File dir) {
- final File file = new File(dir, "server.properties");
- if (!file.isFile()) {
- log.warn("Server directory without server.properties file: {}", dir);
- return Optional.empty();
- }
- final Properties properties = new Properties();
- try (final FileReader reader = new FileReader(file)) {
- properties.load(reader);
- final String name = properties.getProperty("level-name");
- final String motd = properties.getProperty("motd");
- final Mode gamemode = Mode.valueOf(properties.getProperty("gamemode").toUpperCase(Locale.ROOT));
- final int serverPort = Integer.parseInt(properties.getProperty("server-port"));
- final int rconPort = Integer.parseInt(properties.getProperty("rcon.port"));
- final String rconPassword = properties.getProperty("rcon.password");
- final int queryPort = Integer.parseInt(properties.getProperty("query.port"));
- final Server server = new Server(dir, name, motd, gamemode, serverPort, rconPort, rconPassword, queryPort);
- serverProcessHelper.updatePid(server);
- applicationEventPublisher.publishEvent(server);
- return Optional.of(server);
- } catch (IOException e) {
- log.error("Failed to read server.properties: file={}, error={}", file, e.getMessage());
- return Optional.empty();
- }
- }
-
- @NonNull
- public Server getByName(@NonNull final String name) {
- return findAll().stream().filter(server -> server.name.equals(name)).findFirst().orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
-}
diff --git a/src/main/java/de/ph87/mc/server/ServerService.java b/src/main/java/de/ph87/mc/server/ServerService.java
index 5d415ab..45d4a40 100644
--- a/src/main/java/de/ph87/mc/server/ServerService.java
+++ b/src/main/java/de/ph87/mc/server/ServerService.java
@@ -1,38 +1,151 @@
package de.ph87.mc.server;
+import jakarta.annotation.PostConstruct;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Consumer;
+
@Slf4j
@Service
@RequiredArgsConstructor
public class ServerService {
- private final ServerRepository repository;
+ private final ApplicationEventPublisher applicationEventPublisher;
- private final ServerProcessHelper serverProcessHelper;
+ private final ServerConfig serverConfig;
- @NonNull
- public Server start(@NonNull final String name) {
- final Server server = repository.getByName(name);
- if (server.isRunning()) {
- return server;
+ private final Object lock = new Object();
+
+ private List list = new ArrayList<>();
+
+ @PostConstruct
+ public void startup() {
+ final File ROOT = new File(serverConfig.getPath());
+ synchronized (lock) {
+ list = Arrays.stream(Objects.requireNonNull(ROOT.listFiles())).map(this::_tryLoadingFromDir).filter(Optional::isPresent).map(Optional::get).toList();
}
- repository.findAll().forEach(serverProcessHelper::stopProcess);
- serverProcessHelper.startProcess(server);
- return server;
}
@NonNull
- public Server stop(@NonNull final String name) {
- final Server server = repository.getByName(name);
- if (!server.isRunning()) {
- return server;
+ private Optional _tryLoadingFromDir(@NonNull final File directory) {
+ try {
+ final Server server = new Server(directory);
+ list.stream().filter(server::eq).findFirst().ifPresent(old -> server.process = old.process);
+ return Optional.of(server);
+ } catch (NoMinecraftServer e) {
+ log.warn(e.getMessage());
+ }
+ return Optional.empty();
+ }
+
+ @NonNull
+ public ServerDto start(@NonNull final String name) {
+ return set(name, this::start);
+ }
+
+ @NonNull
+ public ServerDto stop(@NonNull final String name) {
+ return set(name, this::stop);
+ }
+
+ private void start(@NonNull final Server server) {
+ synchronized (server.lock) {
+ if (server.isRunning()) {
+ log.warn("Server is already running: name={}", server.properties.name);
+ return;
+ }
+ log.info("Starting server: name={}", server.properties.name);
+ final ProcessBuilder builder = new ProcessBuilder("java", "-jar", "server.jar");
+ builder.directory(server.directory);
+ try {
+ server.process = builder.start();
+ log.info("Server started: name={}", server.properties.name);
+ } catch (IOException e) {
+ log.error("Failed to start Server: name={}, error={}", server.properties.name, e.getMessage());
+ }
+ }
+ }
+
+ private void stop(@NonNull final Server server) {
+ synchronized (server.lock) {
+ if (!server.isRunning()) {
+ log.warn("Server is not running: name={}", server.properties.name);
+ return;
+ }
+ if (server.shutdown) {
+ log.warn("Server is already shutting down: name={}", server.properties.name);
+ return;
+ }
+ server.shutdown = true;
+ log.info("Stopping Server: name={}", server.properties.name);
+ new Thread(() -> _stop_async(server), "STOP-" + server.properties.name).start();
+ }
+ }
+
+ private void _stop_async(@NonNull final Server server) {
+ log.debug("Thread spawned: name={}", server.properties.name);
+ synchronized (server.lock) {
+ assert server.process != null;
+ log.info("Stopping server: name={}", server.properties.name);
+ server.process.destroy();
+ try {
+ server.process.waitFor();
+ log.info("Server stopped: name={}", server.properties.name);
+ } catch (InterruptedException e) {
+ log.error("Interrupted while waiting for server to stop: name={}", server.properties.name);
+ } finally {
+ server.process = null;
+ server.shutdown = false;
+ publish(server);
+ log.debug("Thread terminated: name={}", server.properties.name);
+ }
+ }
+ }
+
+ @NonNull
+ private ServerDto set(final @NonNull String name, @NonNull final Consumer modifier) {
+ final Server server = getByName(name);
+ modifier.accept(server);
+ return publish(server);
+ }
+
+ @NonNull
+ private ServerDto publish(@NonNull final Server server) {
+ final ServerDto dto = new ServerDto(server);
+ applicationEventPublisher.publishEvent(dto);
+ return dto;
+ }
+
+ @NonNull
+ private Server getByName(@NonNull final String name) {
+ synchronized (lock) {
+ return list.stream().filter(server -> server.properties.name.equals(name)).findFirst().orElseThrow();
+ }
+ }
+
+ @NonNull
+ public List findAll() {
+ synchronized (lock) {
+ return list.stream().map(ServerDto::new).toList();
+ }
+ }
+
+ @NonNull
+ public File getIconFileByName(@NonNull final String name) {
+ synchronized (lock) {
+ return getByName(name).iconFile;
}
- serverProcessHelper.stopProcess(server);
- return server;
}
}
diff --git a/src/main/java/de/ph87/mc/websocket/IWebsocketMessage.java b/src/main/java/de/ph87/mc/websocket/IWebsocketMessage.java
index 448bb03..4b0bdc3 100644
--- a/src/main/java/de/ph87/mc/websocket/IWebsocketMessage.java
+++ b/src/main/java/de/ph87/mc/websocket/IWebsocketMessage.java
@@ -5,7 +5,7 @@ public interface IWebsocketMessage {
default String getWebsocketDestination() {
String name = getClass().getSimpleName();
if (name.endsWith("Dto")) {
- return name.substring(0, name.length() - 4);
+ return name.substring(0, name.length() - 3);
}
return name;
}
diff --git a/src/main/java/de/ph87/mc/websocket/WebSocketService.java b/src/main/java/de/ph87/mc/websocket/WebSocketService.java
index 42c9f04..6dd3fcd 100644
--- a/src/main/java/de/ph87/mc/websocket/WebSocketService.java
+++ b/src/main/java/de/ph87/mc/websocket/WebSocketService.java
@@ -16,7 +16,9 @@ public class WebSocketService {
@EventListener
public void send(@NonNull final IWebsocketMessage message) {
- simpMessageSendingOperations.convertAndSend(message.getWebsocketDestination(), message);
+ final String destination = message.getWebsocketDestination();
+ log.debug("Websocket: destination={}", destination);
+ simpMessageSendingOperations.convertAndSend(destination, message);
}
}