Announcement Announcement Module
Collapse
No announcement yet.
How to start ActiveMq broker from spring xml configuration? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to start ActiveMq broker from spring xml configuration?

    Hi,

    I'm trying to deploy and application hosted within Tomcat that has active JMS queue(s). The goal is to be able to send messages from a remote client.

    This is my connection factory settings:

    <!-- JMS ConnectionFactory to use -->
    <bean id="jmsFactory" class="org.codehaus.activemq.ActiveMQConnectionFac tory">
    <property name="brokerURL">
    <!--<value>vm://localhost</value>-->
    <value>tcp://localhost:61616</value>
    </property>
    </bean>

    The problem is, where do I call the start() function?

    Thanks for helping!

  • #2
    you can use init-method:
    Code:
      <bean id="jmsFactory"
                class="org.codehaus.activemq.ActiveMQConnectionFactory"
                init-method="start"> 
        <property name="brokerURL"> 
          <value>tcp&#58;//localhost&#58;61616</value> 
        </property> 
    </bean>
    HTH

    Comment


    • #3
      Originally posted by irbouho
      you can use init-method:
      Code:
        <bean id="jmsFactory"
                  class="org.codehaus.activemq.ActiveMQConnectionFactory"
                  init-method="start"> 
          <property name="brokerURL"> 
            <value>tcp&#58;//localhost&#58;61616</value> 
          </property> 
      </bean>
      HTH
      Indeed this is Spring's way to execute the start() function, however, my problem lies elsewhere. I am at loss on how to wire Activemq together with Spring within Tomcat to start a JMS listener that is available for remote clients to connect to and start pumping messages into.

      So far, I've been able to use Activemq's "vm://localhost" in my junit test cases to pass messages using these beans (taken from Activemq's sample directory):

      Code:
          <!-- JMS ConnectionFactory to use -->
          <bean id="jmsFactory" class="org.codehaus.activemq.ActiveMQConnectionFactory">
              <property name="brokerURL">
                  <!-- <value>vm&#58;//localhost</value> -->
                  <value>tcp&#58;//localhost&#58;61616</value>
              </property>
          </bean>
          
          <!-- Spring JMS Template -->
          <bean id="myJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
              <property name="connectionFactory">
                  <!-- lets wrap in a pool to avoid creating a connection per send -->
                  <bean class="org.springframework.jms.connection.SingleConnectionFactory">
                      <property name="targetConnectionFactory">
                          <ref local="jmsFactory"/>
                      </property>
                  </bean>
              </property>
              <property name="pubSubDomain">
                  <value>false</value>
              </property>
          </bean>
          
          <!-- a sample POJO which uses a Spring JmsTemplate -->
          <bean id="producer" class="message.SpringProducer">
              <property name="template">
                <ref bean="myJmsTemplate"></ref>
              </property>
          
              <property name="subject">
                <value>org.codehaus.activemq.spring.Test</value>
              </property>
              
              <property name="messageCount">
                <value>10</value>
              </property>
          </bean>
          
          
          <!-- a sample POJO consumer -->
          <bean id="consumer" class="message.SpringConsumer">
              <property name="template">
                <ref bean="myJmsTemplate"></ref>
              </property>
              
              <property name="destination">
                <bean class="org.codehaus.activemq.message.ActiveMQQueue" autowire="constructor">
                  <constructor-arg>
                    <value>org.codehaus.activemq.spring.Test</value>
                  </constructor-arg>
                </bean>
              </property>
          </bean>
      However, in reality, something needs to be a listener that a remote client (e.g. on another machine) needs to be able to connect to and send messages. What that something is, that's the one I need help with

      Comment


      • #4
        Firstly, the documentation on using Spring with ActiveMQ is here...

        http://activemq.codehaus.org/Spring+Support

        So you're first example of Spring XML works great for creating your JMS client (connection factory) for ActiveMQ in Spring. Setting the embedded broker flag would deploy a broker inside the connection factory.

        If you are using an embedded broker, you can configure this using the XML configuration file (which uses Spring under the covers) like this, where you reference the XML config file..

        Code:
         <bean id="jmsFactory" class="org.codehaus.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL">
              <value>vm&#58;//localhost</value>
            </property>
            <property name="useEmbeddedBroker">
              <value>true</value>
            </property>
            <property name="brokerContainerFactory">
              <!-- specify that the ActiveMQ XML config file should be used to configure the Broker -->
              <bean class="org.codehaus.activemq.spring.SpringBrokerContainerFactory">
                <property name="resource">
                  <value>classpath&#58;org/codehaus/activemq/spring/activemq.xml</value>
                </property>
              </bean>
            </property>
          </bean>

        Comment


        • #5
          I've just updated the Spring + ActiveMQ documentation to make this a little more clear...

          http://activemq.codehaus.org/Spring+Support?refresh=1

          Comment


          • #6
            More questions

            Originally posted by jstrachan
            Firstly, the documentation on using Spring with ActiveMQ is here...

            http://activemq.codehaus.org/Spring+Support

            So you're first example of Spring XML works great for creating your JMS client (connection factory) for ActiveMQ in Spring. Setting the embedded broker flag would deploy a broker inside the connection factory.
            Correct, I totally got it (finally )
            However, I notice that Activemq has an issue with using urls other than vm://localhost for embedded broker (Issue AMQ-77 in Jira). I actually reproduced that issue and got the same error (Address has been used in JVM Bind).

            Now, for my case (and I'm sure for a lot of others as well), a broker is only useful if my producers can get to it remotely (not within the same JVM). So until this problem has been fixed, I can't use the embedded broker.

            Having said that, now that I finally are able to build Activemq 1.1 snapshot on my box, I'm actually tempted to help fix this problem. Any directions on which area to focus on?

            Another question is the scalability of the embedded broker, is this designed to be a sandbox (light load) testing only, in other words, how is the embedded broker different (performance and capacity-wise) than the "real" broker running as a separate server?

            Apology to Spring people for taking the bandwidth with Activemq questions, but I do believe Spring and Activemq *together* provides a convincing argument for not solving everything with an app-server.

            Comment


            • #7
              Re: More questions

              Originally posted by wgunadi
              Originally posted by jstrachan
              Firstly, the documentation on using Spring with ActiveMQ is here...

              http://activemq.codehaus.org/Spring+Support

              So you're first example of Spring XML works great for creating your JMS client (connection factory) for ActiveMQ in Spring. Setting the embedded broker flag would deploy a broker inside the connection factory.
              Correct, I totally got it (finally )
              Great
              However, I notice that Activemq has an issue with using urls other than vm://localhost for embedded broker (Issue AMQ-77 in Jira). I actually reproduced that issue and got the same error (Address has been used in JVM Bind).

              Now, for my case (and I'm sure for a lot of others as well), a broker is only useful if my producers can get to it remotely (not within the same JVM). So until this problem has been fixed, I can't use the embedded broker.
              There are a few options here despite the AMQ-77 issue. There is the URL you connect to the local embedded broker and the URL others use to connect to the embedded broker. So you can use vm://localhost to connect to the embedded broker - and other remote clients can connect using whatever transportConnector you've configured in your activemq.xml file.

              e.g. a remove client could connect via tcp://somehostort yet the ConnectionFactory using the embedded broker should always use a vm://localhost style URL to avoid unnecessary networking/marshalling.

              i.e. the URL you connect to in the ConnectionFactory is specified by the brokerURL property. The URLs that a broker accepts from remote VMs are specified in the transportConnector elements in the activemq.xml file. So 1 broker could accept 10 different URLs with different protocols and details (http, multicast, tcp, ssl and whatever ports you wish). It will always allow VM transport for JMS clients inside the same VM to connect efficiently.

              Having said that, now that I finally are able to build Activemq 1.1 snapshot on my box, I'm actually tempted to help fix this problem. Any directions on which area to focus on?
              The code for handling URLs and embedded brokers is all a little fiddley right now - I'd probably suggest searching around JIRA and finding a more fun bit of code to work on - like Jabber support or something . Being able to watch JMS topics using a Jabber client sounds cool

              Another question is the scalability of the embedded broker, is this designed to be a sandbox (light load) testing only, in other words, how is the embedded broker different (performance and capacity-wise) than the "real" broker running as a separate server?

              Apology to Spring people for taking the bandwidth with Activemq questions, but I do believe Spring and Activemq *together* provides a convincing argument for not solving everything with an app-server.
              The embedded broker is completely identical to the remove standalone broker - other than its in the same VM versus a remote VM. For very heavy loads, having your broker in a separate VM can help from a stability perspective (e.g. figuring out how much RAM you need gets harder as you run more distributed services inside the same JVM).

              Its completely up to you how you configure the embedded broker & what kinds of services it can offer such as transports, persistence, discovery agents, network connectors etc.

              I hope that helps - and thanks for your kind words on ActiveMQ and Spring. We also think they're a great combination - increasingly we see ActiveMQ as a great plugin to Spring for all kinds of remoting and clustering features too.

              Comment


              • #8
                Re: More questions

                Originally posted by jstrachan
                There are a few options here despite the AMQ-77 issue. There is the URL you connect to the local embedded broker and the URL others use to connect to the embedded broker. So you can use vm://localhost to connect to the embedded broker - and other remote clients can connect using whatever transportConnector you've configured in your activemq.xml file.

                e.g. a remove client could connect via tcp://somehostort yet the ConnectionFactory using the embedded broker should always use a vm://localhost style URL to avoid unnecessary networking/marshalling.

                i.e. the URL you connect to in the ConnectionFactory is specified by the brokerURL property. The URLs that a broker accepts from remote VMs are specified in the transportConnector elements in the activemq.xml file. So 1 broker could accept 10 different URLs with different protocols and details (http, multicast, tcp, ssl and whatever ports you wish). It will always allow VM transport for JMS clients inside the same VM to connect efficiently.
                I try this but I still hit the AMQ-77 problem:

                Code:
                2004-09-16 15&#58;04&#58;10,703 WARN 
                &#91;org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy&#93; - <Factory method public static org.codehaus.activemq.transport.TransportServerChannel org.codehaus.activemq.transport.TransportServerChannelProvider.newInstance&#40;org.codehaus.activemq.message.WireFormat,java.lang.String&#41; throws javax.jms.JMSException,java.net.URISyntaxException threw exception>
                javax.jms.JMSException&#58; Bind to tcp&#58;//localhost&#58;61616 failed&#58; Address already in use&#58; JVM_Bind

                Here's my configuration:
                First, I declare a jmsFactory bean that will give me a ConnectionFactory whose url is vm://localhost, but it is configured to use a tcp connector:

                Code:
                    <bean id="jmsFactory" class="org.codehaus.activemq.ActiveMQConnectionFactory">
                        <property name="brokerURL">
                            <value>vm&#58;//localhost</value>
                        </property>
                        <property name="useEmbeddedBroker">
                            <value>true</value>
                        </property>
                        <property name="brokerContainerFactory">
                            <!-- specify that the ActiveMQ XML config file should be used to configure the Broker -->
                            <bean class="org.codehaus.activemq.spring.SpringBrokerContainerFactory">
                                <property name="resource">
                                    <!-- <value>classpath&#58;org/codehaus/activemq/spring/activemq.xml</value> -->
                                    <value>/WEB-INF/springBroker.xml</value>
                                </property>
                            </bean>
                        </property>
                    </bean>
                ... with springBroker.xml contains:

                Code:
                  <broker>
                    <connector>
                      <tcpServerTransport uri="tcp&#58;//localhost&#58;61616" backlog="1000" useAsyncSend="true" maxOutstandingMessages="50"/>
                    </connector>
                
                    <persistence>
                      <jdbmPersistence directory="target/jdbm"/>
                    </persistence>
                  </broker>
                Am I interpreting your instruction correctly? or am I missing something?

                Comment


                • #9
                  Proper usage?

                  I'm new to JMS and currently I'm lost at configuring ActiveMQ to run in Tomcat.

                  What from all of these beans (xml below) do I need to be able to run JMS as in EJB container?

                  What does this property (in my inboundMessageB/activationSpec) do?
                  <property name="destinationName">
                  <value>test.spring.inboundMessageB</value>
                  </property>

                  Where do I configure all possible queues and topics?

                  Who does the binding of queues and topics to JNDI?

                  Uf, uf :? ... so much to grasp ...

                  Rgds, Ales

                  btw: where do I get activemq-container.jar which containes Spring binding classes - since the one on download site doesn't include org.codehaus.activemq.jca.TargetSourceMessageListe ner class

                  ------------------------- jms.xml ----------------------

                  <?xml version="1.0" encoding="UTF-8"?>
                  <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

                  <!--
                  - JMS configuration
                  -->
                  <beans>

                  <!-- BROKER -->

                  <bean id="jmsFactory" class="org.codehaus.activemq.ActiveMQConnectionFac tory">
                  <property name="brokerURL"><value>vm://localhost</value></property>
                  <property name="useEmbeddedBroker"><value>true</value></property>
                  <!-- specify that the ActiveMQ XML config file should be used to configure the Broker -->
                  <property name="brokerXmlConfig"><value>org/codehaus/activemq/spring/example.xml</value></property>
                  </bean>

                  <!-- CONSUMER -->

                  <!-- A JCA container for ActiveMQ -->
                  <bean id="activeMQContainer" class="org.codehaus.activemq.jca.JCAContainer">

                  <!-- the work manager (thread pool) for this container -->
                  <property name="workManager">
                  <bean id="workManager" class="org.codehaus.activemq.work.SpringWorkManage r">
                  </bean>
                  </property>

                  <!-- the JCA Resource Adapter -->
                  <property name="resourceAdapter">
                  <bean id="activeMQResourceAdapter" class="org.codehaus.activemq.ra.ActiveMQResourceAd apter">
                  <property name="serverUrl">
                  <value>vm://localhost</value>
                  </property>
                  </bean>
                  </property>

                  </bean>

                  <!-- an inbound message connector using a stateful, pooled MessageListener -->
                  <bean id="inboundMessageB" factory-method="addConnector" factory-bean="activeMQContainer" singleton="true">
                  <!-- subscription details -->
                  <property name="activationSpec">
                  <bean class="org.codehaus.activemq.ra.ActiveMQActivation Spec">
                  <property name="destinationName">
                  <value>test.spring.inboundMessageB</value>
                  </property>
                  <property name="destinationType">
                  <value>javax.jms.Queue</value>
                  </property>
                  </bean>
                  </property>
                  <!-- This example uses a pooled bean -->
                  <property name="messageListener">
                  <ref bean="pooledEchoBean"/>
                  </property>
                  </bean>

                  <!-- Message Driven POJOs -->
                  <!-- a thread safe non-pooled MessageListener -->
                  <bean id="echoBean" class="org.codehaus.activemq.jca.TestBean"/>

                  <!-- a pooled, non-thread safe MessageListener using ProxyFactoryBean -->
                  <bean id="pooledEchoBean" class="org.codehaus.activemq.jca.TargetSourceMessa geListener">
                  <property name="targetSource">
                  <bean id="pooledEchoBeanTargetSource" class="org.springframework.aop.target.CommonsPoolT argetSource">
                  <property name="targetBeanName">
                  <value>pooledEchoBeanTarget</value>
                  </property>
                  <property name="maxSize">
                  <value>25</value>
                  </property>
                  </bean>
                  </property>
                  </bean>

                  <!-- Message Driven POJOs -->
                  <!-- a non-thread safe pooled MessageListener -->
                  <bean id="pooledEchoBeanTarget" class="org.codehaus.activemq.jca.TestBean" singleton="false"/>

                  <!-- PRODUCER -->

                  <bean id="jmsProducer" class="org.springframework.jms.JmsProducerFactoryB ean">
                  <property name="session"><ref local="jmsSession"/></property>
                  <property name="destination"><ref local="queue"/></property>
                  <property name="priority"><value>6</value></property>
                  </bean>

                  <bean id="queue" class="org.springframework.jndi.JndiObjectFactoryB ean">
                  <property name="jndiName"><value>testQueueJndi</value></property>
                  </bean>

                  <bean id="jmsSession" class="org.springframework.jms.JmsSessionFactoryBe an">
                  <property name="transacted"><value>false</value></property>
                  <property name="connection"><ref local="jmsConnection"/></property>
                  </bean>

                  <bean id="jmsConnection" class="org.springframework.jms.JmsConnectionFactor yBean">
                  <property name="connectionFactory"><ref local="jmsConnFactory"/></property>
                  </bean>

                  <bean id="jmsConnFactory" class="org.springframework.jndi.JndiObjectFactoryB ean">
                  <property name="jndiName"><value>QueueConnectionFactory</value></property>
                  </bean>

                  </beans>

                  Comment


                  • #10
                    Good modificatios?

                    I'm trying to get 'JCA Container' example working.
                    At current binaries I had to modify spring.xml.

                    JCAConnector has no messageListener property and looking at source code I presumed you have to set TargetSource.

                    Insted of
                    <property name="messageListener">
                    <ref bean="echoBean"/>
                    </property>

                    Going directly to pool target source
                    <property name="targetSource"><ref local="pooledEchoBeanTargetSource"/></property>

                    You also have to add concurrent.jar (not mentioned anywhere) to make things work.

                    What else must I do to be able to send messages to a queue? When I was
                    able to start this (the modified spring.xml went through on starting web
                    app), does this mean that there is already a consumer waiting for
                    messages, similar to MDB?
                    Which queue, destination?

                    How do I wire up producer?
                    Some xml bean wiring code from Mark Pollack didn't do the trick (PRODUCER xml below).
                    The code it self works, but I don't know where to look for connectionFactory (JNDI lookup exception thrown), ...

                    Kind regards,
                    Ales Justin

                    ---------- modified spring.xml ------------
                    <?xml version="1.0" encoding="UTF-8"?>
                    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
                    "http://www.springframework.org/dtd/spring-beans.dtd">

                    <!--
                    - JMS configuration
                    -->
                    <beans>

                    <!-- CONSUMER -->

                    <!-- A JCA container for ActiveMQ -->
                    <bean id="activeMQContainer"
                    class="org.codehaus.activemq.jca.JCAContainer">
                    <!-- the work manager (thread pool) for this container -->
                    <property name="workManager">
                    <bean id="workManager"
                    class="org.codehaus.activemq.work.SpringWorkManage r" />
                    </property>
                    <!-- the JCA Resource Adapter -->
                    <property name="resourceAdapter">
                    <bean id="activeMQResourceAdapter"
                    class="org.codehaus.activemq.ra.ActiveMQResourceAd apter">
                    <property
                    name="serverUrl"><value>vm://localhost</value></property>
                    </bean>
                    </property>
                    </bean>

                    <!-- an inbound message connector using a stateful, pooled
                    MessageListener -->
                    <bean id="inboundMessage" factory-method="addConnector"
                    factory-bean="activeMQContainer">
                    <!-- subscription details -->
                    <property name="activationSpec">
                    <bean class="org.codehaus.activemq.ra.ActiveMQActivation Spec">
                    <property
                    name="destinationName"><value>testQueueJndi</value></property>
                    <property
                    name="destinationType"><value>javax.jms.Queue</value></property>
                    </bean>
                    </property>
                    <!-- This example uses a pooled bean -->
                    <property name="targetSource"><ref
                    local="pooledEchoBeanTargetSource"/></property>
                    </bean>

                    <!-- a pooled, non-thread safe MessageListener using
                    ProxyFactoryBean -->
                    <bean id="pooledEchoBeanTargetSource"
                    class="org.springframework.aop.target.CommonsPoolT argetSource">
                    <property
                    name="targetBeanName"><value>pooledEchoBeanTarget</value></property>
                    <property name="maxSize"><value>25</value></property>
                    </bean>

                    <!-- Message Driven POJOs -->
                    <!-- a non-thread safe pooled MessageListener -->
                    <bean id="pooledEchoBeanTarget"
                    class="com.generalynx.ecos.connector.jms.EchoBean" singleton="false"/>

                    <bean id="testBean"
                    class="com.generalynx.ecos.connector.jms.TestConne ctor" >
                    <property name="connector"><ref local="inboundMessage"/></property>
                    </bean>

                    <!-- PRODUCER -->

                    <bean id="jmsProducer"
                    class="org.springframework.jms.JmsProducerFactoryB ean">
                    <property name="session"><ref local="jmsSession"/></property>
                    <property name="destination"><ref local="queue"/></property>
                    <property name="priority"><value>6</value></property>
                    </bean>

                    <bean id="queue" class="org.springframework.jndi.JndiObjectFactoryB ean">
                    <property name="jndiName"><value>testQueueJndi</value></property>
                    </bean>

                    <bean id="jmsSession"
                    class="org.springframework.jms.JmsSessionFactoryBe an">
                    <property name="transacted"><value>false</value></property>
                    <property name="connection"><ref local="jmsConnection"/></property>
                    </bean>

                    <bean id="jmsConnection"
                    class="org.springframework.jms.JmsConnectionFactor yBean">
                    <property name="connectionFactory"><ref
                    local="jmsConnFactory"/></property>
                    </bean>

                    <bean id="jmsConnFactory"
                    class="org.springframework.jndi.JndiObjectFactoryB ean"
                    depends-on="inboundMessage" >
                    <property
                    name="jndiName"><value>ConnectionFactory</value></property>
                    </bean>

                    </beans>

                    Comment

                    Working...
                    X