3
votes

I have an activemq broker and I want to split its configuration into multiple files. I want to prepare a separate configuration file, which will be generated automatically and which will contain only definitions of queues.

File 1: activemq.xml

<beans ...>
  <broker ...>

  </broker>
</beans>

File 2: queues.xml

<beans ...>
  <broker ...>
    <destinations>
      <queue physicalName="q1"/>
    </destinations>
  </broker>
</beans>

I tried to use:

Spring import:

<import resource="queues.xml"/>

but got

ERROR: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.apache.activemq.xbean.XBeanBrokerService#1' defined in class path resource [queues.xml]: Invocation of init method failed; nested exception is javax.management.InstanceAlreadyExistsException: org.apache.activemq:type=Broker,brokerName=localhost org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.apache.activemq.xbean.XBeanBrokerService#1' defined in class path resource [queues.xml]: Invocation of init method failed; nested exception is javax.management.InstanceAlreadyExistsException: org.apache.activemq:type=Broker,brokerName=localhost

XInclude:

activemq.xml:

<beans ...
  xmlns:xi="http://www.w3.org/2001/XInclude"
>
  <broker ...>
    <xi:include href="queues.xml" parse="xml"/>
  </broker>

</beans>

but got

ERROR: org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 142 in XML > document from class path resource [activemq.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 142; columnNumber: 45; cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'xi:include'. org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 142 in XML document from class path resource [activemq.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 142; columnNumber: 45; cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'xi:include'.

Xml entities activemq.xml

<!DOCTYPE beans [
<!ENTITY queues SYSTEM "queues.xml">
]>
<beans ...>
  <broker ...>
    &queues;
  </broker>
</beans>

but got

ERROR: org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 28 in XML document from class path resource [activemq.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 28; columnNumber: 3; Element type "beans" must be declared. org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 28 in XML document from class path resource [activemq.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 28; columnNumber: 3; Element type "beans" must be declared.

Any ideas? Thanks in advance.

4
I know now why the entity approach doesn't work. I use XSD based Spring configuration files for configuring ActiveMQ broker and when I add the entity definition, it switches to DTD validation instead of the XSD and this is why it complains about element beans not being defined. So the entity is being defined correctly, but the very usage of the DTD is problematic and so this solution is a dead way.rattaman

4 Answers

2
votes

I asked at activemq forums and someone posted a solution there. Here is an answer solution at activemq forum. You can use XML entities, but you have to disable XML validation, so you have to start with: bin/activemq start 'xbean:conf/activemq.xml?validate=false'

1
votes

For anyone trying to do this on Openshift's JBoss AMQ (+6.2) xPaaS images, there's a launch.sh script that needs to be modified in the container with the line:

exec $AMQ_HOME/bin/activemq console 'xbean:$AMQ_HOME/conf/activemq.xml?validate=false'

Note the use of 'console' rather than 'start'. As per the OP's desired to split the configuration, you can define multiple configuration files using the DOCTYPE file reference.

From there you can add custom authorization policy entries etc and mount this configuration with config maps.

If you do this, you'll likely break the readinessProbe.sh as well (it can't parse the XML elements you introduce like '&destinationpolicy;'). Fortunately this script is really only interested in the ports (which it could get from ENV!) so a quick solution/hack is to strip away the naughty lines before parsing the XML.

0
votes

these really are spring configuration problems

  • javax.management.InstanceAlreadyExistsException is caused when you try to create 2 beans with same name,so in your configuration please check if you are trying to create 2 beans with identical names.
  • The matching wildcard is strict, but no declaration can be found for element 'xi:include' this error occurs when ddo not have your namespace configured(i.e 'xi' is not a configured namespace for this spring configuration, you need to explicitly define it)
  • SAX parse exception is generally thrown when your xml is not well formed or it doesnt adhere to particular DTD

hope this helps!

Good luck!

0
votes

I've wanted to do this myself but haven't yet found time to try it, so I'm hoping you'll find a way to make it work.

The only idea I've come up with is to try to use Spring's inheritance feature to declare a superclass bean with the common elements/attributes and a subclass bean (with parent=superClassBeanID) that provides the ones that aren't standard. Note that you don't need multiple files for this approach; define both beans in the same file so you don't have to worry about that particular pain point.

Even if it works, this approach wouldn't let you override attributes and elements below the first level, but it might be good enough for what you need. And as I said, I've made no attempt to test this, so it might fail miserably.