0

i'm developing/running a SpringBoot App on Kubernetes 1.24, which i'm also using to learn several techniques with mostly using WebClient and with my newest attempt, also sending E-Mails with JavaMailSender etc.

Lately i was updating a few parts in my code, where i'm not sure anymore what was leading to the issue in the subject.

But i suspect it could have something to do with adding a new @Component for my EmailSender class or that i had to use @ComponentScan to access the mail package, as it was outside of my controller class package.

As e.g.:

[...]
@Configuration
public class EmailConfiguration {
    @Bean
    public JavaMailSender getJavaMailSender() {
           [...]
        }
}

and also:

@Component
public class EmailSender {
    @Autowired
    private JavaMailSender emailSender;
    @Bean
    public void sendSimpleMessage(String to, String subject, String text) {
       [...]
    }
}

Also i've updated from Eclipse Temurin 17.0.6+10 to 17.0.7+7

To get more details, i've added the following to the application.properties:

management.server.port=8081
management.server.address=0.0.0.0
management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.endpoint.health.probes.enabled=true
management.health.livenessState.enabled=true
management.health.readinessState.enabled=true
management.endpoint.health.show-details=always
management.endpoints.web.base-path=/actuator

So i've got the following response calling http://localhost:8081/actuator/health:

{
  "status": "DOWN",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "H2",
        "validationQuery": "isValid()"
      }
    },
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 1022565265408,
        "free": 861403496448,
        "threshold": 10485760,
        "path": "C:\\Users\\nick\\eclipse-workspace\\demoapp\\.",
        "exists": true
      }
    },
    "livenessState": {
      "status": "DOWN"
    },
    "ping": {
      "status": "UP"
    },
    "readinessState": {
      "status": "OUT_OF_SERVICE"
    }
  },
  "groups": [
    "liveness",
    "readiness"
  ]
}

My pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.6</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>my.demo.springboot</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Demo SpringBoot</name>
    <description>Demo Spring Boot Example</description>

    <properties>
        <java.version>17</java.version>
        <log4j2.version>2.20.0</log4j2.version>
        <netty.version>4.1.92.Final</netty.version>
        <snakeyaml.version>2.0</snakeyaml.version>
    </properties>

    <dependencies>
    
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>
        
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <scope>runtime</scope>
    </dependency>


        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
            <scope>runtime</scope>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.11.5</version>
        </dependency>
    
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.11.5</version>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.11.5</version>
        </dependency>
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>4.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.ocpsoft.prettytime</groupId>
            <artifactId>prettytime</artifactId>
            <version>5.0.6.Final</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

I was reading on the following at the official documentation:

Tasks expected to run during startup should be executed by CommandLineRunner and ApplicationRunner components instead of using Spring component lifecycle callbacks such as @PostConstruct.

But i did not modified any behavior on such, so i'm currently not sure where and what to look for.

As i'm running on kubernetes, i'm using both endpoints to monitor my application, but now it keeps restarting as a both healthchecks fail with 503.

I'm hoping that it is just something simple i've forgot/changed and anyone knows or had that issue already.

Let me know if anyhow more information is required.

Thanks!

Update:

This only happens with Spring Boot 3.0.6, with 3.0.5 everything running fine with:

{
  "status": "UP",
  "components": {
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 1022565265408,
        "free": 863173750784,
        "threshold": 10485760,
        "path": "C:\\<censored>\\.",
        "exists": true
      }
    },
    "livenessState": {
      "status": "UP"
    },
    "mail": {
      "status": "UP",
      "details": {
        "location": "<censored>.net:25"
      }
    },
    "ping": {
      "status": "UP"
    },
    "readinessState": {
      "status": "UP"
    }
  },
  "groups": [
    "liveness",
    "readiness"
  ]
}

This issue on GitHub might be related.

theraven
  • 21
  • 7
  • Why the email configuration as Spring Boot will add auto configuration for it. Also you shouldn't need the compont-scan as your `@SpringBootApplication` annotated class should be in a top level package. – M. Deinum May 10 '23 at 11:23
  • @M. Deinum i had to do this because my SpringBootApplication annotated class is outside of the package and couldn't be found otherwise. E.g.: (SpringBootApplication) my.demo.springboot.application.StartUpApplication.java (My E-Mail package) my.demo.springboot.bo.email.EmailConfiguration.java my.demo.springboot.bo.email.EmailSender.java – theraven May 10 '23 at 11:40
  • That really shouldn't matter in this case, but as stated you don't really need the `EmailConfiguration`. In fact it actually influence auto configuration for the mail stuff (even the actuator part). So I suggest ditch that and instead specify the `spring.mail` properties instead, Spring Boot will now create and manage the mailsender for you (and include a check as well for actuator). – M. Deinum May 10 '23 at 11:42
  • @M.Deinum thanks! To be honest i was actually confused because of this, as i saw it on several "googles" :-) Because i was configuring it twice, in my application.properties the way you just mentioned, and inside that EmailConfiguration class. Now i've commented out my configuration class to only use the properties and i can see a new field mail with the status UP at the actuatur path. But so far it still returns me the 503 with livenessState DOWN and readinessState OUT_OF_SERVICE. – theraven May 10 '23 at 11:49
  • At least some progress. One thing I notice is the uppercase `S` in your property names, those don't really match the ones in the documentation try with a lowercase `s` instead. – M. Deinum May 10 '23 at 12:41
  • @M.Deinum originally i've found that on here: https://www.baeldung.com/spring-liveness-readiness-probes#actuator-probes but changing it also did not had any effect. It's confusing why it is marked as down even if my app is running perfectly fine. – theraven May 11 '23 at 04:42
  • Do you execute some long running tasks with a `CommandLineRunner` or `ApplicationRunner`? You can enable DEBUG or TRACE logging (which will flood your console) to see what is going on. One thing that might influence things is that you have both `spring-boot-starter-web` and `spring-boot-starter-webflux` as a dependency and it doesn't know which to use. Have you explicitly configured which runtime (servlet or reactive) to use? – M. Deinum May 11 '23 at 05:24
  • @M.Deinum no, i'm not using any Runners that are e.g. scheduled. But i'm explicitly using parts of jakarta.servlet.* (which is in web) and also webflux (needed for webclient) I do have activated TRACE logging as such: logging.level.root=TRACE logging.level.org.springframework=TRACE logging.level.org.apache.tomcat=TRACE logging.level.org.apache.catalina=TRACE and now it is actually getting flooded, but so far i couldn't find anything that leads me to a hint. I mostly see messages coming from: org.apache.tomcat.util.net.NioEndpoint Is there something special i have to look for? – theraven May 11 '23 at 08:03
  • But have you instructed Spring to use SERVLET explicitly instead of Reactive? As you have both you have to explicitly specify which to use. See https://stackoverflow.com/questions/51377675/dont-spring-boot-starter-web-and-spring-boot-starter-webflux-work-together on how to do that. Or add `spring.main.web-application-type` and set it to `SERVLET`. – M. Deinum May 11 '23 at 08:06
  • A sorry, no i never did that as it was working fine without. But now, also by adding it as property e.g. spring.main.web-application-type=servlet/reactive or in my main method is still returning the same error. – theraven May 11 '23 at 08:25
  • Then I yield, with the little information you provided this will be impossible to answer. – M. Deinum May 11 '23 at 08:53
  • @M.Deinum thank you for support anyway! I still suppose it has to be a tiny thing somewhere :-) – theraven May 11 '23 at 08:56
  • Probably but with the config shown here that would be impossible to answer. Generally when discovered it is one of those facepalm moments (which I had plenty of in my 25 year career :) ). – M. Deinum May 11 '23 at 09:08
  • @M.Deinum fyi: I was cleaning and clearing my whole code and at some step i figured out that: When i'm changing the version to Spring Boot 3.0.5, both livenessState and readinessState is UP and everything is running perfectly fine. Changing to version to 3.0.6 you see the above result where everything is down. That means the error/issue must be somewhere in the newest version or there was something new/different implemented i didn't see so far. – theraven May 17 '23 at 12:19

1 Answers1

0

Issue is related with GitHub issue 35161. With a fix and its description as:

Liveness and readiness probes return down when lazy initialization is enabled

Updating to Spring Boot Version 3.1.0 solved it for me (also 3.0.7 should have the fix, but untested from my side) and the health endpoint is up again (3.1.0 just has been published 3 days ago).

Details:

This is a regression caused by the changes for #34347. The return type of the @Bean method has changed from ApplicationAvailabilityBean to ApplicationAvailability. This means that type information is lost and the bean factory cannot tell that it's an ApplicationListener.

{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "H2",
        "validationQuery": "isValid()"
      }
    },
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 1022565265408,
        "free": 862148792320,
        "threshold": 10485760,
        "path": "C:\\<censored>\\eclipse-workspace\\demo\\.",
        "exists": true
      }
    },
    "livenessState": {
      "status": "UP"
    },
    "ping": {
      "status": "UP"
    },
    "readinessState": {
      "status": "UP"
    }
  },
  "groups": [
    "liveness",
    "readiness"
  ]
}
theraven
  • 21
  • 7