使用Simple-Java-Mail构建Quarkus原生镜像时遇StreamProvider缺失异常
解决Quarkus + simple-java-mail原生镜像下StreamProvider找不到的问题
问题根源
GraalVM原生镜像采用AOT静态编译,不会自动扫描META-INF/services下的SPI(服务提供者接口)文件,而Jakarta Mail的StreamProvider依赖SPI机制加载实现类,这就是开发模式正常、原生镜像运行失败的核心原因。
分步解决方案
1. 调整依赖,使用适配Quarkus的Jakarta Mail实现
simple-java-mail默认依赖com.sun.mail:jakarta.mail,替换为Quarkus推荐的angus-mail,同时排除旧依赖避免冲突:
<dependencies> <dependency> <groupId>org.simplejavamail</groupId> <artifactId>simple-java-mail</artifactId> <version>8.12.4</version> <exclusions> <exclusion> <groupId>com.sun.mail</groupId> <artifactId>jakarta.mail</artifactId> </exclusion> <exclusion> <groupId>com.sun.mail</groupId> <artifactId>jakarta.activation</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.eclipse.angus</groupId> <artifactId>angus-mail</artifactId> <version>2.0.3</version> </dependency> <dependency> <groupId>org.eclipse.angus</groupId> <artifactId>angus-activation</artifactId> <version>2.0.3</version> </dependency> </dependencies>
2. 显式注册StreamProvider的SPI实现
在src/main/resources/META-INF/services目录下创建文件jakarta.mail.util.StreamProvider,写入angus的实现类全限定名:
org.eclipse.angus.mail.util.StreamProviderImpl
这会告诉GraalVM原生镜像编译时要包含这个实现类。
3. 开启原生镜像的安全服务支持
邮件发送依赖SSL等安全服务,原生镜像默认未完全开启,在application.properties中添加:
quarkus.native.additional-build-args=--enable-all-security-services
4. 添加反射配置(可选,若上述步骤仍未解决)
创建src/main/resources/META-INF/native-image/reflect-config.json,添加必要类的反射规则:
[ { "name": "org.eclipse.angus.mail.util.StreamProviderImpl", "allDeclaredConstructors": true, "allPublicConstructors": true, "allDeclaredMethods": true, "allPublicMethods": true }, { "name": "jakarta.mail.Session", "allDeclaredConstructors": true, "allPublicConstructors": true, "allDeclaredMethods": true, "allPublicMethods": true } ]
验证
重新构建原生镜像:
./mvnw package -Dnative
运行生成的镜像文件,检查邮件发送是否正常。
内容的提问来源于stack exchange,提问作者Minh Long Vu
相关产品推荐
相关产品推荐

