Issue
We have configured email delivery using the application server JNDI mail resource, adding the following property to the portal-ext.properties file
mail.session.jndi.name=mail/Session
We followed this Liferay documentation to configure it:
When we try to send an email we are getting the following exception:
2023-03-14 16:03:14.394 ERROR [liferay/mail-2][InfrastructureUtil:90] Unable to lookupmail/Session
java.lang.ClassCastException: class javax.mail.Session cannot be cast to class javax.mail.Session (javax.mail.Session is in unnamed module of loader 'javax.mail.api@1.6.5.redhat-00001' @35cb51f9; javax.mail.Session is in unnamed module of loader com.liferay.shielded.container.internal.ShieldedContainerClassLoader @345def0f)
at com.liferay.portal.kernel.util.InfrastructureUtil._createMailSession(InfrastructureUtil.java:87) [portal-kernel.jar:?]
at com.liferay.portal.kernel.util.InfrastructureUtil.getMailSession(InfrastructureUtil.java:51) [portal-kernel.jar:?]
at com.liferay.mail.service.impl.MailServiceImpl.getSession(MailServiceImpl.java:193) [portal-impl.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
at com.liferay.portal.spring.aop.AopMethodInvocationImpl.proceed(AopMethodInvocationImpl.java:50) [portal-impl.jar:?]
at com.liferay.portal.spring.transaction.TransactionInterceptor.invoke(TransactionInterceptor.java:69) [portal-impl.jar:?]
at com.liferay.portal.spring.aop.AopMethodInvocationImpl.proceed(AopMethodInvocationImpl.java:57) [portal-impl.jar:?]
at com.liferay.change.tracking.internal.aop.CTTransactionAdvice.invoke(CTTransactionAdvice.java:79) [bundleFile:?]
at com.liferay.portal.spring.aop.AopMethodInvocationImpl.proceed(AopMethodInvocationImpl.java:57) [portal-impl.jar:?]
at com.liferay.portal.spring.aop.AopInvocationHandler.invoke(AopInvocationHandler.java:49) [portal-impl.jar:?]
at com.sun.proxy.$Proxy122.getSession(Unknown Source) [?:?]
at com.liferay.mail.kernel.service.MailServiceUtil.getSession(MailServiceUtil.java:81) [portal-kernel.jar:?]
at com.liferay.petra.mail.MailEngine.getSession(MailEngine.java:83) [com.liferay.petra.mail.jar:?]
at com.liferay.petra.mail.MailEngine.send(MailEngine.java:186) [com.liferay.petra.mail.jar:?]
at com.liferay.petra.mail.MailEngine.send(MailEngine.java:336) [com.liferay.petra.mail.jar:?]
at com.liferay.mail.messaging.MailMessageListener.doMailMessage(MailMessageListener.java:100) [portal-impl.jar:?]
at com.liferay.mail.messaging.MailMessageListener.doReceive(MailMessageListener.java:115) [portal-impl.jar:?]
at com.liferay.portal.kernel.messaging.BaseMessageListener.doReceive(BaseMessageListener.java:48) [portal-kernel.jar:?]
at com.liferay.portal.kernel.messaging.BaseMessageListener.receive(BaseMessageListener.java:34) [portal-kernel.jar:?]
at com.liferay.portal.kernel.messaging.InvokerMessageListener.receive(InvokerMessageListener.java:74) [portal-kernel.jar:?]
at com.liferay.portal.messaging.internal.ParallelDestination$1.run(ParallelDestination.java:56) [bundleFile:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
at java.lang.Thread.run(Thread.java:834) [?:?]
Environment
- Liferay DXP 7.4 installation using JNDI email configuration
Resolution
The root cause of this issue is javax.mail.Session class is being loaded by two different classloaders from two java libraries.
- The first class is loaded from the mail.jar library from the application server. (
loader 'javax.mail.api@1.6.5.redhat-00001') - The second class is loaded from the mail.jar library from the Liferay application. (
loader com.liferay.shielded.container.internal.ShieldedContainerClassLoader @345def0f)).
According to the tomcat JDNI installation documentation here: https://tomcat.apache.org/tomcat-9.0-doc/jndi-resources-howto.html#JavaMail_Sessions
In the "4. Install the JavaMail libraries" sections, it is said:
Unpackage the distribution and place mail.jar into $CATALINA_HOME/lib so that it is available to Tomcat during the initialization of the mail Session Resource. Note: placing this jar in both $CATALINA_HOME/lib and a web application's lib folder will cause an error, so ensure you have it in the $CATALINA_HOME/lib location only.
(Although this documentation is for Tomcat, the problem with JBoss would be equivalent.)
So in order to avoid the error, the solution would be to remove the mail.jar library from the Liferay web application, so the javax.mail.Session class should always be resolved using the classloader that is at the application server level.
To remove this mail.jar library from the application server:
- Shutdown the application server
- Create a backup of
[LIFERAY_HOME]/tomcat-9.x.x/webapps/ROOT/WEB-INF/shielded-container-lib/mail.jarjust in in case it is necessary to restore it - Delete the mail.jar from the
shielded-container-libfolder - Start the application server
Additional Information