MySQL 连接器不适用于 GraalVM 和 Docker

问题描述 投票:0回答:1

我正在尝试使用 JDBC 和 mysql-connector-java 在带有 Graalvm 的图像上执行基本的 SQL 查询(问题的原因)。

显然每个尝试将 GraalVM 与 JDBC/MySQL 和 Docker 结合使用的人每次都会遇到同样的问题。

我遇到以下异常

Exception in thread "main" java.lang.ExceptionInInitializerError
   at com.mysql.cj.Constants.<clinit>(Constants.java:49)
   at com.mysql.cj.util.Util.<clinit>(Util.java:67)
   at com.mysql.cj.conf.ConnectionUrl$Type.getImplementingInstance(ConnectionUrl.java:241)
   at com.mysql.cj.conf.ConnectionUrl$Type.getConnectionUrlInstance(ConnectionUrl.java:211)
   at com.mysql.cj.conf.ConnectionUrl.getConnectionUrlInstance(ConnectionUrl.java:280)
   at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:195)
   at java.sql.DriverManager.getConnection(DriverManager.java:681)
   at java.sql.DriverManager.getConnection(DriverManager.java:229)
   at com.me.test.Main.testJDBC(Main.java:73)
   at com.me.test.Main.main(Main.java:94)
Caused by: java.lang.RuntimeException: Can't load resource bundle due to underlying     exception java.util.MissingResourceException: Can't find bundle for base name com.mysql.cj.LocalizedErrorMessages, locale en_US
   at com.mysql.cj.Messages.<clinit>(Messages.java:60)
... 10 more
Caused by: java.util.MissingResourceException: Can't find bundle for base name com.mysql.cj.LocalizedErrorMessages, locale en_US
   at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:2045)
   at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1683)
   at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1586)
   at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1549)
   at java.util.ResourceBundle.getBundle(ResourceBundle.java:858)
   at com.mysql.cj.Messages.<clinit>(Messages.java:58)
... 10 more

我的 Dockerfile

FROM ghcr.io/graalvm/graalvm-ce:latest

RUN gu install native-image
WORKDIR /tmp/dist
ADD ./app.jar ./app.jar

COPY ./reflect-config.json ./reflect-config.json

RUN native-image -jar ./app.jar --verbose --no-fallback
RUN  microdnf install zip

ADD bootstrap bootstrap

RUN chmod +x bootstrap
RUN chmod +x ./app

RUN zip -j function.zip bootstrap app


ENTRYPOINT ["./app"]

我的 pom 文件中的依赖项

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.29</version>
</dependency>
<dependency>
  <groupId>com.oracle.database.jdbc</groupId>
  <artifactId>ojdbc8</artifactId>
  <version>21.5.0.0</version>
</dependency>

最后是我的java代码:

public void testJDBC() throws SQLException, IOException {
    String url = "jdbc:mysql://foo.blabla.aws-region.rds.amazonaws.com:3306/database";
    String user = "root";
    String password = "password";
    try(java.sql.Connection conn = java.sql.DriverManager.getConnection(url, user, password)){
        doSomething(conn);
    }
}

编辑1:

我遵循了 Mark Rotteveel 的建议,并添加了一个 “resource-config.json” 文件,其中包含以下内容:

{
  "resources": {
    "includes": [
      {"pattern": "com.mysql.cj.LocalizedErrorMessages.properties"}
    ]
  }
}

并在“native-image.properties”文件中添加以下内容

Args = -H:EnableURLProtocols=http,https -H:ReflectionConfigurationFiles=/tmp/dist/reflect-config.json -H:ResourceConfigurationFiles=/tmp/dist/resource-config.json
修复了当前错误,但正如预期的那样,我们有了一个新错误:

Exception in thread "main" java.lang.ClassCastException: com.mysql.cj.exceptions.CJException cannot be cast to com.mysql.cj.exceptions.WrongArgumentException at com.mysql.cj.util.Util.getInstance(Util.java:169) at com.mysql.cj.util.Util.getInstance(Util.java:174) at com.mysql.cj.conf.ConnectionUrl$Type.getImplementingInstance(ConnectionUrl.java:241) at com.mysql.cj.conf.ConnectionUrl$Type.getConnectionUrlInstance(ConnectionUrl.java:211) at com.mysql.cj.conf.ConnectionUrl.getConnectionUrlInstance(ConnectionUrl.java:280) at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:195) at java.sql.DriverManager.getConnection(DriverManager.java:681) at java.sql.DriverManager.getConnection(DriverManager.java:229) at com.me.test.Main.testJDBC(Main.java:77) at com.me.test.Main.main(Main.java:98)

编辑2:

我在文件

“reflect-config.json”中配置了以下内容

[ { "name": "com.mysql.cj.conf.url.SingleConnectionUrl", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.conf.url.FailoverDnsSrvConnectionUrl", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.conf.url.LoadBalanceDnsSrvConnectionUrl", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.conf.url.ReplicationDnsSrvConnectionUrl", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.conf.url.XDevApiDnsSrvConnectionUrl", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.conf.url.FailoverConnectionUrl", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.conf.url.LoadBalanceConnectionUrl", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.conf.url.ReplicationConnectionUrl", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.conf.url.XDevApiConnectionUrl", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.log.Jdk14Logger", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.log.NullLogger", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.log.Slf4JLogger", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.cj.log.StandardLogger", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name": "com.mysql.jdbc.Driver", "allDeclaredFields": true, "allDeclaredMethods": true, "allDeclaredConstructors": true }, { "name":"oracle.jdbc.OracleDriver", "methods":[{"name":"<init>","parameterTypes":[] }] }, { "name":"oracle.jdbc.driver.T4CDriverExtension", "methods":[{"name":"<init>","parameterTypes":[] }] }, { "name" : "oracle.jdbc.driver.T2CDriverExtension", "methods":[{"name":"<init>","parameterTypes":[] }] }, { "name":"oracle.net.ano.Ano", "methods":[{"name":"<init>","parameterTypes":[] }] }, { "name":"oracle.net.ano.AuthenticationService", "methods":[{"name":"<init>","parameterTypes":[] }] }, { "name":"oracle.net.ano.DataIntegrityService", "methods":[{"name":"<init>","parameterTypes":[] }] }, { "name":"oracle.net.ano.EncryptionService", "methods":[{"name":"<init>","parameterTypes":[] }] }, { "name":"oracle.net.ano.SupervisorService", "methods":[{"name":"<init>","parameterTypes":[] }] } ]
但由于某种原因出现连接错误(使用 AWS RDS 和 host.docker.internal 进行测试)。

Exception in thread "main" java.sql.SQLNonTransientConnectionException: Cannot connect to MySQL server on foo.blabla.aws-region.rds.amazonaws.com:3,306. Make sure that there is a MySQL server running on the machine/port you are trying to connect to and that the machine this software is running on is able to connect to this host/port (i.e. not firewalled). Also make sure that the server has not been started with the --skip-networking flag. at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73) at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:462) at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) at java.sql.DriverManager.getConnection(DriverManager.java:681) at java.sql.DriverManager.getConnection(DriverManager.java:229) at com.me.test.Main.testJDBC(Main.java:104) at com.me.test.Main.main(Main.java:125) Caused by: java.lang.ClassCastException: com.mysql.cj.exceptions.CJException cannot be cast to com.mysql.cj.exceptions.UnableToConnectException at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:825) at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:448) ... 6 more
此错误仅在使用 

“ghcr.io/graalvm/graalvm-ce:latest” 时发生,如果我使用其他虚拟机,例如 “amazoncorretto:18-alpine” 一切都很完美。

完整源代码:

https://github.com/ederbaum/MySQLGraalVM

有什么可行的解决办法吗?

java docker jdbc mysql-connector graalvm
1个回答
0
投票
这两个链接可以解决您的问题。

https://www.graalvm.org/native-image/libraries-and-frameworks/

https://github.com/oracle/graalvm-reachability-metadata/tree/master/metadata/mysql/mysql-connector-java/8.0.29

© www.soinside.com 2019 - 2024. All rights reserved.