Micronaut 和 Java 邮件 API
Micronaut and Java Mail API
我们正在尝试将单体应用程序的一部分迁移到微服务,因此我们决定使用 micronaut。我们现在正在提取一个电子邮件服务,它提供一些输入将呈现电子邮件并与 SMTP 服务器交谈以发送它们。
为此,我们使用 Java 邮件,当我们尝试创建 GraalVM docker 图像时,它似乎有一些问题。有没有人设法做到这一点,或者根本不可能让它发挥作用?
一些附加信息:
Dockerfile:
FROM oracle/graalvm-ce:19.2.0 as graalvm
COPY . /home/app/email-service
WORKDIR /home/app/email-service
RUN gu install native-image
RUN native-image --no-server -cp build/libs/email-service-*.jar
FROM frolvlad/alpine-glibc
EXPOSE 8080
COPY --from=graalvm /home/app/email-service .
ENTRYPOINT ["./email-service"]
原生-image.properties:
"lazy" 驱动程序、redis、kafka 和 thymeleaf 的一些其他 "lazy" 初始化已经到位。
Args = --initialize-at-run-time=io.micronaut.views.thymeleaf.ThymeleafFactory \
--initialize-at-run-time=io.micronaut.views.thymeleaf.ThymeleafViewsRenderer \
--initialize-at-run-time=io.micronaut.views.velocity.VelocityViewsRenderer \
--initialize-at-run-time=io.micronaut.configuration.lettuce.session.$RedisHttpSessionConfigurationDefinition \
--initialize-at-run-time=io.micronaut.configuration.kafka.embedded.KafkaEmbedded \
--initialize-at-run-time=oracle.jdbc.driver.OracleDriver \
--initialize-at-run-time=java.sql.DriverManager \
--initialize-at-run-time=org.hibernate.jpa.HibernatePersistenceProvider \
--initialize-at-run-time=com.sun.mail.util.MailLogger \
-H:IncludeResources=logback.xml|application.yml \
-H:Name=email-service \
-H:Class=com.acme.MySuperDuperApplication
Micronaut 版本: 1.2.0
Java 邮件版本: 1.6.2 (com.sun.mail:javax.mail:1.6.2
)
本机图像编译错误:
Warning: Aborting stand-alone image build. com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of com.sun.mail.util.MailLogger are allowed in the image heap as this class should be initialized at image runtime. To see how this object got instantiated use -H:+TraceClassInitialization.
Detailed message:
Trace:
at parsing javax.mail.internet.MailDateFormat.access[=14=]0(MailDateFormat.java:149)
Call path from entry point to javax.mail.internet.MailDateFormat.access[=14=]0():
at javax.mail.internet.MailDateFormat.access[=14=]0(MailDateFormat.java:149)
at javax.mail.internet.MailDateFormat$AbstractDateParser.parse(MailDateFormat.java:426)
at javax.mail.internet.MailDateFormat.parse(MailDateFormat.java:251)
at java.text.DateFormat.parse(DateFormat.java:364)
at freemarker.core.JavaTemplateDateFormat.parse(JavaTemplateDateFormat.java:49)
at freemarker.core.JavaTemplateDateFormat.parse(JavaTemplateDateFormat.java:33)
at freemarker.core.BuiltInsForMultipleTypes$dateBI$DateParser.parse(BuiltInsForMultipleTypes.java:204)
at freemarker.core.BuiltInsForMultipleTypes$dateBI$DateParser.get(BuiltInsForMultipleTypes.java:167)
at freemarker.ext.beans.HashAdapter.get(HashAdapter.java:73)
at freemarker.ext.beans.HashAdapter.getValue(HashAdapter.java:124)
at sun.security.ssl.SSLSocketImpl$NotifyHandshakeThread.run(SSLSocketImpl.java:2687)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:460)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8337338252cd8734f63a79b5e3df(generated:0)
不确定这是否足够,但您可以尝试在构建时初始化 com.sun.mail.util.MailLogger
--initialize-at-build-time=com.sun.mail.util.MailLogger
作为参数
这将在运行前预加载class,这可能解决或不解决编译问题
附带说明一下,我想您可以将运行时初始化参数链接到一个逗号分隔的列表中,即
--initialize-at-runtime=io.micronaut.views.thymeleaf.ThymeleafFactory,io.micronaut.views.thymeleaf.ThumeleafViewsRenderer, ...
在尝试了一些不同的东西之后,我发布了最终对我们有用的东西,这样其他人可能会得到帮助。
首先我们升级到最新版本的micronaut(目前2.3.4
),同时我们使用了最新版本的com.sun.mail:jakarta.mail
(目前2.0.0
)。
其次,我们的 nativeImage args 如下(省略了一些其他依赖项):
--report-unsupported-elements-at-runtime
-H:+ReportExceptionStackTraces
-H:-DeleteLocalSymbols
-H:+PreserveFramePointer
-H:IncludeResources=META-INF/mailcap
-H:IncludeResources=META-INF/mailcap.default
-H:IncludeResources=META-INF/javamail.default.address.map
-H:IncludeResources=META-INF/javamail.charset.map
-H:IncludeResources=META-INF/javamail.default.providers
-H:IncludeResources=META-INF/services/javax.mail.Provider
然后我们不得不标记一些 类 用于自省使用 @TypeHint
:
@TypeHit({
SMTPTransport.class,
MimeMultipart.class,
MailcapCommandMap.class,
text_html.class,
multipart_mixed.class,
handler_base.class,
image_gif.class,
image_jpeg.class,
message_rfc822.class,
text_xml.class,
text_plain.class
})
最后,我们有一个 SMTP Sender bean,我们必须在其上配置 mailcap(因此资源包含可能效果不佳):
@PostConstruct
public void initialize() {
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mc);
}
有了所有这些,我们就能够创建一个可以毫无问题地发送电子邮件的原生图像。
我们正在尝试将单体应用程序的一部分迁移到微服务,因此我们决定使用 micronaut。我们现在正在提取一个电子邮件服务,它提供一些输入将呈现电子邮件并与 SMTP 服务器交谈以发送它们。
为此,我们使用 Java 邮件,当我们尝试创建 GraalVM docker 图像时,它似乎有一些问题。有没有人设法做到这一点,或者根本不可能让它发挥作用?
一些附加信息:
Dockerfile:
FROM oracle/graalvm-ce:19.2.0 as graalvm
COPY . /home/app/email-service
WORKDIR /home/app/email-service
RUN gu install native-image
RUN native-image --no-server -cp build/libs/email-service-*.jar
FROM frolvlad/alpine-glibc
EXPOSE 8080
COPY --from=graalvm /home/app/email-service .
ENTRYPOINT ["./email-service"]
原生-image.properties:
"lazy" 驱动程序、redis、kafka 和 thymeleaf 的一些其他 "lazy" 初始化已经到位。
Args = --initialize-at-run-time=io.micronaut.views.thymeleaf.ThymeleafFactory \
--initialize-at-run-time=io.micronaut.views.thymeleaf.ThymeleafViewsRenderer \
--initialize-at-run-time=io.micronaut.views.velocity.VelocityViewsRenderer \
--initialize-at-run-time=io.micronaut.configuration.lettuce.session.$RedisHttpSessionConfigurationDefinition \
--initialize-at-run-time=io.micronaut.configuration.kafka.embedded.KafkaEmbedded \
--initialize-at-run-time=oracle.jdbc.driver.OracleDriver \
--initialize-at-run-time=java.sql.DriverManager \
--initialize-at-run-time=org.hibernate.jpa.HibernatePersistenceProvider \
--initialize-at-run-time=com.sun.mail.util.MailLogger \
-H:IncludeResources=logback.xml|application.yml \
-H:Name=email-service \
-H:Class=com.acme.MySuperDuperApplication
Micronaut 版本: 1.2.0
Java 邮件版本: 1.6.2 (com.sun.mail:javax.mail:1.6.2
)
本机图像编译错误:
Warning: Aborting stand-alone image build. com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of com.sun.mail.util.MailLogger are allowed in the image heap as this class should be initialized at image runtime. To see how this object got instantiated use -H:+TraceClassInitialization.
Detailed message:
Trace:
at parsing javax.mail.internet.MailDateFormat.access[=14=]0(MailDateFormat.java:149)
Call path from entry point to javax.mail.internet.MailDateFormat.access[=14=]0():
at javax.mail.internet.MailDateFormat.access[=14=]0(MailDateFormat.java:149)
at javax.mail.internet.MailDateFormat$AbstractDateParser.parse(MailDateFormat.java:426)
at javax.mail.internet.MailDateFormat.parse(MailDateFormat.java:251)
at java.text.DateFormat.parse(DateFormat.java:364)
at freemarker.core.JavaTemplateDateFormat.parse(JavaTemplateDateFormat.java:49)
at freemarker.core.JavaTemplateDateFormat.parse(JavaTemplateDateFormat.java:33)
at freemarker.core.BuiltInsForMultipleTypes$dateBI$DateParser.parse(BuiltInsForMultipleTypes.java:204)
at freemarker.core.BuiltInsForMultipleTypes$dateBI$DateParser.get(BuiltInsForMultipleTypes.java:167)
at freemarker.ext.beans.HashAdapter.get(HashAdapter.java:73)
at freemarker.ext.beans.HashAdapter.getValue(HashAdapter.java:124)
at sun.security.ssl.SSLSocketImpl$NotifyHandshakeThread.run(SSLSocketImpl.java:2687)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:460)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8337338252cd8734f63a79b5e3df(generated:0)
不确定这是否足够,但您可以尝试在构建时初始化 com.sun.mail.util.MailLogger
--initialize-at-build-time=com.sun.mail.util.MailLogger
作为参数
这将在运行前预加载class,这可能解决或不解决编译问题
附带说明一下,我想您可以将运行时初始化参数链接到一个逗号分隔的列表中,即
--initialize-at-runtime=io.micronaut.views.thymeleaf.ThymeleafFactory,io.micronaut.views.thymeleaf.ThumeleafViewsRenderer, ...
在尝试了一些不同的东西之后,我发布了最终对我们有用的东西,这样其他人可能会得到帮助。
首先我们升级到最新版本的micronaut(目前2.3.4
),同时我们使用了最新版本的com.sun.mail:jakarta.mail
(目前2.0.0
)。
其次,我们的 nativeImage args 如下(省略了一些其他依赖项):
--report-unsupported-elements-at-runtime
-H:+ReportExceptionStackTraces
-H:-DeleteLocalSymbols
-H:+PreserveFramePointer
-H:IncludeResources=META-INF/mailcap
-H:IncludeResources=META-INF/mailcap.default
-H:IncludeResources=META-INF/javamail.default.address.map
-H:IncludeResources=META-INF/javamail.charset.map
-H:IncludeResources=META-INF/javamail.default.providers
-H:IncludeResources=META-INF/services/javax.mail.Provider
然后我们不得不标记一些 类 用于自省使用 @TypeHint
:
@TypeHit({
SMTPTransport.class,
MimeMultipart.class,
MailcapCommandMap.class,
text_html.class,
multipart_mixed.class,
handler_base.class,
image_gif.class,
image_jpeg.class,
message_rfc822.class,
text_xml.class,
text_plain.class
})
最后,我们有一个 SMTP Sender bean,我们必须在其上配置 mailcap(因此资源包含可能效果不佳):
@PostConstruct
public void initialize() {
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mc);
}
有了所有这些,我们就能够创建一个可以毫无问题地发送电子邮件的原生图像。