0

I'm replacing activemq-all 5.18.6 with activemq-broker and activemq-client. I've found a side effect in my Java servlets that javax.jms.ConnectionFactory has to be replaced in the servlet XML and the Java code with org.apache.activemq.ActiveMQConnectionFactory. However, this leads to a runtime error in the Catalina log:

WARNING [main] XmlWebApplicationContext.refresh Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'JMSConnectionFactory' defined in ServletContext resoure [/WEB-INF/JmsProcessing-servlet.xml]: Invocation of init method failed; nested exception is javax.naming.NamingException: Unexpected exception resolving reference [Root exception is java.lang.IllegalArgumentException: The local resource link [ConnectionFactory] that refers to global resource [jms/ConnectionFactory] was expected to return an instance of [org.apache.activemq.ActiveMQConnectionFactory] but returned an instance of [org.apache.activemq.ActiveMQConnectionFactory]]

I have verified that org.apache.activemq.ActiveMQConnectionFactory is being referenced in all relevant locations so it's not a simple typo.

context.xml:

<?xml....?>
<Context docBase="JmsProcessing" reloadable="true">
   <ResourceLink name="jdbc/dev" global="jdbc/dev" type="javax.sql.DataSource" />
   <ResourceLink name="jms/ConnectionFactory"
                 global="jms/ConnectionFactory"
                 type="org.apache.activemq.ActiveMQConnectionFactory" />
       <!-- was  type="javax.jms.ConnectionFactory" -->
</Context>

JmsProcessing-servlet.xml:

<?xml ... ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       org/springframework/beans/factory/xml/spring-beans-2.5.xsd
       spring-beans-2.5.xsd">
   <bean id="JMSConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
      <property name="jndiName">
         <value>java:comp/env/jms/ConnectionFactory</value>
      </property>
   </bean>

   <bean name="processingBean" class="com.custom.processing.impl.JmsProcessor">
      <property name="connectionFactory" ref="JMSConnectionFactory" />
   </bean>
</beans>

I'm using Spring 4.3.18, building in Java 17, running in Java 11 on RH9.

I found activemq-client-5.18.6.jar in two locations. From the install directory, they are

  • tomcat/lib/activemq-client-5.18.6.jar
  • tomcat/webapps/JmsProcessing/WEB-INF/lib/activemq-client-5.18.6.jar

I suspect the jar needs to be in the webapp-specific directory and not the Tomcat lib directory, but I could have this backwards.

6
  • yikes! spring config in xml? Haven't seen that in many years Commented Apr 25 at 15:39
  • @lance-java I didn't write it, I'm just maintaining it. Commented Apr 25 at 15:55
  • @JustinBertram: First, visual inspection. Second, I copied both instances to separate files and ran diff - it said they were identical. Third, a search in vi found both. I'm trying to get Tomcat to tell me what classpath it's actually using at runtime, because multiple instances of the same class is quite possible. Commented Apr 25 at 15:57
  • @JustinBertram In my previous comment, yes I was referring to the actual text. If there is a way I can inspect the runtime instances and see why they might not be perfectly identical, please suggest it. Commented Apr 25 at 16:00
  • @JustinBertram Because that caused a possibly similar problem (or possibly similar fix) -- expected instance was javax.jms.ConnectionFactory but actual instance was org....ActiveMQConnectionFactory. I had come across something saying I should only have needed to change the XML files, not the code..... Commented Apr 25 at 16:03

1 Answer 1

0

This sounds like a classloading problem to me. I've seen this kind of thing before where two instance of the same class are considered different because they came from different classloaders (i.e. different jars). I'm not familiar with Tomcat classloading behavior so my recommendation would be to eliminate one instance of activemq-client-5.18.6.jar and test. If it still doesn't work then restore the one you eliminated and eliminate the other and test.

Generally speaking, you definitely should be able to use the JMS API rather than implementation-specific ActiveMQ classes. That's one of the main benefits of using an API in the first place.

Lastly, you typically don't need activemq-broker on your application's classpath. That's usually only necessary if you're running an embedded instance of the broker in the same JVM as the client application.

Sign up to request clarification or add additional context in comments.

2 Comments

In reply to the last paragraph - one of the other web apps imports activemq.broker.jmx.TopicViewMBean. I haven't touched any of the MBean-related code.
Understood. I guess that's a design flaw for these classes in ActiveMQ Classic. Those MBean definitions should almost certainly be pulled out of the broker module and either into their own module or potentially the client module as is done in ActiveMQ Artemis.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.