Java, Telegram Bot runtime problems

67 Views Asked by At

I'll start by saying that I'm not a Java expert, and I'm facing a really strange problem that I'm not able to solve. I'm working on an application to which I decided to add a telegram bot in order to give some remote information. When I run the application from the IDE (currently I'm using IntelliJ IDEA) all works fine, as soon as I create an executable version of the same application the telegram bot stops to working without throw any exception and I cannot figure out what I'm doing wrong. Now in order to isolate the problem I created a dummy project that implement only the telegram bot (that I've extracted from the first project) but the behavior is the same: from IDE no problem, from executable the bot don't work. In the following section you can find all the details about the code and all the dependencies that I'm using. Basically I created a JavaFX project that is made by only one scene whit 2 buttonsç

  • Connect: used to open the connection with the telegram bot
  • Send: used to send a "Test" message over the bot channel.

Application View

Code

Here you can find the FX controller class:

package com.example.telegrambotui;

import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Optional;

public class HelloController {
    @FXML
    private Label welcomeText;

    private TelegramBot telegramBot;

    @FXML
    protected void connectClick() throws IOException {
        try {
            telegramBot = new TelegramBot("My_test_bot");
            welcomeText.setText("Connected");
        } catch (Exception e) {
            File file = new File("C:\\Users\\luca-\\IdeaProjects\\TelegramBotUI\\Installer\\ConnectException.txt");
            file.createNewFile();
            PrintWriter pw = new PrintWriter(file);
            e.printStackTrace(pw);
        }
    }

    @FXML
    protected void onTestButtonClick() throws IOException {
        try {
            telegramBot.sendMessage("Test");
            welcomeText.setText("Sent \"Test\"");
        } catch (TelegramApiException e) {
            welcomeText.setText("Excetion!!");
            fireAlarm(Alert.AlertType.ERROR, HelloApplication.stage, "Error", "Connection error!", e.getMessage());
            File file = new File("C:\\Users\\luca-\\IdeaProjects\\TelegramBotUI\\Installer\\TestButtonException.txt");
            file.createNewFile();
            PrintWriter pw = new PrintWriter(file);
            e.printStackTrace(pw);
            pw.close();
        }

    }

    private Optional<ButtonType> fireAlarm(Alert.AlertType type, Stage owner, String title, String headerText, String contentText) {
        Alert alert = new Alert(type);
        alert.initOwner(owner);
        alert.setTitle(title);
        alert.setContentText(contentText);
        if (!headerText.equals("")) {
            alert.setHeaderText(headerText);
        }

        return alert.showAndWait();
    }
}

Here you can find the TelegramBot class:

package com.example.telegrambotui;

import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;


public class TelegramBot extends TelegramLongPollingBot {
    private final static HashMap<String, TelegramChannel> AvailableBots = new HashMap<>(){{
        put("My_test_bot", new TelegramChannel("My_test_bot", "Here I've put the bot Token"));
    }};

    private TelegramChannel telegramChannel;
    private final String INIT;

    private final String HELLO_WORLD = "/hello";
    private final String IS_ALIVE = "/alive";
    private final List<String> COMMANDS = Arrays.asList( IS_ALIVE, HELLO_WORLD);
    private TelegramBotsApi telegramBotsApi;


    public TelegramBot(String channel) throws TelegramApiException {
        telegramChannel = AvailableBots.get(channel);
        telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class);
        telegramBotsApi.registerBot(this);
        INIT = "<strong>[" + telegramChannel.username() + "]</strong>\n";
    }

    public static String[] getAvailableBot() {
        String[] bots = new String[AvailableBots.keySet().size()];
        int i = 0;
        for(String k: AvailableBots.keySet()){
            bots[i] = k;
            i++;
        }
        return bots;
    }

    @Override
    public void onUpdateReceived(Update update) {
        if (update.hasChannelPost() && update.getChannelPost().hasText()) {
            if (COMMANDS.contains(update.getChannelPost().getText())){
                try {
                    switch (update.getChannelPost().getText()){
                        case HELLO_WORLD -> sendMessage("Hello World!");
                        case IS_ALIVE -> sendMessage("I'm alive!!");
                    }
                } catch (TelegramApiException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public void sendMessage(String mex) throws TelegramApiException {
        if(!mex.startsWith(INIT)){
            mex = INIT + mex;
        }
        SendMessage toSend = new SendMessage(telegramChannel.chat_id(), mex);
        toSend.enableHtml(true);

        execute(toSend);
    }

    @Override
    public String getBotUsername() {
        return telegramChannel.username();
    }

    @Override
    public String getBotToken() {
        return telegramChannel.token();
    }
}

Dependencies

Here you can find all the dependencies:

Dependencies

And this is the Artifacts file:

Artifacts part 1 Artifacts part 2

Executable script

In order to generate the executable file Im using the following script:

jpackage -t exe --name "TelegramBotUI"  --icon ".\MyIcon.ico" --input "../out/artifacts/TelegramBotUI_jar" --dest "./" --main-jar "TelegramBotUI.jar" --main-class "com.example.telegrambotui.HelloApplication" --module-path "C:\Program Files\Java\javafx-jmods-17.0.2" --add-modules javafx.controls,javafx.fxml --win-menu --win-dir-chooser

Since I didn't catch any exception from the executable version, I tried to save any kind of exception in the txt file if there was one but none was caught. I think that Im doing some mistakes in the way I generate the executable because from the IDE the application works without any problem. I've tried to change the Telegram bot version with a new one (6.9.7.1) but nothing has changed. What am I doing wrong?

[EDIT 1]

Here you can find the Application class:

package com.example.telegrambotui;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    public static Stage stage;
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        this.stage = stage;
        stage.setOnCloseRequest(event -> {
            System.exit(0);
        });

        Scene scene = new Scene(fxmlLoader.load(), 320, 240);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

Detail about the problem

The excepted behavior is that I press the connect button and then when I press the Test button the bot should post a "Test" message over the telegram channel; if I wrote /hello or /alive over the telegram channel the bot should respond, respectively, with an "Hello" or "I'm alive" message. Basically the problem is that the bot, from the excecutable application, does not respond without giving any exception.

[EDIT 2]

Following the tips in the comment I've added an UncaughtExceptionHandler to the Application class and now when I press the connect button I encounter this exception:

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(Unknown Source)
    at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(Unknown Source)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
    at javafx.base/javafx.event.Event.fireEvent(Unknown Source)
    at javafx.graphics/javafx.scene.Node.fireEvent(Unknown Source)
    at javafx.controls/javafx.scene.control.Button.fire(Unknown Source)
    at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(Unknown Source)
    at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(Unknown Source)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
    at javafx.base/javafx.event.Event.fireEvent(Unknown Source)
    at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Unknown Source)
    at javafx.graphics/javafx.scene.Scene.processMouseEvent(Unknown Source)
    at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source)
    at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(Unknown Source)
    at javafx.graphics/com.sun.glass.ui.View.notifyMouse(Unknown Source)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(Unknown Source)
    at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.javafx.reflect.Trampoline.invoke(Unknown Source)
    at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(Unknown Source)
    at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(Unknown Source)
    ... 47 more
Caused by: java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
    at org.telegram.telegrambots.bots.DefaultAbsSender.<clinit>(DefaultAbsSender.java:66)
    at com.example.telegrambotui.HelloController.connectClick(HelloController.java:24)
    ... 57 more
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
    at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
    ... 59 more

It seems that the problem is caused be the slf4j Logger Factory class that cannot be found but if you look at the Artifact I've added it.

0

There are 0 best solutions below