I am new to mule and trying to push logs to activemq queue using jms appender. I was getting error while using jms appender with mule 4.3
2025-06-05T07:02:25.588889200Z WrapperListener_start_runner ERROR Could not create plugin of type class org.apache.logging.log4j.core.appender.mom.JmsAppender for element JMS: java.lang.NoClassDefFoundError: javax/jms/JMSException java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2025-06-05T07:02:25.590884400Z WrapperListener_start_runner ERROR Unable to invoke factory method in class org.apache.logging.log4j.core.appender.mom.JmsAppender for element JMS: java.lang.IllegalStateException: No factory method found for class org.apache.logging.log4j.core.appender.mom.JmsAppender java.lang.IllegalStateException: No factory method found for class org.apache.logging.log4j.core.appender.mom.JmsAppender
at org.apache.logging.log4j.core@2.24.2/org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.findFactoryMethod(PluginBuilder.java:268)
at org.apache.logging.log4j.core@2.24.2/org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:140)
then i did some research and found the solution. The solution was to add javax.jms-api.2.0.1.jar to mule/lib/boot folder and the error got resolved.
But after upgrading the mule app from 4.3 to 4.9 version i am getting another error
WrapperManager: Initializing...
Running Mule in testing mode
java.lang.module.ResolutionException: Modules javax.jms.api and jakarta.jms.api export package javax.jms to module org.apache.maven.resolver.transport.wagon
at java.base/java.lang.module.Resolver.resolveFail(Resolver.java:901)
at java.base/java.lang.module.Resolver.failTwoSuppliers(Resolver.java:815)
at java.base/java.lang.module.Resolver.checkExportSuppliers(Resolver.java:736)
what i understood from this error that both javax.jms and jakarta.jms exporting the same package, but i am not using jakarta.jms dependency in my mule app. I don't know if mule 4.9 is adding during runtime.
So If I am removing javax.jms-api jar from boot folder then i am getting NoClassDeFoundError but if I am adding javax.jms-api then I am getting the above error where javax conflicting with jakarta.
So the solution wokring with mule 4.3 is not working with mule 4.9.
example app:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>mule-application</packaging>
<name>test</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<app.runtime>4.4.0-20230320</app.runtime>
<mule.maven.plugin.version>3.8.2</mule.maven.plugin.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-maven-plugin</artifactId>
<version>${mule.maven.plugin.version}</version>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-http-connector</artifactId>
<version>1.7.3</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-sockets-connector</artifactId>
<version>1.2.3</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.16.0</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>anypoint-exchange-v3</id>
<name>Anypoint Exchange</name>
<url>https://maven.anypoint.mulesoft.com/api/v3/maven</url>
<layout>default</layout>
</repository>
<repository>
<id>mulesoft-releases</id>
<name>MuleSoft Releases Repository</name>
<url>https://repository.mulesoft.org/releases/</url>
<layout>default</layout>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>mulesoft-releases</id>
<name>MuleSoft Releases Repository</name>
<layout>default</layout>
<url>https://repository.mulesoft.org/releases/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
jndi.properties
queue.testQueue=LogQueue2
java.naming.provider.url=tcp://localhost:61616
log4j2.xml
<?xml version="1.0" encoding="utf-8"?>
<Configuration>
<!--These are some of the loggers you can enable.
There are several more you can find in the documentation.
Besides this log4j configuration, you can also use Java VM environment variables
to enable other logs like network (-Djavax.net.debug=ssl or all) and
Garbage Collector (-XX:+PrintGC). These will be append to the console, so you will
see them in the mule_ee.log file. -->
<Appenders>
<JMS name="testJMS" factoryName="org.apache.activemq.jndi.ActiveMQInitialContextFactory" factoryBindingName="ConnectionFactory" destinationBindingName="testQueue">
<!-- <PatternLayout pattern="%-5p %d [%t] [processor: %X{processorPath}; event: %X{correlationId}] %c: %m%n"/> -->
<JsonLayout compact="true">
<KeyValuePair key="correlationId" value="${ctx:correlationId}"/>
<KeyValuePair key="processorPath" value="${ctx:attributes.requestUri}"/>
</JsonLayout>
</JMS>
<RollingFile name="file" fileName="${sys:mule.home}${sys:file.separator}logs${sys:file.separator}test.log"
filePattern="${sys:mule.home}${sys:file.separator}logs${sys:file.separator}test-%i.log">
<PatternLayout pattern="%-5p %d [%t] [processor: %X{processorPath}; event: %X{correlationId}] %c: %m%n"/>
<SizeBasedTriggeringPolicy size="10 MB"/>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<!-- Http Logger shows wire traffic on DEBUG -->
<!--AsyncLogger name="org.mule.service.http.impl.service.HttpMessageLogger" level="DEBUG"/-->
<AsyncLogger name="org.mule.service.http" level="WARN"/>
<AsyncLogger name="org.mule.extension.http" level="WARN"/>
<!-- Mule logger -->
<AsyncLogger name="org.mule.runtime.core.internal.processor.LoggerMessageProcessor" level="INFO"/>
<AsyncRoot level="INFO">
<AppenderRef ref="file"/>
</AsyncRoot>
</Loggers>
</Configuration>
this much is enough to reproduce the issue. but create the app based on mule 4.9
Can anyone guide me how can i resolve this issue?
Thanks
The javax.jms API was deprecated and replaced by Jakarta JMS API years ago. Applications and libraries like log4j2 need to migrate to Jakarta JMS API.
It seems to be a limitation of the current version of log4j2:
Due to breaking changes in the underlying API, the JMS Appender cannot be used with Jakarta Messaging API 3.0 or later.
It seems that the support was developed for a future version of log4j2 but apparently has not been backported to log4j2 2.x at this time. I'm not aware of an alternative.
You might need to replace the usage of log4j2 JMS appender by a different appender. I personally believe that queues systems like JMS are not the best place to use for logging.
Another alternative to keep using JMS is to write your own custom JMS appender for your application, using directly the Jakarta JMS API, or find one already created by someone else.