Skip to content

Commit

Permalink
- Fix showing terminal buffered messages a lot of times on closing th…
Browse files Browse the repository at this point in the history
…e server

- No more Exceptions when exiting of the application via `CTRL + C`
- Use GraalVM instead of Launch4j for creating Windows native images. Launch4j made necessary for the user to have JRE
- Add JLine in bundles for better compatibility with the native image build
- Change Deprecated JLine Jansi to JNI Version
  • Loading branch information
FelipeKobra committed Jan 14, 2025
1 parent 5f2c94a commit 1260371
Show file tree
Hide file tree
Showing 17 changed files with 163 additions and 114 deletions.
2 changes: 1 addition & 1 deletion .idea/artifacts/ChatClient_jar.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/artifacts/ChatServer_jar.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Change Log

## [0.0.3](https://github.com/FelipeKobra/JMessenger/tree/v0.0.3) - To Release

### Enhancements

- Use GraalVM instead of Launch4j for creating Windows native images. Launch4j made necessary for the user to have JRE
- Added JLine in bundles for better compatibility with the native image build
- Change Deprecated JLine Jansi to JNI Version

### Bug Fixes

- Fixed showing terminal buffered messages a lot of times on closing the server
- No more Exceptions when exiting of the application via `CTRL + C`

## [0.0.2](https://github.com/FelipeKobra/JMessenger/tree/v0.0.2) - January 12, 2025

### Enhancements
Expand Down
File renamed without changes.
File renamed without changes.
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<p align="center"><img src="src/main/resources/images/command.png" alt="command"></p>
<h1 align="center">JMessenger</h1>

**JMessenger** is a terminal-based chat application that allows you to communicate seamlessly with others over a
network. It supports both client and server functionalities, making it easy to set up and use.
**JMessenger** is a terminal-based chat application that allows you to communicate seamlessly with others over
the internet. It supports both client and server functionalities, making it easy to set up and use.

## Table of Contents

- [Notes](#notes)
- [Installation](#installation)
- [Usage](#usage)
- [UTF-8 Support](#utf-8-support)
- [Windows Executable](#windows-executable)
- [JAR](#jar)
- [Building](#building)
Expand All @@ -34,6 +35,24 @@ network. It supports both client and server functionalities, making it easy to s

## Usage

### UTF-8 Support

For being able to see emojis and different symbols on your terminal, you need to check it's encoding. For enabling
the UTF-8 Charset on the current terminal instance check some tips

- Powershell

```powershell
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding
```

- Bash

```bash
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
```

### Windows Executable

Download the executable (`.exe`) from the [Releases](https://github.com/FelipeKobra/JavaTerminalChat/releases) section.
Expand Down Expand Up @@ -100,6 +119,8 @@ To build the artifacts, run this command in the root folder:
## Requirements for Developers

- JDK 21 or higher
- GraalVM JDK 21 or Higher
- Powershell

## Contributing

Expand Down
7 changes: 3 additions & 4 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@

- [ ] Create communication with cryptography

## Configuration

- [ ] Add a file for server config

## QOL

- [ ] Add colors to the terminal
Expand All @@ -16,6 +12,9 @@
## Basic

- [ ] Notify clients when someone connects/disconnects
- [ ] Better warning when server not found on client instead of throwing an exception
- [ ] Make user terminal automatically support UTF8 Characters
- [x] Disable Debug on native-image

## Administration

Expand Down
127 changes: 63 additions & 64 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
<name>org.gladiator</name>
</organization>

<!-- App Properties -->
<properties>
<!-- App Properties -->
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<artifacts.output.directory>${project.build.directory}/artifacts</artifacts.output.directory>
<!-- Dependency Properties -->
<jline.bundle.version>3.28.0</jline.bundle.version>
<native.maven.plugin.version>0.10.4</native.maven.plugin.version>
</properties>

<build>
Expand Down Expand Up @@ -88,79 +91,51 @@
</execution>
</executions>
</plugin>
<!-- https://mvnrepository.com/artifact/com.akathist.maven.plugins.launch4j/launch4j-maven-plugin -->
<!-- Create Application Windows Executables -->
<!-- https://mvnrepository.com/artifact/org.graalvm.buildtools/native-maven-plugin -->
<!-- Create Windows Native Images -->
<plugin>
<groupId>com.akathist.maven.plugins.launch4j</groupId>
<artifactId>launch4j-maven-plugin</artifactId>
<version>2.5.2</version>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${native.maven.plugin.version}</version>
<extensions>false</extensions>
<configuration>
<outputDirectory>target/artifacts</outputDirectory>
<skipNativeTests>true</skipNativeTests>
<fallback>false</fallback>
<debug>false</debug>
<verbose>false</verbose>
<quickBuild>true</quickBuild>
<buildArgs>
-J-Dfile.encoding=UTF-8
</buildArgs>
</configuration>
<executions>
<!-- Server Executable -->
<execution>
<id>executable-server-main</id>
<phase>package</phase>
<id>build-native-server</id>
<goals>
<goal>launch4j</goal>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
<configuration>
<icon>src/main/resources/images/server.ico</icon>
<headerType>console</headerType>
<outfile>${artifacts.output.directory}/Server.exe</outfile>
<jar>${artifacts.output.directory}/Server.jar</jar>
<errTitle>${project.artifactId}</errTitle>
<jre>
<path>%JAVA_HOME%;%PATH%</path>
<requiresJdk>false</requiresJdk>
<requires64Bit>false</requires64Bit>
</jre>
<versionInfo>
<fileVersion>0.${project.version}</fileVersion>
<txtFileVersion>${project.version}</txtFileVersion>
<fileDescription>Server executable for ${project.artifactId}</fileDescription>
<copyright>${project.groupId}</copyright>
<productVersion>0.${project.version}</productVersion>
<txtProductVersion>${project.version</txtProductVersion>
<productName>${project.artifactId} Server</productName>
<internalName>${project.artifactId} Server</internalName>
<originalFilename>Server.exe</originalFilename>
</versionInfo>
<imageName>Server</imageName>
<mainClass>app.server.ServerMain</mainClass>
</configuration>
</execution>
<!-- Client Executable -->
<execution>
<id>executable-client-main</id>
<phase>package</phase>
<id>build-native-client</id>
<goals>
<goal>launch4j</goal>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
<configuration>
<icon>src/main/resources/images/client.ico</icon>
<headerType>console</headerType>
<outfile>${artifacts.output.directory}/Client.exe</outfile>
<jar>${artifacts.output.directory}/Client.jar</jar>
<errTitle>${project.artifactId}</errTitle>
<jre>
<path>%JAVA_HOME%;%PATH%</path>
<requiresJdk>false</requiresJdk>
<requires64Bit>false</requires64Bit>
</jre>
<versionInfo>
<fileVersion>0.${project.version}</fileVersion>
<txtFileVersion>${project.version}</txtFileVersion>
<fileDescription>Client executable for ${project.artifactId}</fileDescription>
<copyright>${project.groupId}</copyright>
<productVersion>0.${project.version}</productVersion>
<txtProductVersion>${project.version</txtProductVersion>
<productName>${project.artifactId} Client</productName>
<internalName>${project.artifactId} Client</internalName>
<originalFilename>Client.exe</originalFilename>
</versionInfo>
<imageName>Client</imageName>
<mainClass>app.client.ClientMain</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<!-- https://mvnrepository.com/artifact/org.codehaus.mojo/exec-maven-plugin -->
<!-- Create Artifacts SHA-256 Hashes -->
<!-- Artifacts SHA-256 Hashes -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
Expand Down Expand Up @@ -203,17 +178,41 @@
<version>1.0.2</version>
</dependency>
<!-- Terminal Section -->
<!-- https://mvnrepository.com/artifact/org.fusesource.jansi/jansi -->
<!-- https://mvnrepository.com/artifact/org.jline/jline-terminal -->
<dependency>
<groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId>
<version>2.4.1</version>
<groupId>org.jline</groupId>
<artifactId>jline-terminal</artifactId>
<version>${jline.bundle.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jline/jline-terminal-jni -->
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-terminal-jni</artifactId>
<version>${jline.bundle.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jline/jline-native -->
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-native</artifactId>
<version>${jline.bundle.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jline/jline-console -->
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-console</artifactId>
<version>${jline.bundle.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jline/jline-style -->
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-style</artifactId>
<version>${jline.bundle.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jline/jline -->
<!-- https://mvnrepository.com/artifact/org.jline/jline-reader -->
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline</artifactId>
<version>3.28.0</version>
<artifactId>jline-reader</artifactId>
<version>${jline.bundle.version}</version>
</dependency>
<!-- Logging Section -->
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
Expand Down
23 changes: 7 additions & 16 deletions src/main/org/gladiator/app/client/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public static Logger getLogger() {
public void run() {
final AsyncSocketIO socketIO = AsyncSocketIO.getAsyncSocketIO(socket, executor);

final var reader = new BufferedReader(new InputStreamReader(socketIO.getInputStream()));
final var reader = new BufferedReader(new InputStreamReader(socketIO.getInputStream(), StandardCharsets.UTF_8));
final var writer = new PrintWriter(socketIO.getOutputStream(), true, StandardCharsets.UTF_8);

String serverName = exchangeNames(writer, reader);
Expand All @@ -79,10 +79,7 @@ private CompletableFuture<Void> receiveMessages(BufferedReader reader) {
return CompletableFuture.runAsync(() -> {
try {
reader.lines()
.map(msg -> {
msg = new String(msg.getBytes(), StandardCharsets.UTF_8);
return ConnectionMessage.fromRawString(msg);
})
.map(ConnectionMessage::fromRawString)
.forEach(msg -> {
chat.showConnectionMessage(msg);
chat.showUserPrompt();
Expand All @@ -102,18 +99,13 @@ private CompletableFuture<Void> sendMessages(PrintWriter writer) {
try {
while ((line = SingletonTerminal.TERMINAL.getLineReader().readLine(chat.userPrompt() + " ")) != null) {
if (line.equals("quit")) {
throw new UserInterruptException("User typed `quit`");
break;
}
String msg = ConnectionMessage.toRawString(config.getName(), line);
writer.println(msg);
}
} catch (EndOfFileException | UserInterruptException e) {
LOGGER.debug("User stopped the console reading, probably by pressing CTRL + C");
try {
socket.close();
} catch (IOException ex) {
LOGGER.error("Error during socket closing after shutdown of sending message: {}", e, e);
}
LOGGER.debug("User stopped the console reading, probably by pressing CTRL + C", e);
} finally {
executor.shutdownNow();
}
Expand Down Expand Up @@ -150,12 +142,11 @@ private void reconnectPrompt() {
try {
String choice = SingletonTerminal.TERMINAL.getLineReader().readLine("Connect to another server? y/N: ");
if (!choice.equalsIgnoreCase("Y")) {
chat.prettyPrint("Chat Ended");
isRunning.set(false);
throw new UserInterruptException("Reconnection choice not made");
}

} catch (UserInterruptException | EndOfFileException e) {
LOGGER.debug("Reconnection choice not made: {}", e.getMessage());
isRunning.set(false);
chat.prettyPrint("Chat Ended");
}
}

Expand Down
7 changes: 3 additions & 4 deletions src/main/org/gladiator/app/client/ClientConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import app.util.SingletonTerminal;
import environment.Port;
import org.apache.commons.lang3.Validate;
import org.jline.reader.UserInterruptException;

public class ClientConfig {
private final String name;
Expand All @@ -24,19 +23,19 @@ public static ClientConfig createClientConfig() {
return new ClientConfig(clientName, serverAddress, serverPort);
}

private static String receiveName() throws UserInterruptException {
private static String receiveName() {
String name = "";
while (name.isBlank()) {
name = SingletonTerminal.TERMINAL.getLineReader().readLine("Choose your name: ");
}
return name;
}

private static String receiveAddress() throws UserInterruptException {
private static String receiveAddress() {
return SingletonTerminal.TERMINAL.getLineReader().readLine("Type the Server IP (default = localhost): ");
}

private static int receivePort() throws UserInterruptException {
private static int receivePort() {
int serverPort;
try {
String serverPortString = SingletonTerminal.TERMINAL.getLineReader().readLine("Type the server port (default = " + Port.PORT_DEFAULT + "): ");
Expand Down
1 change: 1 addition & 0 deletions src/main/org/gladiator/app/client/ClientMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public static void main(final String... args) {
try (Client client = Client.createClient(isRunning)) {
client.run();
} catch (UserInterruptException e) {
isRunning.set(false);
Server.getLogger().debug("User didn't finished typing during a line read, probably by pressing CTRL+C", e);
}
}
Expand Down
Loading

0 comments on commit 1260371

Please sign in to comment.