activemq в apache karaf, загрузка конфигурации с помощью xbean

Я хочу создать встроенный брокер ActiveMQ, используя конфигурацию xbean внутри пакета OSGi, работающего на Apache Karaf. Этот код:

brokerService = BrokerFactory.createBroker("xbean:file:etc/config.xml");

не выполняется за следующим исключением:

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to load type: org.apache.activemq.xbean.XBeanBrokerService. Reason: java.lang.ClassNotFoundException: org.apache.activemq.xbean.XBeanBrokerService not found by org.apache.xbean.spring [81]; nested exception is java.lang.ClassNotFoundException: org.apache.activemq.xbean.XBeanBrokerService not found by org.apache.xbean.spring [81]
        at org.apache.xbean.spring.context.v2c.XBeanQNameHelper.getBeanInfo(XBeanQNameHelper.java:75)
        at org.apache.xbean.spring.context.v2c.XBeanQNameHelper.coerceNamespaceAwarePropertyValues(XBeanQNameHelper.java:54)
        at org.apache.xbean.spring.context.v2c.XBeanBeanDefinitionParserDelegate.parseBeanDefinitionElement(XBeanBeanDefinitionParserDelegate.java:59)
        at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseBeanDefinitionElement(BeanDefinitionParserDelegate.java:396)
        at org.apache.xbean.spring.context.v2c.XBeanNamespaceHandler.parseBeanFromExtensionElement(XBeanNamespaceHandler.java:224)
        at org.apache.xbean.spring.context.v2c.XBeanNamespaceHandler.parseBeanFromExtensionElement(XBeanNamespaceHandler.java:276)
        at org.apache.xbean.spring.context.v2c.XBeanNamespaceHandler.parse(XBeanNamespaceHandler.java:156)
        at org.apache.xbean.spring.context.v2.XBeanNamespaceHandler.parse(XBeanNamespaceHandler.java:49)
        at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1338)
        at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1328)
        at org.apache.xbean.spring.context.v2.XBeanBeanDefinitionDocumentReader.parseBeanDefinitions(XBeanBeanDefinitionDocumentReader.java:84)
        at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:93)
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493)
        at org.apache.xbean.spring.context.v2.XBeanXmlBeanDefinitionReader.registerBeanDefinitions(XBeanXmlBeanDefinitionReader.java:79)
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390)
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
        at org.apache.xbean.spring.context.ResourceXmlApplicationContext.loadBeanDefinitions(ResourceXmlApplicationContext.java:111)
        at org.apache.xbean.spring.context.ResourceXmlApplicationContext.loadBeanDefinitions(ResourceXmlApplicationContext.java:104)
        at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
        at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:467)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:397)
        at org.apache.xbean.spring.context.ResourceXmlApplicationContext.<init>(ResourceXmlApplicationContext.java:64)
        at org.apache.xbean.spring.context.ResourceXmlApplicationContext.<init>(ResourceXmlApplicationContext.java:52)
        at org.apache.activemq.xbean.XBeanBrokerFactory$1.<init>(XBeanBrokerFactory.java:114)
        at org.apache.activemq.xbean.XBeanBrokerFactory.createApplicationContext(XBeanBrokerFactory.java:114)
        at org.apache.activemq.xbean.XBeanBrokerFactory.createBroker(XBeanBrokerFactory.java:70)
        at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:71)
        at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:54)
        at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:85)
        at jmstest.bundle.TestActivator.start(TestActivator.java:18)
        at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:629)
        at org.apache.felix.framework.Felix.activateBundle(Felix.java:1842)
        at org.apache.felix.framework.Felix.startBundle(Felix.java:1759)
        at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1163)
        at org.apache.felix.framework.StartLevelImpl.run(StartLevelImpl.java:264)
        at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassNotFoundException: org.apache.activemq.xbean.XBeanBrokerService not found by org.apache.xbean.spring [81]
        at org.apache.felix.framework.ModuleImpl.findClassOrResourceByDelegation(ModuleImpl.java:787)
        at org.apache.felix.framework.ModuleImpl.access$400(ModuleImpl.java:71)
        at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.loadClass(ModuleImpl.java:1768)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
        at org.apache.xbean.spring.context.v2c.XBeanQNameHelper.loadClass(XBeanQNameHelper.java:107)
        at org.apache.xbean.spring.context.v2c.XBeanQNameHelper.getBeanInfo(XBeanQNameHelper.java:72)
        ... 36 more

Все необходимые пакеты (activemq, activemq-spring, xbean-spring) загружены и работают, и в моем комплекте они все находятся в Import-Package.

Тот же файл конфигурации, загруженный из автономного брокера ActiveMQ, работает должным образом.

Я считаю, что это происходит потому, что xbean не может получить доступ к классам из пакета, который он не импортирует. Это можно обойти?


person Vladimir Matveev    schedule 11.05.2012    source источник


Ответы (1)


Решил сам, но похоже на взлом. Оцените, если кто-то подскажет, как это исправить, если это возможно.

Идея состоит в том, чтобы заменить загрузчик классов по умолчанию тем, который загружал текущий класс (активатор пакета в моем случае):

ClassLoader c = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

brokerService = BrokerFactory.createBroker("xbean:file:etc/config.xml");
brokerService.start();

Thread.currentThread().setContextClassLoader(c);

XBean пробует несколько загрузчиков классов при загрузке класса, включая загрузчик классов контекста потока. Конечно, getClass().getClassLoader() загрузчик знает об импорте моего пакета, поэтому XBean удается загрузить все необходимые классы (при условии, что они находятся в заголовке Import-Package). Может быть, это будет полезно и кому-то другому.

person Vladimir Matveev    schedule 12.05.2012