2

I have an JavaFx application that has no stage. It only runs at system tray. Basically it listen to a service and show notification according to it.

The connection between app and service is done using Socket. However, service can send a priority message, which will be shown first than others.

The problem: I have all my messages in a PriorityQueue but I don't know how to handle a notification await for the other finish to show. Is that the best approach? Is the architecture correct? Also, since TrayNotification class will show a Scene, I'm afraid of having problems with UI Thread.

This is Message class:

public class Message implements Comparable<Message> {

    private int priority;
    private String notificationType;
    private String title;
    private String message;

    public Message() {

    }

    public Message (int priority, String notificationType, String title, String message) {
        this.priority = priority;
        this.notificationType = notificationType;
        this.title = title;
        this.message = message;
    }

    public void setPriority(int priority) {
        this.priority = priority;
    }

    public int getPriority() {
        return this.priority;
    }

    public void setNotificationType(String notificationType) {
        this.notificationType = notificationType;
    }

    public NotificationType getNotificationType() {
        if (this.notificationType.equals(NotificationType.CUSTOM.toString())) {
            return NotificationType.CUSTOM;
        }
        else if (this.notificationType.equals(NotificationType.ERROR.toString())) {
            return NotificationType.ERROR;
        }
        else if (this.notificationType.equals(NotificationType.INFORMATION.toString())) {
            return NotificationType.INFORMATION;
        }
        else if (this.notificationType.equals(NotificationType.NOTICE.toString())) {
            return NotificationType.NOTICE;
        }
        else if (this.notificationType.equals(NotificationType.SUCCESS.toString())) {
            return NotificationType.SUCCESS;
        }
        else if (this.notificationType.equals(NotificationType.WARNING.toString())) {
            return NotificationType.WARNING;
        }
        else {
            throw new IllegalArgumentException("Invalid notification type.");
        }
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTitle() {
        return this.title;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getMessage() {
        return this.message;
    }

    @Override
    public int compareTo(Message otherMessage) {
        return Integer.compare(this.priority, otherMessage.getPriority());
    }
}

My application class, SystemtrayLauncher, has this code on start method, after configuring tray:

/** Start to listen to service **/
ServiceConnector connector = new ServiceConnector(8888);
new Thread(connector).start();

ServiceConnector (which I think needs to be improved to handle PriorityQueue):

public class ServiceConnector extends Task<Void> {

    private ServerSocket socket;
    private int port;
    public static PriorityQueue<Message> messageQueue = new PriorityQueue<>();

    public ServiceConnector(int port) {
        this.port = port;
    }

    public void connect() {

        try {
            System.out.println("Opening connection...");
            socket = new ServerSocket(this.port);
            socket.setSoTimeout(0);

            System.out.println("Connection opened at port " + this.port);

            while (true) {

                System.out.println("Awaiting service connection...");
                Socket service = socket.accept();
                System.out.println(
                    "Service at " + service.getInetAddress().getHostAddress() + " connected");

                Message message = MessageListener.getMessage(service);

                if (message != null) {
                    messageQueue.offer(message);

                    // get top priority message
                    Platform.runLater(() -> MessageListener.notifyUser(messageQueue.peek()));
                }
                else {
                    CustomAlert dialog = new CustomAlert(Alert.AlertType.ERROR);
                    dialog.setContentText(SystemConfiguration.LOCALE.getString("MESSAGE_ERROR"));
                    dialog.showAndWait();
                }

                service.close();
            }

        } catch (IOException exc) {
            exc.printStackTrace();
        }
    }

    @Override
    protected Void call() throws Exception {
        this.connect();
        return null;
    }
}

MessageListener

public class MessageListener {

    private static TrayNotification trayNotification;

    public static Message getMessage(Socket service) {
        System.out.println("Processing message...");

        try {
            BufferedReader inputReader =
                new BufferedReader(new InputStreamReader(service.getInputStream()));

            /**
             * JSON format:
             * {
             *     "priority": "1 for urgent and greater with less priority",
             *     "notificationType": "ERROR|INFORMATION|NOTICE|SUCCESS|WARNING",
             *     "title": "A string to be show as notification windows title",
             *     "message": "A string to be show as message"
             * }
             */

            JSONObject jsonMessage = new JSONObject(inputReader.readLine());

            Message message = new Message();
            message.setPriority(jsonMessage.getInt("priority"));
            message.setNotificationType(jsonMessage.getString("notificationType"));
            message.setTitle(jsonMessage.getString("title"));
            message.setMessage(jsonMessage.getString("message"));

            inputReader.close();
            service.close();

            System.out.println("Message with priority " + message.getPriority() + " processed.");

            return message;

        } catch (IOException exc) {
            exc.printStackTrace();
            return null;
        }
    }

    /**
     * Notify user with processed service message.
     * @param message
     *
     */
    public static void notifyUser(Message message) {

        System.out.println("Priority: " + message.getPriority());

        trayNotification = new TrayNotification();
        trayNotification.setAnimationType(AnimationType.POPUP);
        trayNotification.setRectangleFill(Paint.valueOf("#0277BD"));
        trayNotification.setImage(new Image(SystemConfiguration.ICON));

        trayNotification.setNotificationType(message.getNotificationType());
        trayNotification.setTitle(message.getTitle());
        trayNotification.setMessage(message.getMessage());

        trayNotification.showAndDismiss(Duration.seconds(3.5));

        ServiceConnector.messageQueue.poll();
    }
}
Leonardo
  • 1,263
  • 7
  • 20
  • 51

0 Answers0