feat: BAEL-5947 External Debugging with JMXTerm (#13847)
* feat: BAEL-5947 External Debugging with JMXTerm * fix: Removed a faulty test * fix: Change Random to ThreadLocalRandom * fix: Renamed a method * fix: Formatting fix
This commit is contained in:
parent
737430655c
commit
ae04ab2510
|
@ -0,0 +1,16 @@
|
||||||
|
package com.baeldung.jmxterm;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public abstract class AbstractPlayerMBean implements PlayerMBean{
|
||||||
|
|
||||||
|
private final UUID id;
|
||||||
|
|
||||||
|
protected AbstractPlayerMBean() {
|
||||||
|
this.id = UUID.randomUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
String getId() {
|
||||||
|
return getName() + id.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.baeldung.jmxterm;
|
||||||
|
|
||||||
|
import javax.management.ListenerNotFoundException;
|
||||||
|
import javax.management.MBeanNotificationInfo;
|
||||||
|
import javax.management.Notification;
|
||||||
|
import javax.management.NotificationBroadcaster;
|
||||||
|
import javax.management.NotificationBroadcasterSupport;
|
||||||
|
import javax.management.NotificationFilter;
|
||||||
|
import javax.management.NotificationListener;
|
||||||
|
|
||||||
|
public abstract class BroadcastingGuessGame implements NotificationBroadcaster, GuessGameMBean {
|
||||||
|
private final NotificationBroadcasterSupport broadcaster =
|
||||||
|
new NotificationBroadcasterSupport();
|
||||||
|
|
||||||
|
private long notificationSequence = 0;
|
||||||
|
|
||||||
|
private final MBeanNotificationInfo[] notificationInfo;
|
||||||
|
|
||||||
|
protected BroadcastingGuessGame() {
|
||||||
|
this.notificationInfo = new MBeanNotificationInfo[]{
|
||||||
|
new MBeanNotificationInfo(new String[]{"game"}, Notification.class.getName(), "Game notification")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void notifyAboutWinner(Player winner) {
|
||||||
|
String message = "Winner is " + winner.getName() + " with score " + winner.getScore();
|
||||||
|
Notification notification = new Notification("game.winner", this, notificationSequence++, message);
|
||||||
|
broadcaster.sendNotification(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) {
|
||||||
|
broadcaster.addNotificationListener(listener, filter, handback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
|
||||||
|
broadcaster.removeNotificationListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MBeanNotificationInfo[] getNotificationInfo() {
|
||||||
|
return notificationInfo;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.jmxterm;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GameRunner {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
MBeanGameServer mBeanGameServer = new MBeanGameServer();
|
||||||
|
Player bob = new Player("Bob");
|
||||||
|
Player alice = new Player("Alice");
|
||||||
|
Player john = new Player("John");
|
||||||
|
List<Player> players = Arrays.asList(bob, alice, john);
|
||||||
|
GuessGame guessGame = new GuessGame(players);
|
||||||
|
mBeanGameServer.registerGame(guessGame);
|
||||||
|
guessGame.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
package com.baeldung.jmxterm;
|
||||||
|
|
||||||
|
import static com.baeldung.jmxterm.RandomNumbergenerator.generateRandomNumber;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class GuessGame extends BroadcastingGuessGame {
|
||||||
|
|
||||||
|
|
||||||
|
public static final int SECOND = 1000;
|
||||||
|
private static final Logger log = Logger.getLogger(GuessGame.class.getCanonicalName());
|
||||||
|
private final List<Player> players;
|
||||||
|
private volatile boolean isFinished = false;
|
||||||
|
private volatile boolean isPaused = false;
|
||||||
|
|
||||||
|
|
||||||
|
public GuessGame(List<Player> players) {
|
||||||
|
this.players = players;
|
||||||
|
log.setLevel(Level.WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
int randomNumber = generateRandomNumber();
|
||||||
|
while (!isFinished) {
|
||||||
|
waitASecond();
|
||||||
|
while (!isPaused && !isFinished) {
|
||||||
|
log.info("Current random number is " + randomNumber);
|
||||||
|
waitASecond();
|
||||||
|
for (Player player : players) {
|
||||||
|
int guess = player.guessNumber();
|
||||||
|
if (guess == randomNumber) {
|
||||||
|
log.info("Players " + player.getName() + " " + guess + " is correct");
|
||||||
|
player.incrementScore();
|
||||||
|
notifyAboutWinner(player);
|
||||||
|
randomNumber = generateRandomNumber();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
log.info("Player " + player.getName() + " guessed incorrectly with " + guess);
|
||||||
|
}
|
||||||
|
log.info("\n");
|
||||||
|
}
|
||||||
|
if (isPaused) {
|
||||||
|
log.info("Game is paused");
|
||||||
|
}
|
||||||
|
if (isFinished) {
|
||||||
|
log.info("Game is finished");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishGame() {
|
||||||
|
isFinished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pauseGame() {
|
||||||
|
isPaused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unpauseGame() {
|
||||||
|
isPaused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Player> getPlayers() {
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitASecond() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(SECOND);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.jmxterm;
|
||||||
|
|
||||||
|
public interface GuessGameMBean {
|
||||||
|
|
||||||
|
void finishGame();
|
||||||
|
void pauseGame();
|
||||||
|
void unpauseGame();
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.baeldung.jmxterm;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import javax.management.InstanceAlreadyExistsException;
|
||||||
|
import javax.management.MBeanRegistrationException;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.MalformedObjectNameException;
|
||||||
|
import javax.management.NotCompliantMBeanException;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
public class MBeanGameServer {
|
||||||
|
|
||||||
|
public static final String ID_FORMAT = "com.baeldung.jmxterm:type=%s,id=%s";
|
||||||
|
private final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
|
||||||
|
public void registerPlayer(AbstractPlayerMBean player) {
|
||||||
|
registerBean(player, "player", player.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerGame(GuessGame guessGame) {
|
||||||
|
registerBean(guessGame, "game", "singlegame");
|
||||||
|
guessGame.getPlayers().forEach(this::registerPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerBean(Object bean, String type, String id) {
|
||||||
|
try {
|
||||||
|
ObjectName name = new ObjectName(String.format(ID_FORMAT, type, id));
|
||||||
|
server.registerMBean(bean, name);
|
||||||
|
} catch (InstanceAlreadyExistsException |
|
||||||
|
MBeanRegistrationException |
|
||||||
|
NotCompliantMBeanException |
|
||||||
|
MalformedObjectNameException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.jmxterm;
|
||||||
|
|
||||||
|
import static com.baeldung.jmxterm.RandomNumbergenerator.*;
|
||||||
|
|
||||||
|
public class Player extends AbstractPlayerMBean {
|
||||||
|
private final String name;
|
||||||
|
private int score = 0;
|
||||||
|
|
||||||
|
public Player(String name) {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int guessNumber() {
|
||||||
|
return generateRandomNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void incrementScore() {
|
||||||
|
score++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getScore() {
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.baeldung.jmxterm;
|
||||||
|
|
||||||
|
public interface PlayerMBean {
|
||||||
|
|
||||||
|
int guessNumber();
|
||||||
|
|
||||||
|
int getScore();
|
||||||
|
|
||||||
|
String getName();
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.baeldung.jmxterm;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
public class RandomNumbergenerator {
|
||||||
|
|
||||||
|
private static final int MIN = 0;
|
||||||
|
private static final int MAX = 10;
|
||||||
|
|
||||||
|
private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current();
|
||||||
|
|
||||||
|
private RandomNumbergenerator() {
|
||||||
|
}
|
||||||
|
public static int generateRandomNumber() {
|
||||||
|
return RANDOM.nextInt(MIN, MAX + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.jmxterm;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class PlayerUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenNewPlayer_thenScoreIsZero() {
|
||||||
|
Player player = new Player("John");
|
||||||
|
assertEquals(0, player.getScore());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenNewPlayer_whenIncrementScore_thenScoreIsOne() {
|
||||||
|
Player player = new Player("John");
|
||||||
|
player.incrementScore();
|
||||||
|
assertEquals(1, player.getScore());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue