-
Notifications
You must be signed in to change notification settings - Fork 1
Lab3 #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lab3 #1
Changes from all commits
388ee6f
12283ee
d205b0e
81917ad
efa87b1
e245be3
fc4049a
200137e
df38385
aa03857
c00a1bf
1754001
1fe3050
460c3da
6faaeb9
287c263
78d13df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| target/ | ||
| /.idea/ | ||
| .env |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,99 @@ | ||
| package com.example; | ||
|
|
||
| import javafx.event.ActionEvent; | ||
| import javafx.fxml.FXML; | ||
| import javafx.scene.control.Label; | ||
| import javafx.scene.control.ListView; | ||
| import javafx.scene.control.TextField; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| /** | ||
| * Controller layer: mediates between the view (FXML) and the model. | ||
| * Handles user interaction, initializes UI bindings, and forwards actions | ||
| * (sending messages, switching topics) to the model. | ||
| */ | ||
| public class HelloController { | ||
|
|
||
| private final HelloModel model = new HelloModel(); | ||
| /** The application model injected by the framework or calling code. */ | ||
| private final HelloModel model; | ||
|
|
||
| /** | ||
| * Default constructor used by the JavaFX runtime. | ||
| * Creates a model with a production {@link NtfyConnectionImpl}. | ||
| */ | ||
| public HelloController() { | ||
| this(new HelloModel(new NtfyConnectionImpl())); | ||
| } | ||
|
|
||
| /** | ||
| * Constructor primarily intended for testing or dependency injection. | ||
| * | ||
| * @param model the model instance this controller should use | ||
| */ | ||
| public HelloController(HelloModel model) { | ||
| this.model = model; | ||
| } | ||
|
|
||
| @FXML | ||
| public ListView<NtfyMessageDto> messageView; | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| @FXML | ||
| private Label messageLabel; | ||
|
|
||
| @FXML | ||
| private Label statusLabel; | ||
|
|
||
| @FXML | ||
| private TextField inputField; | ||
|
|
||
| @FXML | ||
| private TextField topicField; | ||
|
|
||
| /** | ||
| * Called automatically by JavaFX after FXML fields are injected. | ||
| * Sets up UI bindings, listens for connection status changes, | ||
| * and triggers the initial topic connection. | ||
| */ | ||
| @FXML | ||
| private void initialize() { | ||
| if (messageLabel != null) { | ||
| messageLabel.setText(model.getGreeting()); | ||
| } | ||
|
|
||
| // Bind input fields to model state | ||
| inputField.textProperty().bindBidirectional(model.messageToSendProperty()); | ||
| topicField.textProperty().bindBidirectional(model.topicProperty()); | ||
| messageView.setItems(model.getMessages()); | ||
|
|
||
| // Update connection status indicator | ||
| model.connectedProperty().addListener((obs, wasConnected, isConnected) -> { | ||
| statusLabel.setText(isConnected ? "🟢 Connected" : "🔴 Disconnected"); | ||
| }); | ||
|
|
||
| model.connectToTopic(); | ||
| } | ||
|
|
||
| /** | ||
| * Handles clicking the "Send" button. | ||
| * Sends the message via the model and clears the input field. | ||
| */ | ||
| public void sendMessage(ActionEvent actionEvent) { | ||
| if (!inputField.getText().trim().isEmpty()) { | ||
| try { | ||
| model.sendMessage(); | ||
| inputField.clear(); | ||
| } catch (IOException e) { | ||
| System.err.println("Failed to send message: " + e.getMessage()); | ||
| } | ||
|
Comment on lines
+86
to
+88
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Show user-visible error feedback instead of System.err. In a GUI application, users cannot see Replace console logging with a JavaFX Alert: } catch (IOException e) {
- System.err.println("Failed to send message: " + e.getMessage());
+ var alert = new Alert(Alert.AlertType.ERROR);
+ alert.setTitle("Send Failed");
+ alert.setHeaderText("Failed to send message");
+ alert.setContentText(e.getMessage());
+ alert.showAndWait();
}Don't forget to add the import: import javafx.scene.control.Alert;🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Handles clicking the "Connect" button. | ||
| * Reconnects the model to the current topic. | ||
| */ | ||
| public void connectToTopic(ActionEvent actionEvent) { | ||
| model.connectToTopic(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,87 @@ | ||
| package com.example; | ||
|
|
||
| import javafx.application.Platform; | ||
| import javafx.beans.property.ReadOnlyBooleanProperty; | ||
| import javafx.beans.property.ReadOnlyBooleanWrapper; | ||
| import javafx.beans.property.SimpleStringProperty; | ||
| import javafx.beans.property.StringProperty; | ||
| import javafx.collections.FXCollections; | ||
| import javafx.collections.ObservableList; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| /** | ||
| * Model layer: encapsulates application data and business logic. | ||
| * Manages the active topic subscription, incoming messages, and | ||
| * message sending through an {@link NtfyConnection}. | ||
| */ | ||
| public class HelloModel { | ||
|
|
||
| /** Underlying connection for sending and receiving messages. */ | ||
| private final NtfyConnection connection; | ||
| /** Observable list of received messages for UI binding. */ | ||
| private final ObservableList<NtfyMessageDto> messages = FXCollections.observableArrayList(); | ||
| /** Text the user intends to send. */ | ||
| private final StringProperty messageToSend = new SimpleStringProperty(); | ||
| /** Currently selected topic. */ | ||
| private final StringProperty topic = new SimpleStringProperty("mytopic"); | ||
| /** Handle for the active subscription, if any. */ | ||
| private NtfyConnection.Subscription currentSubscription; | ||
| /** Indicates whether the model is currently connected to a topic. */ | ||
| private final ReadOnlyBooleanWrapper connected = new ReadOnlyBooleanWrapper(false); | ||
|
|
||
| /** | ||
| * Creates a new model using the provided {@link NtfyConnection}. | ||
| * | ||
| * @param connection the message connection backend | ||
| */ | ||
| public HelloModel(NtfyConnection connection) { | ||
| this.connection = connection; | ||
| } | ||
|
|
||
| /** @return observable list of received messages */ | ||
| public ObservableList<NtfyMessageDto> getMessages() { | ||
| return messages; | ||
| } | ||
|
|
||
| public StringProperty messageToSendProperty() { | ||
| return messageToSend; | ||
| } | ||
|
|
||
| public String getMessageToSend() { | ||
| return messageToSend.get(); | ||
| } | ||
|
|
||
| public void setMessageToSend(String message) { | ||
| messageToSend.set(message); | ||
| } | ||
|
|
||
| public String getTopic() { | ||
| return topic.get(); | ||
| } | ||
|
|
||
| public StringProperty topicProperty() { | ||
| return topic; | ||
| } | ||
|
|
||
| public void setTopic(String topic) { | ||
| this.topic.set(topic); | ||
| } | ||
|
|
||
| /** | ||
| * Read-only property indicating whether a subscription is active. | ||
| */ | ||
| public ReadOnlyBooleanProperty connectedProperty() { | ||
| return connected.getReadOnlyProperty(); | ||
| } | ||
|
|
||
| /** | ||
| * @return true if a subscription is active and open | ||
| */ | ||
| public boolean isConnected() { | ||
| return connected.get(); | ||
| } | ||
|
|
||
| /** | ||
| * Returns a greeting based on the current Java and JavaFX versions. | ||
| */ | ||
|
|
@@ -12,4 +90,73 @@ public String getGreeting() { | |
| String javafxVersion = System.getProperty("javafx.version"); | ||
| return "Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + "."; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Sends the value of {@link #messageToSend} to the current topic. | ||
| * | ||
| * @throws IOException if sending through the connection fails | ||
| */ | ||
| public void sendMessage() throws IOException { | ||
| connection.send(topic.get(), messageToSend.get()); | ||
| messageToSend.set(""); | ||
| } | ||
|
Comment on lines
+94
to
+102
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify that the controller handles IOException from sendMessage. The exception-based error handling is good: on success, the input is cleared (line 101); on failure, the exception prevents clearing so the user can retry. However, ensure the controller catches and handles the Run this script to check how the controller handles exceptions from 🏁 Script executed: #!/bin/bash
# Description: Verify HelloController handles IOException from sendMessage
# Search for sendMessage() calls and surrounding error handling
rg -n -A 10 -B 3 '\.sendMessage\s*\(' --type=javaLength of output: 3620 Error handling exists but lacks user-facing feedback. The controller properly catches 🤖 Prompt for AI Agents |
||
|
|
||
| /** | ||
| * Connects to the current topic by creating a new subscription. | ||
| * Any previous subscription is closed first. | ||
| * Old messages are preserved if subscription creation fails. | ||
| * Incoming messages are added to {@link #messages} on the JavaFX thread. | ||
| */ | ||
| public void connectToTopic() { | ||
| disconnect(); | ||
|
|
||
| // Make a backup of current messages in case subscription fails | ||
| var oldMessages = FXCollections.observableArrayList(messages); | ||
| // Clear messages for the new topic | ||
| messages.clear(); | ||
|
|
||
| try { | ||
| // Start receiving new messages asynchronously | ||
| currentSubscription = connection.receive(topic.get(), | ||
| m -> runOnFx(() -> messages.add(m))); | ||
| // Mark as connected | ||
| connected.set(true); | ||
| } catch (Exception e) { | ||
| // Restore old messages if connection failed | ||
| messages.setAll(oldMessages); | ||
| connected.set(false); | ||
| System.err.println("Failed to connect to topic: " + e.getMessage()); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * Stops the active subscription, if one exists, and updates connection state. | ||
| */ | ||
| public void disconnect() { | ||
| if (currentSubscription != null) { | ||
| try { | ||
| if (currentSubscription.isOpen()) { | ||
| currentSubscription.close(); | ||
| } | ||
| } catch (IOException e) { | ||
| System.err.println("Error closing subscription: " + e.getMessage()); | ||
| } | ||
| currentSubscription = null; | ||
| connected.set(false); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Ensures that the given task runs on the JavaFX thread. | ||
| * Falls back to direct execution if JavaFX is not initialized (e.g. in tests). | ||
| */ | ||
| private static void runOnFx(Runnable task) { | ||
| try { | ||
| if (Platform.isFxApplicationThread()) task.run(); | ||
| else Platform.runLater(task); | ||
| } catch (IllegalStateException notInitialized) { | ||
| task.run(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| package com.example; | ||
|
|
||
| import java.io.Closeable; | ||
| import java.io.IOException; | ||
| import java.util.function.Consumer; | ||
|
|
||
| /** | ||
| * Represents a connection to a Ntfy-compatible notification service. | ||
| * Implementations of this interface provide basic operations for: | ||
| * * Sending messages to a specific topic | ||
| * * Subscribing to incoming messages from a topic | ||
| */ | ||
| public interface NtfyConnection { | ||
|
|
||
| /** | ||
| * Sends a message to the given topic. | ||
| * | ||
| * @param topic the topic to publish to (must not be null or blank) | ||
| * @param message the message content to send | ||
| * @throws IOException if the message cannot be delivered due to | ||
| * network errors or underlying I/O issues | ||
| */ | ||
| void send(String topic, String message) throws IOException; | ||
|
|
||
| /** | ||
| * Subscribes to a topic and receives messages asynchronously. | ||
| * | ||
| * @param topic the topic to subscribe to | ||
| * @param messageHandler callback invoked for every received message on a background thread | ||
| * @return a {@link Subscription} that controls the active message stream | ||
| */ | ||
| Subscription receive(String topic, Consumer<NtfyMessageDto> messageHandler); | ||
|
|
||
| /** | ||
| * Controls an active topic subscription. | ||
| * Encapsulates the logic to stop an active message stream. | ||
| */ | ||
| interface Subscription extends Closeable { | ||
|
|
||
| /** | ||
| * Closes this subscription and stops receiving messages. | ||
| * | ||
| * @throws IOException if closing fails | ||
| */ | ||
| @Override | ||
| void close() throws IOException; | ||
|
|
||
| /** | ||
| * Checks whether the subscription is still active. | ||
| * | ||
| * @return true if active, false otherwise | ||
| */ | ||
| boolean isOpen(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect Jackson group ID.
The group ID
tools.jackson.coreappears incorrect. The standard Jackson library usescom.fasterxml.jackson.coreas the group ID.Apply this diff to correct the group ID:
Note: Jackson 3.x is still in development. Version 2.18.2 is the latest stable release from the 2.x series.
📝 Committable suggestion
🤖 Prompt for AI Agents