Search code examples
spring-bootscheduled-tasksgoogle-kubernetes-enginecron-task

Spring boot @Scheduler not working in Google Kubernetes Engine


I have a Spring boot application which consists of a scheduled task and a rest controller. The scheduled task connects to Gmail with Javamail to parse certain emails and store them in a MongoDB database and the controller is to query that data in the databse. I am deploying this application in GKE. When I do, I see the following log messages and my task does not run:

enter image description here

The controller is accessible but as you can see the application starts but then the taskScheduler executor service shuts down. I can't find information in the logs about why this is happening. When I run it locally it works, so I thought it could be related to Docker, but I ran the application from a Docker container (also locally) and it worked as well. I have another spring boot application that runs some scheduled tasks deployed on GKE and working the only difference is that it does not expose any rest controllers.

Do you have any idea what might be the cause of this issue?

Here's my main class

@EnableScheduling
@EnableMongoRepositories
@SpringBootApplication
public class EmailApplication {
    public static void main(String[] args) {
        SpringApplication.run(EmailCheckerApplication.class, args);
    }
}

Here's my scheduled task. This does not run at all.

@Scheduled(fixedDelay = 60000) // I also tried with @Scheduled(cron = "0 */1 * * * *")
public void checkEmails() {
    try {
        //connects to Gmail
        Message[] messages = getMessages();
        //parse emails & store them in DB
        closeAll();
    } catch (Exception e) {
        LOGGER.finest("Error Parsing emails: " + e.getMessage());
    }
}

Here's my Dockerfile

FROM adoptopenjdk/openjdk13:jre-13.0.2_8-alpine

COPY build/libs/email-checker-0.0.1.jar /tmp
RUN chmod 744 /tmp/email-checker-0.0.1.jar
CMD ["java", "-jar", "-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE}", "/tmp/email-checker-0.0.1.jar"]

Here's my dependencies in build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation group: 'javax.mail', name: 'mail', version: '1.4.7'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '2.4.2'
    compile group: 'org.springframework.data', name: 'spring-data-mongodb', version: '3.1.3'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-mongodb', version: '2.4.2'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

Edit

Weird, if I run kubectl logs -n service <pod-name> -f I don't see the log messages of the ExecutorServices shutting down, but I don't see the log messages of the scheduled task either.

Here's the last log messages enter image description here


Solution

  • I solved the issue. Actually there were two issues, but the main one is that when my application was trying to connect to Gmail, it was throwing an exception saying that Web login was required. So I realized that Spring boot was ignoring LOGGER.finest in my catch block. I was able to spot that first by adding a bunch of LOGGER.info before every single line of code in my scheduled task and then changing LOGGER.finest to LOGGER.info.

    So to solve the main issue I followed some suggestions in this SO question and to solve the issue with LOGGER.finest I added the property logging.level.my-package=DEBUG in my application.properties (change my-package to a package in your application you want to set the log level to). If you have different profiles for lower environments and production, you can set it to ERROR in the production profile.