Ошибка приведения Spring JndiObjectFactoryBean к ConnectionFactory для JMS Solace-MQ

У меня есть хорошая рабочая конфигурация XML для Camel Context, которая использует JNDI с Spring

Позже Solace.JndiObjectFactoryBean используется как connectionFactory

<bean id="Solace.JmsComponent" class="  on">
    <property name="connectionFactory" ref="Solace.JndiObjectFactoryBean" />
    <property name="destinationResolver" ref="Solace.JndiDestinationResolver" />
</bean>

Я пытаюсь преобразовать это в класс Java, который простирается от org.apache.camel.spring.javaconfig.CamelConfiguration, Но есть одна проблема. Когда я пытаюсь установить фабрику соединений на компонент JMS component.setConnectionFactory(getJndiObjectFactoryBean()); getJndiObjectFactoryBean(), я получаю исключение времени компиляции:

The method setConnectionFactory(ConnectionFactory) in the type JmsComponent 
is not applicable for the arguments (JndiObjectFactoryBean)

Но когда я пытаюсь привести JndiObjectFactoryBean, возвращенный из getJndiObjectFactoryBean явно, к SolConnectionFactory, я получаю ошибку времени выполнения

016-02-05 17:39:09,234|[localhost-startStop-1]|[]|[]|[ERROR] web.context.ContextLoader [line:307] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getJMSConfiguration' defined in class path resource [com//camel
/CamelRoutesConfig.class]: Instantiation of bean failed; nested exception is org
.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.apache.camel.component.jms.JmsConfiguration com.camel.CamelRoutesConfig.getJMSConfiguration()] threw exception; nested exception is java.lang.ClassCastException: org.springframework.jndi.JndiObjectFactoryBean$$EnhancerByCG
LIB$$18b94f95 cannot be cast to com.solacesystems.jms.SolConnectionFactory
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsi
ngFactoryMethod(ConstructorResolver.java:581)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1029)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
.createBeanInstance(AbstractAutowireCapableBeanFactory.java:925)

Я полагаю, что на пути к классу есть необходимые банки. sol-common-xyzjar, sol-jcsmp-xyzjar, sol-jms-xyzjar

3 ответа

Решение

JndiObjectFactoryBean не может быть брошено в ConnectionFactory,

Есть два варианта:

  1. использование JndiObjectFactoryBean.getObject() в JndiObjectFactoryBean это возвращается вашим getJndiObjectFactoryBean() метод.
  2. Получить Spring, чтобы обеспечить ConnectionFactory,

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml"); ConnectionFactory connectionFactory = (ConnectionFactory) context.getBean("Solace.JndiObjectFactoryBean");

Мы столкнулись с подобной ситуацией, когда портировали рабочую конфигурацию Spring XML (используемую Apache Camel для чтения из очереди Weblogic JMS Server) в предпочтительную конфигурацию Java Spring-Boot.

jmsConfiguration.setConnectionFactory( (javax.jms.ConnectionFactory)getJndiFactoryBean().getObject());

Выше кода сделали трюк для подражания

<bean id="jmsConfiguration" class="org.apache.camel.component.jms.JmsConfiguration">
    <property name="connectionFactory" ref="jndiFactoryBean"/>
    <property name="destinationResolver" ref="jndiDestinationResolver"/>
</bean>

(Непонятно, что Spring XML делает дополнительно под прикрытием, поскольку это не так просто, как установка jndiFactoryBean на jmsConfiguration)

В случае, если вы используете подход getObject(), обязательно вызовите afterPropertiesSet(), прежде чем использовать getObject()

org.springframework.jndi.JndiObjectFactoryBean cf = new org.springframework.jndi.JndiObjectFactoryBean();
JndiTemplate jndiTemplate = new org.springframework.jndi.JndiTemplate();
Properties environment = new Properties();
environment.setProperty("java.naming.factory.initial", "com.xxx"); //initial context
environment.setProperty("java.naming.provider.url", "xxx://xxx"); //url
jndiTemplate.setEnvironment(environment);
cf.setJndiTemplate(jndiTemplate);
cf.setJndiName("XXX");
//System.out.println(cf.getObject()); //null
cf.afterPropertiesSet();
//System.out.println(cf.getObject()); //now has the value

org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter adapter = new org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter();
adapter.setTargetConnectionFactory((ConnectionFactory) cf.getObject());
Другие вопросы по тегам