Skip to content

Commit 081b820

Browse files
committed
Refactor HelloModel to use NtfyConnection for message handling and add unit tests
1 parent 6627f45 commit 081b820

7 files changed

Lines changed: 131 additions & 37 deletions

File tree

src/main/java/com/example/HelloController.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@
55
import javafx.scene.control.Label;
66
import javafx.scene.control.ListView;
77

8-
/**
9-
* Controller layer: mediates between the view (FXML) and the model.
10-
*/
118
public class HelloController {
129

13-
private final HelloModel model = new HelloModel();
10+
private final HelloModel model = new HelloModel(new NtfyConnectionImpl());
1411
public ListView<NtfyMessageDto> messageView;
1512

1613
@FXML

src/main/java/com/example/HelloModel.java

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import io.github.cdimascio.dotenv.Dotenv;
44
import javafx.application.Platform;
5+
import javafx.beans.property.SimpleStringProperty;
6+
import javafx.beans.property.StringProperty;
57
import javafx.collections.FXCollections;
68
import javafx.collections.ObservableList;
79
import tools.jackson.databind.ObjectMapper;
@@ -18,57 +20,41 @@
1820
*/
1921
public class HelloModel {
2022

21-
private final String hostName;
22-
private final HttpClient http = HttpClient.newHttpClient();
23-
private final ObjectMapper mapper = new ObjectMapper();
23+
private final NtfyConnection connection;
2424
private final ObservableList<NtfyMessageDto> messages = FXCollections.observableArrayList();
25+
private final StringProperty messageToSend = new SimpleStringProperty();
2526

26-
public HelloModel() {
27-
Dotenv dotenv = Dotenv.load();
28-
hostName = Objects.requireNonNull(dotenv.get("HOST_NAME"));
27+
public HelloModel(NtfyConnection connection) {
28+
this.connection = connection;
2929
receiveMessage();
3030
}
3131

3232
public ObservableList<NtfyMessageDto> getMessages() {
3333
return messages;
3434
}
3535

36+
public String getMessageToSend() {
37+
return messageToSend.get();
38+
}
39+
public StringProperty messageToSendProperty() {
40+
return messageToSend;
41+
}
42+
43+
public void setMessageToSend(String message) {
44+
messageToSend.set(message);
45+
}
46+
3647
public String getGreeting() {
3748
String javaVersion = System.getProperty("java.version");
3849
String javafxVersion = System.getProperty("javafx.version");
3950
return "Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".";
4051
}
4152

4253
public void sendMessage() {
43-
HttpRequest httpRequest = HttpRequest.newBuilder()
44-
.POST(HttpRequest.BodyPublishers.ofString("Hello World!🚀"))
45-
.uri(URI.create(hostName + "/mytopic"))
46-
.build();
47-
48-
try {
49-
//TODO: handle long blockings end request to not freeze the JavaFX thread
50-
//1, Use thread send message
51-
//2, Use async
52-
var response = http.send(httpRequest, HttpResponse.BodyHandlers.ofString());
53-
} catch (IOException e) {
54-
System.out.println("Error sending message");
55-
} catch (InterruptedException e) {
56-
System.out.println("Interrupted sending message");
57-
}
54+
connection.send(messageToSend.get());
5855
}
5956

6057
public void receiveMessage() {
61-
HttpRequest httpRequest = HttpRequest.newBuilder()
62-
.GET()
63-
.uri(URI.create(hostName + "/mytopic/json"))
64-
.build();
65-
66-
http.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofLines())
67-
.thenAccept(response -> response.body()
68-
.map( s -> mapper.readValue(s, NtfyMessageDto.class))
69-
.filter(message -> message.event().equals("message"))
70-
.peek(System.out::println)
71-
.forEach( s -> Platform.runLater(() -> messages.add(s))));
72-
58+
connection.receive(m -> Platform.runLater(() -> messages.add(m)));
7359
}
7460
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.example;
2+
3+
import java.util.function.Consumer;
4+
5+
public interface NtfyConnection {
6+
7+
public boolean send(String message);
8+
9+
public void receive(Consumer<NtfyMessageDto> messageHandler);
10+
11+
12+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.example;
2+
3+
import io.github.cdimascio.dotenv.Dotenv;
4+
import tools.jackson.databind.ObjectMapper;
5+
import java.io.IOException;
6+
import java.net.URI;
7+
import java.net.http.HttpClient;
8+
import java.net.http.HttpRequest;
9+
import java.net.http.HttpResponse;
10+
import java.util.Objects;
11+
import java.util.function.Consumer;
12+
13+
public class NtfyConnectionImpl implements NtfyConnection {
14+
15+
private final HttpClient http = HttpClient.newHttpClient();
16+
private final String hostName;
17+
private final ObjectMapper mapper = new ObjectMapper();
18+
19+
public NtfyConnectionImpl() {
20+
Dotenv dotenv = Dotenv.load();
21+
hostName = Objects.requireNonNull(dotenv.get("HOST_NAME"));
22+
}
23+
24+
@Override
25+
public boolean send(String message) {
26+
HttpRequest httpRequest = HttpRequest.newBuilder()
27+
.POST(HttpRequest.BodyPublishers.ofString("Hello World!🚀"))
28+
.header("Cache", "no")
29+
.uri(URI.create(hostName + "/mytopic"))
30+
.build();
31+
32+
try {
33+
var response = http.send(httpRequest, HttpResponse.BodyHandlers.ofString());
34+
return true;
35+
} catch (IOException e) {
36+
System.out.println("Error sending message");
37+
} catch (InterruptedException e) {
38+
System.out.println("Interrupted sending message");
39+
}
40+
return false;
41+
}
42+
43+
@Override
44+
public void receive(Consumer<NtfyMessageDto> messageHandler) {
45+
HttpRequest httpRequest = HttpRequest.newBuilder()
46+
.GET()
47+
.uri(URI.create(hostName + "/mytopic/json"))
48+
.build();
49+
50+
http.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofLines())
51+
.thenAccept(response -> response.body()
52+
.map( s -> mapper.readValue(s, NtfyMessageDto.class))
53+
.filter(message -> message.event().equals("message"))
54+
.peek(System.out::println)
55+
.forEach(messageHandler));
56+
57+
}
58+
}

src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
requires java.sql;
77
requires tools.jackson.databind;
88
requires java.desktop;
9+
requires javafx.graphics;
910

1011
opens com.example to javafx.fxml;
1112
exports com.example;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.example;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.assertj.core.api.Assertions.assertThat;
6+
7+
class HelloModelTest {
8+
9+
@Test
10+
void sendMessageCallsConnectionWithMessageToSend() {
11+
// Arrange, Given
12+
var spy = new NtfyConnectionSpy();
13+
var model = new HelloModel(spy);
14+
model.setMessageToSend("Hello World");
15+
// Act, When
16+
model.sendMessage();
17+
// Assert, Then
18+
assertThat(spy .message).isEqualTo("Hello World");
19+
}
20+
21+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.example;
2+
3+
import java.util.function.Consumer;
4+
5+
public class NtfyConnectionSpy implements NtfyConnection{
6+
7+
String message;
8+
9+
@Override
10+
public boolean send(String message) {
11+
this.message = message;
12+
return true;
13+
}
14+
15+
@Override
16+
public void receive(Consumer<NtfyMessageDto> messageHandler) {
17+
18+
}
19+
}

0 commit comments

Comments
 (0)