This Java project demonstrates a simple communication system between two players using message channels. It implements the SOLID principles and provides two execution modes: same-process and separate-process communication.
The project simulates a game where two players exchange messages. One player (initiator) sends an initial message, and each player responds by appending their name and a counter to the received message. The exchange continues until the initiator has sent and received 10 messages each.
- Message Channel Abstraction: Uses an interface for different communication implementations (in-memory queues for same-process, TCP sockets for separate processes).
- SOLID Principles: Designed with Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion in mind.
- Two Execution Modes:
- Same-process: Players communicate via shared blocking queues.
- Separate-process: Players run in different JVMs and communicate over TCP sockets.
src/main/java/com/gameplay/: Main source codeMain.java: Entry point for same-process execution.InitiatorMain.java: Entry point for initiator in separate-process mode.ResponderMain.java: Entry point for responder in separate-process mode.communication/: Communication abstractionsMessageChannel.java: Interface for sending/receiving messages.impl/: ImplementationsQueueMessageChannel.java: In-memory queue implementation.SocketMessageChannel.java: TCP socket implementation.
controller/GameController.java: Orchestrates the game loop in same-process mode.domain/Player.java: Represents a player with messaging capabilities.model/Message.java: Simple message data holder.
target/classes/: Compiled classes.
- Java 17 or higher (for records and modern features).
- No external dependencies.
For a quick start guide, see QUICKSTART.md
cd /Users/kiran/JavaWorkspace/GamePlay
find src/main/java -name "*.java" | xargs javac -d target/classesmvn compileYou can run the project using shell scripts (recommended) or manual Java commands.
Shell scripts are located in ./shellScripts/ directory
Same-Process Mode:
./shellScripts/start.sh same-processSeparate-Process Mode:
./shellScripts/start.sh separate-processFor more script options and detailed usage, see SCRIPTS.md
In this mode, both players run in the same JVM using shared queues.
java -cp target/classes com.gameplay.MainThis will start the game, perform 10 exchanges, and print the message flow to the console.
In this mode, each player runs in a separate JVM, communicating over TCP sockets. The ResponderMain must be started first to listen for incoming connections.
Terminal 1 - Start the Responder:
cd /Users/kiran/JavaWorkspace/GamePlay
java -cp target/classes com.gameplay.ResponderMainTerminal 2 - Start the Initiator (after responder is listening):
cd /Users/kiran/JavaWorkspace/GamePlay
java -cp target/classes com.gameplay.InitiatorMainOr run responder in background:
java -cp target/classes com.gameplay.ResponderMain &
sleep 2 # Wait for responder to start listening
java -cp target/classes com.gameplay.InitiatorMainThe initiator sends an initial "start" message, and both players exchange messages until the initiator has sent and received 9 responses (10 total interactions). The game ends with a "STOP" message sent by the initiator.
Player2 received: start
Player1 received: start -> Player2(1)
Player2 received: start -> Player2(1) -> Player1(1)
Player1 received: start -> Player2(1) -> Player1(1) -> Player2(2)
Player2 received: start -> Player2(1) -> Player1(1) -> Player2(2) -> Player1(2)
...
Game finished.
ResponderMain Output:
Player2 received: start
Player2 received: start -> Player2(1) -> Player1(1)
Player2 received: start -> Player2(1) -> Player1(1) -> Player2(2) -> Player1(2)
Player2 received: start -> Player2(1) -> Player1(1) -> Player2(2) -> Player1(2) -> Player2(3) -> Player1(3)
...
Player2 received: start -> Player2(1) -> Player1(1) -> ... -> Player1(9)
Responder finished.
InitiatorMain Output:
Player1 received: start -> Player2(1)
Player1 received: start -> Player2(1) -> Player1(1) -> Player2(2)
Player1 received: start -> Player2(1) -> Player1(1) -> Player2(2) -> Player1(2) -> Player2(3)
...
Player1 received: start -> Player2(1) -> Player1(1) -> ... -> Player2(9)
Initiator finished.
- Ports: The separate-process mode uses hardcoded ports (1234 and 1235). Ensure these are available.
- Connection Handling: The SocketMessageChannel automatically retries failed connections for up to 30 seconds, making it robust to startup order variations.
- Blocking I/O: The project uses blocking I/O for simplicity, so it will wait indefinitely for messages.
- Message Serialization: Messages are serialized using Java's ObjectInputStream/ObjectOutputStream for network transmission.
- Production Use: For production use, consider adding:
- Timeout mechanisms
- Comprehensive error handling and logging
- Configurable ports
- Graceful shutdown handlers