./mvnw spring-boot:build-image with default setup creates runtime image with encoding that is not utf-8. Java has default utf-8 encoding. e.g. reading env. variable with non ascii characters creates invalid String with question marks. As a workaround I set runtime image env. variable:
<configuration>
<image>
<env>
<!-- set UTF-8 encoding for runtime image -->
<BPE_LANG>C.UTF-8</BPE_LANG>
</env>
</image>
</configuration>
I believe the image should use by default same setup as java, which is utf-8
Comment From: wilkinsona
Java has default utf-8 encoding.
Only since Java 18 (JEP 400). Which version of Java are you using?
Comment From: michalgebauer
Right, I use java 21. So if you'll find my request valid, then proper logic should be to set utf-8 for java 18 and higher.
Comment From: wilkinsona
Thanks.
I don't think this is a problem with the JVM's encoding as it's UTF-8 when running a Paketo-generated image:
docker run docker.io/library/gh-43663:0.0.1-SNAPSHOT
Calculating JVM memory based on 6674064K available memory
For more information on this calculation, see https://paketo.io/docs/reference/java-reference/#memory-calculator
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx6082201K -XX:MaxMetaspaceSize=79862K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 6674064K, Thread Count: 250, Loaded Class Count: 11686, Headroom: 0%)
Enabling Java Native Memory Tracking
Adding 146 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -XX:+ExitOnOutOfMemoryError -XX:MaxDirectMemorySize=10M -Xmx6082201K -XX:MaxMetaspaceSize=79862K -XX:ReservedCodeCacheSize=240M -Xss1M -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -Dorg.springframework.cloud.bindings.boot.enable=true
UTF-8
UTF-8
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.4.1)
2025-01-06T09:29:56.181Z INFO 1 --- [gh-43663] [ main] c.example.gh_43663.Gh43663Application : Starting Gh43663Application v0.0.1-SNAPSHOT using Java 21.0.5 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2025-01-06T09:29:56.185Z INFO 1 --- [gh-43663] [ main] c.example.gh_43663.Gh43663Application : No active profile set, falling back to 1 default profile: "default"
2025-01-06T09:29:57.004Z INFO 1 --- [gh-43663] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
2025-01-06T09:29:57.020Z INFO 1 --- [gh-43663] [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2025-01-06T09:29:57.021Z INFO 1 --- [gh-43663] [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.34]
2025-01-06T09:29:57.060Z INFO 1 --- [gh-43663] [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2025-01-06T09:29:57.062Z INFO 1 --- [gh-43663] [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 821 ms
2025-01-06T09:29:57.398Z INFO 1 --- [gh-43663] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
2025-01-06T09:29:57.413Z INFO 1 --- [gh-43663] [ main] c.example.gh_43663.Gh43663Application : Started Gh43663Application in 1.685 seconds (process running for 2.164)
Note that UTF-8 that is output twice before the banner. This is the file.encoding and default charset of the JVM. The output above was produced by an application with the following main class:
package com.example.gh_43663;
import java.nio.charset.Charset;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Gh43663Application {
public static void main(String[] args) {
System.out.println(System.getProperty("file.encoding"));
System.out.println(Charset.defaultCharset());
SpringApplication.run(Gh43663Application.class, args);
}
}
However, I do see a problem when trying to pass in an environment variable with non-ASCII characters in its value. This affects both pack and Spring Boot's image building support so I don't think it's a Boot-specific problem.
Building a container with pack using paketobuildpacks/builder-jammy-base and running it with a problematic environment variable shows that the variable is set correctly in the container:
$ docker run -e NON_ASCII_ENV_VAR_TEST=åüéç -it --entrypoint /bin/bash gh-43663
cnb@efa876252910:/workspace$ printenv NON_ASCII_ENV_VAR_TEST
åüéç
Running the entrypoint, however, then shows that the value has been corrupted if the app dumps out System.getenv():
cnb@efa876252910:/workspace$ /cnb/process/web
…
NON_ASCII_ENV_VAR_TEST=????????
This will have to be addressed on the buildpacks side. I'd recommend starting by discussing the problem with the community, probably in their Slack workspace.
Comment From: michalgebauer
Thanks, that's exactly the problem I was pointing out. I will to address this on the buildpacks side.