rubenlagus / TelegramBots

Java library to create bots using Telegram Bots API
https://telegram.me/JavaBotsApi
MIT License
4.77k stars 1.22k forks source link

Java EE #1

Closed elettrico closed 6 years ago

elettrico commented 8 years ago

Hi, I'm trying to use telegram api inside an entreprise application. It is working but there are a lot of problem due to thread generations UpdatesThread.java, because threads conflict with the container. Is there a way to use your library in java EE or do you know any working implementation? Thank you

rubenlagus commented 8 years ago

Hi, can you give a bit more information about the error you are getting (stacktrace, where it crash, etc)?

This library is running in my example for 6 bots at the same time in same instances and I don't get any error.

elettrico commented 8 years ago

Hi rubenlagus, it is not an error: in a java SE environment your example works perfectly, but it is forbidden in a java EE environment to use threads: creation, destruction and dafety of threads are managed by the container (glassfish, in this case) using beans. UpdatesThread run two threads for every bot, synchronizing them using a list, in java EE it's not necessary and "illegal", so I'm trying to modify the library source to adapt it to a java EE environment: using a Singleton bean and a timer for scheduling the update every 5 seconds seems to work. My changes to the code are far from being optimized, and I've to cut out some libraries for avoiding conflict (jersey is included in glassfish, for example), so I'be broken the webhook method, but if you want to see what I'm talking about I can mail you my experiment.

rubenlagus commented 8 years ago

Sure, drop me a line at @ruben

elettrico commented 8 years ago

Done. I'll wait your reply.

montalbano commented 8 years ago

Hi elettrico I have a big issue with the integration of this library in my Spring MVC project...did you modify the library to work properly in Java EE? I explained my problem in this issue: https://github.com/rubenlagus/TelegramBots/issues/32

elettrico commented 8 years ago

Il 15/04/2016 13:30, montalbano ha scritto:

Hi elettrico I have a big issue with the integration of this library in my Spring MVC project...did you modify the library to work properly in Java EE?

actually it's working. I don't know much about spring, but the big problem with java ee was the thread creation, I've changed the thread creation using beans that are managed by the container. maybe it's something similar in spring?

montalbano commented 8 years ago

yes, but my problem is in the HOT REDEPLOY of glassfish:

Warning: Error invoking requestInitialized method on ServletRequestListener org.jboss.weld.servlet.WeldListener org.jboss.weld.exceptions.IllegalStateException: WELD-000227: Bean identifier index inconsistency detected - the distributed container probably does not work with identical applications Expected hash: 422265265 Current index: BeanIdentifierIndex [hash=-141639221, indexed=20]:

Bean identifier index inconsistency..and this block the whole application..I don't know why

montalbano commented 8 years ago

There is another error in my stacktrace: Grave: Exception in thread "Thread-41" Grave: java.lang.IllegalStateException: This web container has not yet been started at org.glassfish.web.loader.WebappClassLoader.findResourceInternal(WebappClassLoader.java:2827) at org.glassfish.web.loader.WebappClassLoader.findResource(WebappClassLoader.java:1320) at org.glassfish.web.loader.WebappClassLoader.getResourceAsStream(WebappClassLoader.java:1528) at org.apache.http.util.VersionInfo.loadVersionInfo(VersionInfo.java:233) at org.apache.http.util.VersionInfo.getUserAgent(VersionInfo.java:319) at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:1046) at org.telegram.telegrambots.updatesreceivers.UpdatesThread$ReaderThread.run(UpdatesThread.java:62)

montalbano commented 8 years ago

I googled for hours and found the solution: I set a new system property in glassfish

org.jboss.weld.serialization.beanIdentifierIndexOptimization = false

to avoid the appearing inconsistencies as explained in the WELD reference here: link

rubenlagus commented 8 years ago

@elettrico May this solve also your issues with it?

elettrico commented 8 years ago

Hi ruben, I didn't have this kind of issue because I've changed the thread model for a bean model: in a EE environment it's a bad practice to use threads: threads have to be managed by the container because it's the container that knows when a thread is needed and when to end it. So I prefer to use beans and let the container (glassfish, in my case) to manage the life of the processes as java EE specificacion suggest. In case of hot redeploy (or not) there are no thread that start before the complete initialization of his container: the org.telegram.telegrambots.updatesreceivers.UpdatesThread$ReaderThread use threads, instead I have a singleton started by glassfish when it's ready and killed during the undeploy. This stackoverflow thread about threads and java EE is interesting http://stackoverflow.com/questions/3212255/java-ee-specification-and-multi-threading Thank you

lapsatech commented 8 years ago

Hi @elettrico @rubenlagus ! Well, did you find a solution for the correct integration TelegramBots with Java EE environment?

antonkazakov commented 8 years ago

@montalbano could u provide an example how did you fixed the issue?

antonkazakov commented 8 years ago

@elettrico could you show me what did you changed

elettrico commented 8 years ago

basically I've created and interface and an abstract class for using with bean, the are copies of the ITelegramLongPollingBot and TelegramLongPollingBot. then I've created an UpdatesBean as a @Singleton and instead of using threads I've used @Schedule annotation for the update method. of course I've added a registerBot(TelegramBeanPollingBot bot) method in TelegramBotsApi class. after that I've created another singleton, TelegramSession, in which I inject UpdatesBean and my bot handler, a bean extending TelegramBeanPollingBot. the last thing I've done is a @Singleton @Startup that use TelegramSession singleton to start the session in @PostConstruct and stop it in @PreDestroy. in this way all the threads are managed as beans by the container.

montalbano commented 8 years ago

I simply set a system property in Glassfish Admin Panel to avoid the bean Identifier Index Optimization.

1) Right Click on the server and choose: "View Domain Admin Console" 2) Configurations -> Server-config -> System properties 3) Click Add Property and add this: org.jboss.weld.serialization.beanIdentifierIndexOptimization = false

antonu17 commented 8 years ago

Detected one more threads issue. When using spring boot with spring-boot-devtools Automatic restart feature new ReaderThread and HandlerThread are starting on spring boot "hot restart". Only "cold" restart (i mean killing jvm :) ) allows original ReaderThread and HandlerThread to stop. Here is an debugger picture after "hot restarting" 3 times: Threads

antonu17 commented 8 years ago

OK, i sloved that "problem" like this:

@Component
public class Worker implements ApplicationRunner {

    private static final Logger log = LoggerFactory.getLogger(Worker.class);

    @Autowired
    private MyTelegramBot bot;
    @Autowired
    private TelegramBotsApi telegramBotsApi;
    private BotSession botSession;

    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {
        try {
            botSession = telegramBotsApi.registerBot(bot);
        } catch (TelegramApiException e) {
            log.error(e.getApiResponse(), e);
        }
    }

    @PreDestroy
    public void tearDown() {
        botSession.close();
    }
}

So on every hot restart request tearDown() is fired and threads ReaderThread and HandlerThread are closed via BotSession.close()

segator commented 7 years ago

I'm getting this error No implementation for org.telegram.telegrambots.generics.BotSession was bound using spring boot

@SpringBootApplication
public class AutoDownloaderApplication implements CommandLineRunner {

    @Autowired
    private MovieGrabber movieGrabber;
    @Autowired
    private TelegramBotsApi telegramBotsApi;
    private BotSession botSession;

    @Override
    public void run(String... args) throws Exception {

        botSession = telegramBotsApi.registerBot(movieGrabber);
    }

    @Bean
    public TelegramBotsApi getTelegramBotsApi() {
        return new TelegramBotsApi();
    }

    @PreDestroy
    public void tearDown() {
        botSession.close();
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(AutoDownloaderApplication.class, args);
    }
}
drunckoder commented 7 years ago

https://github.com/rubenlagus/TelegramBots/issues/161

Boburmirzo commented 7 years ago

Hello, I am trying to use telegram api inside JSF CDI container. Your example bots are working well but I got this error repeatedly 409 [Error]: Conflict: terminated by other long poll or webhook. I try to initialize TelegramBotApi inside ServletContextListener and close botSection when context is destroyed. Here is code. @WebListener public class WebContextListener implements ServletContextListener {

private static final Logger LOGGER = LoggerFactory.getLogger(WebContextListener.class);

private BotSession botSession;

@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
    LOGGER.debug("Web context initialisation has been started");
    try {
        ApiContextInitializer.init();
        TelegramBotsApi telegramBotsApi = new TelegramBotsApi();
        try {
            // Register long polling bots. They work regardless type of TelegramBotsApi we are creating
            botSession=telegramBotsApi.registerBot(new CommandsHandler());
        } catch (TelegramApiException e) {
            BotLogger.error("Initialize", e);
        }
    } catch (Exception e) {
        BotLogger.error("Initialize", e);
    }
}

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
    LOGGER.info("contextDestroyed start");
    botSession.close();
    LOGGER.info("Bot stop");
}

}

I fixed this problem and faced with another one but everything is working well, when I stop each time WildFly JBoss server it is showing this exception BOTSESSION: java.net.SocketException: Socket closed. maybe I am doing something wrong. How to implement your library for CDI JAVA EE application? Please give me any idea. Thank you

rubenlagus commented 7 years ago

@Boburmirzo I think your second problem is related to #168

Regarding first one, just make sure that you are not registering the same bot twice. Remember that you can only run one concurrent getUpdates request.

SinaDBMS commented 7 years ago

@elettrico Hi, i'm facing the same issue, the problem occurs when i register the Bots inside a session bean. Could you or any one else who has managed to overcome the problem give a more detailed answer or when possible the modified version of this api? Thank you in advance!

Boburmirzo commented 7 years ago

Hello @elettrico, Which container are you using? In our case, we used JSF CDI container, I register bots when servlet context is initialized and stop when context is destroyed. For example, we are using Shiro web environment by customizing EnvironmentLoaderListener class like this:

public class CustomEnvironmentLoaderListener extends EnvironmentLoaderListener { @Inject private OrdersBotLongPolling ordersBotLongPolling; // make sure that BotPolling class should be annotated // @named and @Dependent if you are using JSF CDI beans ................................................... private DefaultBotSession ordersBotSession; private DefaultBotSession productsBotSession;
..................... @Override protected WebEnvironment createEnvironment(ServletContext pServletContext) { ............................ registerBots(); }

private void registerBots() { LOGGER.debug("Telegram bots initialisations has been started"); ApiContextInitializer.init(); registerOrdersBot(); }

private void registerOrdersBot() { LOGGER.debug("Initializing Likada Orders Bot"); try { ordersBotLongPolling.clearWebhook(); ordersBotLongPolling.register(firstcommand); ordersBotLongPolling.register(secondcommand); ordersBotSession = ApiContext.getInstance(DefaultBotSession.class); ordersBotSession.setToken(ordersBotLongPolling.getBotToken()); ordersBotSession.setOptions(ordersBotLongPolling.getOptions()); ordersBotSession.setCallback(ordersBotLongPolling); ordersBotSession.start(); } catch (TelegramApiException e) { BotLogger.error("Initialize", e); } } @Override public void destroyEnvironment(ServletContext servletContext) { super.destroyEnvironment(servletContext); productsBotSession.stop(); ordersBotSession.stop(); LOGGER.info("Bots are stopped"); } }

if you would like to inject all you beans inside bot controller, put annotation like following:

@Named @ApplicationScoped public class OrdersBotController { @Inject private TelegramUserService telegramUserService; } We also tried to put Bot inside a session bean, but It does not work. Then, we put inside Application scope

I hope it will help you to solve your problem. Thanks

SinaDBMS commented 7 years ago

image

I use EJB session beans. As in the image, i intend to initialize my Bots in a singelton sessino bean, like a Main thread in a standard java application. Do you think it's a good approach? shoud i continue this way in order to deploy my bot on a remote server(i'm using openshift as webserver)? Any ideas or suggestions would be appreciated!

hechteka commented 6 years ago

Hi elettrico

you posted a solution on commented on Apr 20, 2016. However this is very unclear. Can you please upload the sample to your GitHub repository?

gigaclood commented 4 years ago

Is it now possible to use this library in a J2EE container like Jboss, WildFly or Tomcat ? I'm asking because I see this issue as closed

Thank you