JBoss hornetq SVN: r10021 - in trunk/examples/jms/clustered-static-discovery: server0 and 4 other directories.
by do-not-reply@jboss.org
Author: ataylor
Date: 2010-12-09 11:47:56 -0500 (Thu, 09 Dec 2010)
New Revision: 10021
Added:
trunk/examples/jms/clustered-static-discovery/server2/
trunk/examples/jms/clustered-static-discovery/server2/client-jndi.properties
trunk/examples/jms/clustered-static-discovery/server2/hornetq-beans.xml
trunk/examples/jms/clustered-static-discovery/server2/hornetq-configuration.xml
trunk/examples/jms/clustered-static-discovery/server2/hornetq-jms.xml
trunk/examples/jms/clustered-static-discovery/server2/hornetq-users.xml
trunk/examples/jms/clustered-static-discovery/server2/jndi.properties
trunk/examples/jms/clustered-static-discovery/server3/
trunk/examples/jms/clustered-static-discovery/server3/client-jndi.properties
trunk/examples/jms/clustered-static-discovery/server3/hornetq-beans.xml
trunk/examples/jms/clustered-static-discovery/server3/hornetq-configuration.xml
trunk/examples/jms/clustered-static-discovery/server3/hornetq-jms.xml
trunk/examples/jms/clustered-static-discovery/server3/hornetq-users.xml
trunk/examples/jms/clustered-static-discovery/server3/jndi.properties
Modified:
trunk/examples/jms/clustered-static-discovery/build.xml
trunk/examples/jms/clustered-static-discovery/server0/hornetq-jms.xml
trunk/examples/jms/clustered-static-discovery/server1/hornetq-jms.xml
trunk/examples/jms/clustered-static-discovery/src/org/hornetq/jms/example/StaticClusteredQueueExample.java
Log:
updated static discovery example
Modified: trunk/examples/jms/clustered-static-discovery/build.xml
===================================================================
--- trunk/examples/jms/clustered-static-discovery/build.xml 2010-12-09 15:01:09 UTC (rev 10020)
+++ trunk/examples/jms/clustered-static-discovery/build.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -21,7 +21,7 @@
<target name="run">
<antcall target="runExample">
<param name="example.classname" value="org.hornetq.jms.example.StaticClusteredQueueExample"/>
- <param name="hornetq.example.beans.file" value="server0 server1"/>
+ <param name="hornetq.example.beans.file" value="server0 server1 server2 server3"/>
</antcall>
</target>
Modified: trunk/examples/jms/clustered-static-discovery/server0/hornetq-jms.xml
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server0/hornetq-jms.xml 2010-12-09 15:01:09 UTC (rev 10020)
+++ trunk/examples/jms/clustered-static-discovery/server0/hornetq-jms.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -9,6 +9,18 @@
<entries>
<entry name="ConnectionFactory"/>
</entries>
+
+ <ha>true</ha>
+ <!-- Pause 1 second between connect attempts -->
+ <retry-interval>1000</retry-interval>
+
+ <!-- Multiply subsequent reconnect pauses by this multiplier. This can be used to
+ implement an exponential back-off. For our purposes we just set to 1.0 so each reconnect
+ pause is the same length -->
+ <retry-interval-multiplier>1.0</retry-interval-multiplier>
+
+ <!-- Try reconnecting an unlimited number of times (-1 means "unlimited") -->
+ <reconnect-attempts>-1</reconnect-attempts>
</connection-factory>
<!--the queue used by the example-->
Modified: trunk/examples/jms/clustered-static-discovery/server1/hornetq-jms.xml
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server1/hornetq-jms.xml 2010-12-09 15:01:09 UTC (rev 10020)
+++ trunk/examples/jms/clustered-static-discovery/server1/hornetq-jms.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -9,6 +9,18 @@
<entries>
<entry name="ConnectionFactory"/>
</entries>
+
+ <ha>true</ha>
+ <!-- Pause 1 second between connect attempts -->
+ <retry-interval>1000</retry-interval>
+
+ <!-- Multiply subsequent reconnect pauses by this multiplier. This can be used to
+ implement an exponential back-off. For our purposes we just set to 1.0 so each reconnect
+ pause is the same length -->
+ <retry-interval-multiplier>1.0</retry-interval-multiplier>
+
+ <!-- Try reconnecting an unlimited number of times (-1 means "unlimited") -->
+ <reconnect-attempts>-1</reconnect-attempts>
</connection-factory>
<!--the queue used by the example-->
Copied: trunk/examples/jms/clustered-static-discovery/server2/client-jndi.properties (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/client-jndi.properties)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server2/client-jndi.properties (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server2/client-jndi.properties 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,16 @@
+#
+# Copyright 2009 Red Hat, Inc.
+# Red Hat licenses this file to you under the Apache License, version
+# 2.0 (the "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+java.naming.provider.url=jnp://localhost:3099
+java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
Copied: trunk/examples/jms/clustered-static-discovery/server2/hornetq-beans.xml (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/hornetq-beans.xml)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server2/hornetq-beans.xml (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server2/hornetq-beans.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Copyright 2009 Red Hat, Inc.
+ ~ Red Hat licenses this file to you under the Apache License, version
+ ~ 2.0 (the "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ ~ implied. See the License for the specific language governing
+ ~ permissions and limitations under the License.
+ -->
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="Naming" class="org.jnp.server.NamingBeanImpl"/>
+
+ <!-- JNDI server. Disable this if you don't want JNDI -->
+ <bean name="JNDIServer" class="org.jnp.server.Main">
+ <property name="namingInfo">
+ <inject bean="Naming"/>
+ </property>
+ <property name="port">3099</property>
+ <property name="bindAddress">localhost</property>
+ <property name="rmiPort">3098</property>
+ <property name="rmiBindAddress">localhost</property>
+ </bean>
+
+ <!-- MBean server -->
+ <bean name="MBeanServer" class="javax.management.MBeanServer">
+ <constructor factoryClass="java.lang.management.ManagementFactory"
+ factoryMethod="getPlatformMBeanServer"/>
+ </bean>
+
+ <!-- The core configuration -->
+ <bean name="Configuration" class="org.hornetq.core.config.impl.FileConfiguration"/>
+
+ <!-- The security manager -->
+ <bean name="HornetQSecurityManager" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl">
+ <start ignored="true"/>
+ <stop ignored="true"/>
+ </bean>
+
+ <!-- The core server -->
+ <bean name="HornetQServer" class="org.hornetq.core.server.impl.HornetQServerImpl">
+ <constructor>
+ <parameter>
+ <inject bean="Configuration"/>
+ </parameter>
+ <parameter>
+ <inject bean="MBeanServer"/>
+ </parameter>
+ <parameter>
+ <inject bean="HornetQSecurityManager"/>
+ </parameter>
+ </constructor>
+ <start ignored="true"/>
+ <stop ignored="true"/>
+ </bean>
+
+ <!-- The JMS server -->
+ <bean name="JMSServerManager" class="org.hornetq.jms.server.impl.JMSServerManagerImpl">
+ <constructor>
+ <parameter>
+ <inject bean="HornetQServer"/>
+ </parameter>
+ </constructor>
+ </bean>
+
+</deployment>
Copied: trunk/examples/jms/clustered-static-discovery/server2/hornetq-configuration.xml (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/hornetq-configuration.xml)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server2/hornetq-configuration.xml (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server2/hornetq-configuration.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,69 @@
+<!--
+ ~ Copyright 2009 Red Hat, Inc.
+ ~ Red Hat licenses this file to you under the Apache License, version
+ ~ 2.0 (the "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ ~ implied. See the License for the specific language governing
+ ~ permissions and limitations under the License.
+ -->
+
+<configuration xmlns="urn:hornetq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd">
+ <clustered>true</clustered>
+
+ <!-- Connectors -->
+ <connectors>
+ <connector name="netty-connector">
+ <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
+ <param key="port" value="5447"/>
+ </connector>
+ <!-- connector to the server0 -->
+ <connector name="server0-connector">
+ <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
+ <param key="port" value="5445"/>
+ </connector>
+ </connectors>
+
+ <!-- Acceptors -->
+ <acceptors>
+ <acceptor name="netty-acceptor">
+ <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
+ <param key="port" value="5447"/>
+ </acceptor>
+ </acceptors>
+
+ <!-- Clustering configuration -->
+ <cluster-connections>
+ <cluster-connection name="my-cluster">
+ <address>jms</address>
+ <connector-ref>netty-connector</connector-ref>
+ <retry-interval>500</retry-interval>
+ <use-duplicate-detection>true</use-duplicate-detection>
+ <forward-when-no-consumers>true</forward-when-no-consumers>
+ <max-hops>1</max-hops>
+ <static-connectors>
+ <connector-ref>server0-connector</connector-ref>
+ </static-connectors>
+ </cluster-connection>
+ </cluster-connections>
+
+ <!-- Other config -->
+
+ <security-settings>
+ <!--security for example queue-->
+ <security-setting match="jms.queue.exampleQueue">
+ <permission type="createDurableQueue" roles="guest"/>
+ <permission type="deleteDurableQueue" roles="guest"/>
+ <permission type="createNonDurableQueue" roles="guest"/>
+ <permission type="deleteNonDurableQueue" roles="guest"/>
+ <permission type="consume" roles="guest"/>
+ <permission type="send" roles="guest"/>
+ </security-setting>
+ </security-settings>
+
+</configuration>
Copied: trunk/examples/jms/clustered-static-discovery/server2/hornetq-jms.xml (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/hornetq-jms.xml)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server2/hornetq-jms.xml (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server2/hornetq-jms.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,45 @@
+<!--
+ ~ Copyright 2009 Red Hat, Inc.
+ ~ Red Hat licenses this file to you under the Apache License, version
+ ~ 2.0 (the "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ ~ implied. See the License for the specific language governing
+ ~ permissions and limitations under the License.
+ -->
+
+<configuration xmlns="urn:hornetq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd">
+ <!--the connection factory used by the example-->
+ <connection-factory name="ConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="netty-connector"/>
+ </connectors>
+ <entries>
+ <entry name="ConnectionFactory"/>
+ </entries>
+
+ <ha>true</ha>
+ <!-- Pause 1 second between connect attempts -->
+ <retry-interval>1000</retry-interval>
+
+ <!-- Multiply subsequent reconnect pauses by this multiplier. This can be used to
+ implement an exponential back-off. For our purposes we just set to 1.0 so each reconnect
+ pause is the same length -->
+ <retry-interval-multiplier>1.0</retry-interval-multiplier>
+
+ <!-- Try reconnecting an unlimited number of times (-1 means "unlimited") -->
+ <reconnect-attempts>-1</reconnect-attempts>
+
+ </connection-factory>
+
+ <!--the queue used by the example-->
+ <queue name="exampleQueue">
+ <entry name="/queue/exampleQueue"/>
+ </queue>
+
+</configuration>
\ No newline at end of file
Copied: trunk/examples/jms/clustered-static-discovery/server2/hornetq-users.xml (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/hornetq-users.xml)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server2/hornetq-users.xml (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server2/hornetq-users.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,7 @@
+<configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd">
+ <!-- the default user. this is used where username is null-->
+ <defaultuser name="guest" password="guest">
+ <role name="guest"/>
+ </defaultuser>
+</configuration>
\ No newline at end of file
Copied: trunk/examples/jms/clustered-static-discovery/server2/jndi.properties (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/jndi.properties)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server2/jndi.properties (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server2/jndi.properties 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,15 @@
+#
+# Copyright 2009 Red Hat, Inc.
+# Red Hat licenses this file to you under the Apache License, version
+# 2.0 (the "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
\ No newline at end of file
Copied: trunk/examples/jms/clustered-static-discovery/server3/client-jndi.properties (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/client-jndi.properties)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server3/client-jndi.properties (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server3/client-jndi.properties 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,16 @@
+#
+# Copyright 2009 Red Hat, Inc.
+# Red Hat licenses this file to you under the Apache License, version
+# 2.0 (the "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+java.naming.provider.url=jnp://localhost:4099
+java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
Copied: trunk/examples/jms/clustered-static-discovery/server3/hornetq-beans.xml (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/hornetq-beans.xml)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server3/hornetq-beans.xml (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server3/hornetq-beans.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Copyright 2009 Red Hat, Inc.
+ ~ Red Hat licenses this file to you under the Apache License, version
+ ~ 2.0 (the "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ ~ implied. See the License for the specific language governing
+ ~ permissions and limitations under the License.
+ -->
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="Naming" class="org.jnp.server.NamingBeanImpl"/>
+
+ <!-- JNDI server. Disable this if you don't want JNDI -->
+ <bean name="JNDIServer" class="org.jnp.server.Main">
+ <property name="namingInfo">
+ <inject bean="Naming"/>
+ </property>
+ <property name="port">4099</property>
+ <property name="bindAddress">localhost</property>
+ <property name="rmiPort">4098</property>
+ <property name="rmiBindAddress">localhost</property>
+ </bean>
+
+ <!-- MBean server -->
+ <bean name="MBeanServer" class="javax.management.MBeanServer">
+ <constructor factoryClass="java.lang.management.ManagementFactory"
+ factoryMethod="getPlatformMBeanServer"/>
+ </bean>
+
+ <!-- The core configuration -->
+ <bean name="Configuration" class="org.hornetq.core.config.impl.FileConfiguration"/>
+
+ <!-- The security manager -->
+ <bean name="HornetQSecurityManager" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl">
+ <start ignored="true"/>
+ <stop ignored="true"/>
+ </bean>
+
+ <!-- The core server -->
+ <bean name="HornetQServer" class="org.hornetq.core.server.impl.HornetQServerImpl">
+ <constructor>
+ <parameter>
+ <inject bean="Configuration"/>
+ </parameter>
+ <parameter>
+ <inject bean="MBeanServer"/>
+ </parameter>
+ <parameter>
+ <inject bean="HornetQSecurityManager"/>
+ </parameter>
+ </constructor>
+ <start ignored="true"/>
+ <stop ignored="true"/>
+ </bean>
+
+ <!-- The JMS server -->
+ <bean name="JMSServerManager" class="org.hornetq.jms.server.impl.JMSServerManagerImpl">
+ <constructor>
+ <parameter>
+ <inject bean="HornetQServer"/>
+ </parameter>
+ </constructor>
+ </bean>
+
+</deployment>
Copied: trunk/examples/jms/clustered-static-discovery/server3/hornetq-configuration.xml (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/hornetq-configuration.xml)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server3/hornetq-configuration.xml (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server3/hornetq-configuration.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,69 @@
+<!--
+ ~ Copyright 2009 Red Hat, Inc.
+ ~ Red Hat licenses this file to you under the Apache License, version
+ ~ 2.0 (the "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ ~ implied. See the License for the specific language governing
+ ~ permissions and limitations under the License.
+ -->
+
+<configuration xmlns="urn:hornetq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd">
+ <clustered>true</clustered>
+
+ <!-- Connectors -->
+ <connectors>
+ <connector name="netty-connector">
+ <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
+ <param key="port" value="5448"/>
+ </connector>
+ <!-- connector to the server0 -->
+ <connector name="server0-connector">
+ <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
+ <param key="port" value="5445"/>
+ </connector>
+ </connectors>
+
+ <!-- Acceptors -->
+ <acceptors>
+ <acceptor name="netty-acceptor">
+ <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
+ <param key="port" value="5448"/>
+ </acceptor>
+ </acceptors>
+
+ <!-- Clustering configuration -->
+ <cluster-connections>
+ <cluster-connection name="my-cluster">
+ <address>jms</address>
+ <connector-ref>netty-connector</connector-ref>
+ <retry-interval>500</retry-interval>
+ <use-duplicate-detection>true</use-duplicate-detection>
+ <forward-when-no-consumers>true</forward-when-no-consumers>
+ <max-hops>1</max-hops>
+ <static-connectors allow-direct-connections-only="false">
+ <connector-ref>server0-connector</connector-ref>
+ </static-connectors>
+ </cluster-connection>
+ </cluster-connections>
+
+ <!-- Other config -->
+
+ <security-settings>
+ <!--security for example queue-->
+ <security-setting match="jms.queue.exampleQueue">
+ <permission type="createDurableQueue" roles="guest"/>
+ <permission type="deleteDurableQueue" roles="guest"/>
+ <permission type="createNonDurableQueue" roles="guest"/>
+ <permission type="deleteNonDurableQueue" roles="guest"/>
+ <permission type="consume" roles="guest"/>
+ <permission type="send" roles="guest"/>
+ </security-setting>
+ </security-settings>
+
+</configuration>
Copied: trunk/examples/jms/clustered-static-discovery/server3/hornetq-jms.xml (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/hornetq-jms.xml)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server3/hornetq-jms.xml (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server3/hornetq-jms.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,45 @@
+<!--
+ ~ Copyright 2009 Red Hat, Inc.
+ ~ Red Hat licenses this file to you under the Apache License, version
+ ~ 2.0 (the "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ ~ implied. See the License for the specific language governing
+ ~ permissions and limitations under the License.
+ -->
+
+<configuration xmlns="urn:hornetq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd">
+ <!--the connection factory used by the example-->
+ <connection-factory name="ConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="netty-connector"/>
+ </connectors>
+ <entries>
+ <entry name="ConnectionFactory"/>
+ </entries>
+
+ <ha>true</ha>
+ <!-- Pause 1 second between connect attempts -->
+ <retry-interval>1000</retry-interval>
+
+ <!-- Multiply subsequent reconnect pauses by this multiplier. This can be used to
+ implement an exponential back-off. For our purposes we just set to 1.0 so each reconnect
+ pause is the same length -->
+ <retry-interval-multiplier>1.0</retry-interval-multiplier>
+
+ <!-- Try reconnecting an unlimited number of times (-1 means "unlimited") -->
+ <reconnect-attempts>-1</reconnect-attempts>
+
+ </connection-factory>
+
+ <!--the queue used by the example-->
+ <queue name="exampleQueue">
+ <entry name="/queue/exampleQueue"/>
+ </queue>
+
+</configuration>
\ No newline at end of file
Copied: trunk/examples/jms/clustered-static-discovery/server3/hornetq-users.xml (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/hornetq-users.xml)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server3/hornetq-users.xml (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server3/hornetq-users.xml 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,7 @@
+<configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd">
+ <!-- the default user. this is used where username is null-->
+ <defaultuser name="guest" password="guest">
+ <role name="guest"/>
+ </defaultuser>
+</configuration>
\ No newline at end of file
Copied: trunk/examples/jms/clustered-static-discovery/server3/jndi.properties (from rev 10019, trunk/examples/jms/clustered-static-discovery/server1/jndi.properties)
===================================================================
--- trunk/examples/jms/clustered-static-discovery/server3/jndi.properties (rev 0)
+++ trunk/examples/jms/clustered-static-discovery/server3/jndi.properties 2010-12-09 16:47:56 UTC (rev 10021)
@@ -0,0 +1,2 @@
+java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
\ No newline at end of file
Modified: trunk/examples/jms/clustered-static-discovery/src/org/hornetq/jms/example/StaticClusteredQueueExample.java
===================================================================
--- trunk/examples/jms/clustered-static-discovery/src/org/hornetq/jms/example/StaticClusteredQueueExample.java 2010-12-09 15:01:09 UTC (rev 10020)
+++ trunk/examples/jms/clustered-static-discovery/src/org/hornetq/jms/example/StaticClusteredQueueExample.java 2010-12-09 16:47:56 UTC (rev 10021)
@@ -39,18 +39,22 @@
@Override
public boolean runExample() throws Exception
{
+ Connection initialConnection = null;
+
Connection connection0 = null;
Connection connection1 = null;
+ Connection connection2 = null;
+
+ Connection connection3 = null;
+
InitialContext ic0 = null;
- InitialContext ic1 = null;
-
try
{
// Step 1. Get an initial context for looking up JNDI from server 0
- ic0 = getContext(0);
+ ic0 = getContext(3);
// Step 2. Look-up the JMS Queue object from JNDI
Queue queue = (Queue)ic0.lookup("/queue/exampleQueue");
@@ -58,42 +62,62 @@
// Step 3. Look-up a JMS Connection Factory object from JNDI on server 0
ConnectionFactory cf0 = (ConnectionFactory)ic0.lookup("/ConnectionFactory");
- // Step 4. Get an initial context for looking up JNDI from server 1
- ic1 = getContext(1);
+ //grab an initial connection and wait, in reality you wouldn't do it this way but since we want to ensure an
+ // equal load balance we do this and then create 4 connections round robined
+ initialConnection = cf0.createConnection();
- // Step 5. Look-up a JMS Connection Factory object from JNDI on server 1
- ConnectionFactory cf1 = (ConnectionFactory)ic1.lookup("/ConnectionFactory");
-
+ Thread.sleep(2000);
// Step 6. We create a JMS Connection connection0 which is a connection to server 0
connection0 = cf0.createConnection();
// Step 7. We create a JMS Connection connection1 which is a connection to server 1
- connection1 = cf1.createConnection();
+ connection1 = cf0.createConnection();
+ // Step 6. We create a JMS Connection connection0 which is a connection to server 0
+ connection2 = cf0.createConnection();
+
+ // Step 7. We create a JMS Connection connection1 which is a connection to server 1
+ connection3 = cf0.createConnection();
+
// Step 8. We create a JMS Session on server 0
Session session0 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Step 9. We create a JMS Session on server 1
Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Step 8. We create a JMS Session on server 0
+ Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Step 9. We create a JMS Session on server 1
+ Session session3 = connection3.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
// Step 10. We start the connections to ensure delivery occurs on them
connection0.start();
connection1.start();
+ connection2.start();
+
+ connection3.start();
+
// Step 11. We create JMS MessageConsumer objects on server 0 and server 1
MessageConsumer consumer0 = session0.createConsumer(queue);
MessageConsumer consumer1 = session1.createConsumer(queue);
- Thread.sleep(1000);
+ MessageConsumer consumer2 = session2.createConsumer(queue);
- // Step 12. We create a JMS MessageProducer object on server 0
- MessageProducer producer = session0.createProducer(queue);
+ MessageConsumer consumer3 = session3.createConsumer(queue);
+ Thread.sleep(2000);
+
+ // Step 12. We create a JMS MessageProducer object on server 3
+ MessageProducer producer = session3.createProducer(queue);
+
// Step 13. We send some messages to server 0
- final int numMessages = 10;
+ final int numMessages = 20;
for (int i = 0; i < numMessages; i++)
{
@@ -103,21 +127,37 @@
System.out.println("Sent message: " + message.getText());
}
-
+ Thread.sleep(2000);
// Step 14. We now consume those messages on *both* server 0 and server 1.
// We note the messages have been distributed between servers in a round robin fashion
// JMS Queues implement point-to-point message where each message is only ever consumed by a
// maximum of one consumer
+ int con0Node = getServer(connection0);
+ int con1Node = getServer(connection1);
+ int con2Node = getServer(connection2);
+ int con3Node = getServer(connection3);
- for (int i = 0; i < numMessages; i += 2)
+ if(con0Node + con1Node + con2Node + con3Node != 6)
{
+ return false;
+ }
+ for (int i = 0; i < numMessages; i += 4)
+ {
TextMessage message0 = (TextMessage)consumer0.receive(5000);
- System.out.println("Got message: " + message0.getText() + " from node 0");
+ System.out.println("Got message: " + message0.getText() + " from node " + con0Node);
TextMessage message1 = (TextMessage)consumer1.receive(5000);
- System.out.println("Got message: " + message1.getText() + " from node 1");
+ System.out.println("Got message: " + message1.getText() + " from node " + con1Node);
+
+ TextMessage message2 = (TextMessage)consumer2.receive(5000);
+
+ System.out.println("Got message: " + message2.getText() + " from node " + con2Node);
+
+ TextMessage message3 = (TextMessage)consumer3.receive(5000);
+
+ System.out.println("Got message: " + message3.getText() + " from node " + con3Node);
}
return true;
@@ -126,6 +166,11 @@
{
// Step 15. Be sure to close our resources!
+ if (initialConnection != null)
+ {
+ initialConnection.close();
+ }
+
if (connection0 != null)
{
connection0.close();
@@ -136,15 +181,20 @@
connection1.close();
}
- if (ic0 != null)
+ if (connection2 != null)
{
- ic0.close();
+ connection2.close();
}
- if (ic1 != null)
+ if (connection3 != null)
{
- ic1.close();
+ connection3.close();
}
+
+ if (ic0 != null)
+ {
+ ic0.close();
+ }
}
}
15 years, 5 months
JBoss hornetq SVN: r10020 - in trunk: tests/src/org/hornetq/tests/integration/client and 1 other directory.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-12-09 10:01:09 -0500 (Thu, 09 Dec 2010)
New Revision: 10020
Modified:
trunk/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java
trunk/tests/src/org/hornetq/tests/integration/client/ConsumerWindowSizeTest.java
Log:
HORNETQ-538 - Fixing issue with flow control
Modified: trunk/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java 2010-12-09 08:23:56 UTC (rev 10019)
+++ trunk/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java 2010-12-09 15:01:09 UTC (rev 10020)
@@ -654,6 +654,7 @@
*/
public void flowControl(final int messageBytes, final boolean discountSlowConsumer) throws HornetQException
{
+ System.err.println("Flow Control being called with clientWindowsize = " + clientWindowSize + " flowControl = " + messageBytes);
if (clientWindowSize >= 0)
{
creditsToSend += messageBytes;
@@ -675,7 +676,10 @@
creditsToSend = 0;
- sendCredits(credits);
+ if (credits > 0)
+ {
+ sendCredits(credits);
+ }
}
else
{
@@ -688,7 +692,10 @@
creditsToSend = 0;
- sendCredits(credits);
+ if (credits > 0)
+ {
+ sendCredits(credits);
+ }
}
}
}
Modified: trunk/tests/src/org/hornetq/tests/integration/client/ConsumerWindowSizeTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/client/ConsumerWindowSizeTest.java 2010-12-09 08:23:56 UTC (rev 10019)
+++ trunk/tests/src/org/hornetq/tests/integration/client/ConsumerWindowSizeTest.java 2010-12-09 15:01:09 UTC (rev 10020)
@@ -12,6 +12,8 @@
*/
package org.hornetq.tests.integration.client;
+import java.io.IOException;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.CountDownLatch;
@@ -19,9 +21,14 @@
import junit.framework.Assert;
-import org.hornetq.api.core.HornetQException;
import org.hornetq.api.core.SimpleString;
-import org.hornetq.api.core.client.*;
+import org.hornetq.api.core.client.ClientConsumer;
+import org.hornetq.api.core.client.ClientMessage;
+import org.hornetq.api.core.client.ClientProducer;
+import org.hornetq.api.core.client.ClientSession;
+import org.hornetq.api.core.client.ClientSessionFactory;
+import org.hornetq.api.core.client.MessageHandler;
+import org.hornetq.api.core.client.ServerLocator;
import org.hornetq.core.client.impl.ClientConsumerInternal;
import org.hornetq.core.logging.Logger;
import org.hornetq.core.postoffice.Binding;
@@ -67,8 +74,7 @@
protected void tearDown() throws Exception
{
locator.close();
-
-
+
super.tearDown();
}
@@ -86,7 +92,6 @@
return encodeSize;
}
-
// https://jira.jboss.org/jira/browse/HORNETQ-385
public void testReceiveImmediateWithZeroWindow() throws Exception
{
@@ -99,7 +104,6 @@
ClientSessionFactory sf = locator.createSessionFactory();
-
ClientSession session = sf.createSession(false, false, false);
session.createQueue("testWindow", "testWindow", true);
session.close();
@@ -151,7 +155,7 @@
}
}
-
+
// https://jira.jboss.org/jira/browse/HORNETQ-385
public void testReceiveImmediateWithZeroWindow2() throws Exception
{
@@ -167,12 +171,12 @@
ClientSession session = sf.createSession(false, false, false);
session.createQueue("testReceive", "testReceive", true);
session.close();
-
+
ClientSession sessionProd = sf.createSession(false, false);
ClientMessage msg = sessionProd.createMessage(true);
msg.putStringProperty("hello", "world");
ClientProducer prod = sessionProd.createProducer("testReceive");
-
+
prod.send(msg);
sessionProd.commit();
@@ -183,7 +187,7 @@
Thread.sleep(1000);
ClientMessage message = null;
message = consumer.receiveImmediate();
- //message = consumer.receive(1000); // the test will pass if used receive(1000) instead of receiveImmediate
+ // message = consumer.receive(1000); // the test will pass if used receive(1000) instead of receiveImmediate
assertNotNull(message);
System.out.println(message.getStringProperty("hello"));
message.acknowledge();
@@ -195,7 +199,7 @@
assertNotNull(message);
System.out.println(message.getStringProperty("hello"));
message.acknowledge();
-
+
session.close();
session1.close();
sessionProd.close();
@@ -206,7 +210,7 @@
server.stop();
}
}
-
+
// https://jira.jboss.org/jira/browse/HORNETQ-385
public void testReceiveImmediateWithZeroWindow3() throws Exception
{
@@ -219,7 +223,6 @@
ClientSessionFactory sf = locator.createSessionFactory();
-
ClientSession session = sf.createSession(false, false, false);
session.createQueue("testWindow", "testWindow", true);
session.close();
@@ -271,7 +274,7 @@
}
}
-
+
public void testReceiveImmediateWithZeroWindow4() throws Exception
{
HornetQServer server = createServer(false, isNetty());
@@ -334,8 +337,7 @@
}
}
-
-
+
/*
* tests send window size. we do this by having 2 receivers on the q. since we roundrobin the consumer for delivery we
* know if consumer 1 has received n messages then consumer 2 must have also have received n messages or at least up
@@ -634,17 +636,15 @@
server.start();
-
locator.setConsumerWindowSize(0);
-
if (largeMessages)
{
locator.setMinLargeMessageSize(100);
}
ClientSessionFactory sf = locator.createSessionFactory();
-
+
session1 = sf.createSession(false, true, true);
session2 = sf.createSession(false, true, true);
@@ -682,7 +682,7 @@
String str = getTextMessage(msg);
Assert.assertEquals("Msg" + i, str);
-
+
log.info("got msg " + str);
msg.acknowledge();
@@ -697,12 +697,11 @@
ClientMessage msg = cons2.receive(1000);
Assert.assertNotNull("expected message at i = " + i, msg);
-
+
String str = getTextMessage(msg);
-
+
log.info("got msg " + str);
-
Assert.assertEquals("Msg" + i, str);
msg.acknowledge();
@@ -810,6 +809,98 @@
}
}
+ public void testSaveBuffersOnLargeMessage() throws Exception
+ {
+ HornetQServer server = createServer(false, isNetty());
+
+ ClientSession session1 = null;
+
+ try
+ {
+ final int numberOfMessages = 10;
+
+ server.start();
+
+ locator.setConsumerWindowSize(0);
+
+ locator.setMinLargeMessageSize(100);
+
+ ClientSessionFactory sf = locator.createSessionFactory();
+
+ session1 = sf.createSession(false, true, true);
+
+ session1.start();
+
+ SimpleString ADDRESS = new SimpleString("some-queue");
+
+ session1.createQueue(ADDRESS, ADDRESS, true);
+
+ ClientConsumerInternal cons1 = (ClientConsumerInternal)session1.createConsumer(ADDRESS);
+
+ // Note we make sure we send the messages *before* cons2 is created
+
+ ClientProducer prod = session1.createProducer(ADDRESS);
+
+ for (int i = 0; i < numberOfMessages; i++)
+ {
+ ClientMessage msg = session1.createMessage(true);
+ msg.getBodyBuffer().writeBytes(new byte[600]);
+ prod.send(msg);
+ }
+
+ for (int i = 0; i < numberOfMessages; i++)
+ {
+ ClientMessage msg = cons1.receive(1000);
+ Assert.assertNotNull("expected message at i = " + i, msg);
+
+ msg.saveToOutputStream(new FakeOutputStream());
+
+ msg.acknowledge();
+
+ Assert.assertEquals("A slow consumer shouldn't buffer anything on the client side!",
+ 0,
+ cons1.getBufferSize());
+ }
+
+ session1.close(); // just to make sure everything is flushed and no pending packets on the sending buffer, or
+ session1.close();
+ session1 = null;
+ Assert.assertEquals(0, getMessageCount(server, ADDRESS.toString()));
+
+ }
+ finally
+ {
+ try
+ {
+ if (session1 != null)
+ {
+ session1.close();
+ }
+ }
+ catch (Exception ignored)
+ {
+ }
+
+ if (server.isStarted())
+ {
+ server.stop();
+ }
+ }
+ }
+
+ class FakeOutputStream extends OutputStream
+ {
+
+ /* (non-Javadoc)
+ * @see java.io.OutputStream#write(int)
+ */
+ @Override
+ public void write(int b) throws IOException
+ {
+ }
+
+ }
+
public void testSlowConsumerOnMessageHandlerNoBuffers() throws Exception
{
internalTestSlowConsumerOnMessageHandlerNoBuffers(false);
@@ -842,7 +933,7 @@
}
ClientSessionFactory sf = locator.createSessionFactory();
-
+
session = sf.createSession(false, true, true);
SimpleString ADDRESS = new SimpleString("some-queue");
@@ -1047,7 +1138,7 @@
{
ConsumerWindowSizeTest.log.trace("Received message " + str);
}
-
+
ConsumerWindowSizeTest.log.info("Received message " + str);
failed = failed || !str.equals("Msg" + count);
@@ -1093,7 +1184,7 @@
Assert.assertTrue(latchReceived.await(TIMEOUT, TimeUnit.SECONDS));
log.info("bs " + consReceiveOneAndHold.getBufferSize());
-
+
long timeout = System.currentTimeMillis() + 1000 * TIMEOUT;
while (consReceiveOneAndHold.getBufferSize() == 0 && System.currentTimeMillis() < timeout)
{
15 years, 5 months
JBoss hornetq SVN: r10019 - trunk/examples/jms.
by do-not-reply@jboss.org
Author: ataylor
Date: 2010-12-09 03:23:56 -0500 (Thu, 09 Dec 2010)
New Revision: 10019
Added:
trunk/examples/jms/clustered-static-discovery/
Removed:
trunk/examples/jms/static-clustered-queue/
Log:
renamed example
Copied: trunk/examples/jms/clustered-static-discovery (from rev 10018, trunk/examples/jms/static-clustered-queue)
15 years, 5 months
JBoss hornetq SVN: r10018 - in trunk/src/main/org/hornetq/core: protocol/core/impl/wireformat and 1 other directory.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-12-08 14:26:11 -0500 (Wed, 08 Dec 2010)
New Revision: 10018
Modified:
trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageImpl.java
trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageInternal.java
trunk/src/main/org/hornetq/core/protocol/core/impl/wireformat/SessionReceiveLargeMessage.java
Log:
tweaks and test fixes
Modified: trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageImpl.java 2010-12-08 17:21:29 UTC (rev 10017)
+++ trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageImpl.java 2010-12-08 19:26:11 UTC (rev 10018)
@@ -39,7 +39,7 @@
// Used only when receiving large messages
private LargeMessageController largeMessageController;
- private int largeMessageSize;
+ private long largeMessageSize;
// Static --------------------------------------------------------
@@ -48,7 +48,7 @@
/**
* @return the largeMessageSize
*/
- public int getLargeMessageSize()
+ public long getLargeMessageSize()
{
return largeMessageSize;
}
@@ -56,7 +56,7 @@
/**
* @param largeMessageSize the largeMessageSize to set
*/
- public void setLargeMessageSize(int largeMessageSize)
+ public void setLargeMessageSize(long largeMessageSize)
{
this.largeMessageSize = largeMessageSize;
}
@@ -184,8 +184,14 @@
{
if (bodyBuffer == null)
{
- createBody(this.largeMessageSize + BODY_OFFSET);
+ long bodySize = this.largeMessageSize + BODY_OFFSET;
+ if (bodySize > Integer.MAX_VALUE)
+ {
+ bodySize = Integer.MAX_VALUE;
+ }
+ createBody((int)bodySize);
+
bodyBuffer = new ResetLimitWrappedHornetQBuffer(BODY_OFFSET, buffer, this);
try
@@ -217,7 +223,7 @@
@Override
public void write(int b) throws IOException
{
- bufferOut.writeByte((byte)(b & Byte.MAX_VALUE));
+ bufferOut.writeByte((byte)(b & 0xff));
}
}
Modified: trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageInternal.java
===================================================================
--- trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageInternal.java 2010-12-08 17:21:29 UTC (rev 10017)
+++ trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageInternal.java 2010-12-08 19:26:11 UTC (rev 10018)
@@ -28,7 +28,7 @@
LargeMessageController getLargeMessageController();
- void setLargeMessageSize(int size);
+ void setLargeMessageSize(long size);
- int getLargeMessageSize();
+ long getLargeMessageSize();
}
Modified: trunk/src/main/org/hornetq/core/protocol/core/impl/wireformat/SessionReceiveLargeMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/protocol/core/impl/wireformat/SessionReceiveLargeMessage.java 2010-12-08 17:21:29 UTC (rev 10017)
+++ trunk/src/main/org/hornetq/core/protocol/core/impl/wireformat/SessionReceiveLargeMessage.java 2010-12-08 19:26:11 UTC (rev 10018)
@@ -15,6 +15,7 @@
import org.hornetq.api.core.HornetQBuffer;
import org.hornetq.core.client.impl.ClientLargeMessageImpl;
+import org.hornetq.core.client.impl.ClientLargeMessageInternal;
import org.hornetq.core.logging.Logger;
import org.hornetq.core.message.impl.MessageInternal;
import org.hornetq.core.protocol.core.impl.PacketImpl;
@@ -101,6 +102,7 @@
deliveryCount = buffer.readInt();
largeMessageSize = buffer.readLong();
message.decodeHeadersAndProperties(buffer);
+ ((ClientLargeMessageInternal)message).setLargeMessageSize(largeMessageSize);
}
}
15 years, 5 months
JBoss hornetq SVN: r10017 - in trunk: src/main/org/hornetq/core/message/impl and 3 other directories.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-12-08 12:21:29 -0500 (Wed, 08 Dec 2010)
New Revision: 10017
Added:
trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageImpl.java
trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageInternal.java
Modified:
trunk/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java
trunk/src/main/org/hornetq/core/client/impl/ClientMessageImpl.java
trunk/src/main/org/hornetq/core/client/impl/ClientMessageInternal.java
trunk/src/main/org/hornetq/core/client/impl/CompressedLargeMessageControllerImpl.java
trunk/src/main/org/hornetq/core/message/impl/MessageImpl.java
trunk/src/main/org/hornetq/core/protocol/core/impl/wireformat/SessionReceiveLargeMessage.java
trunk/tests/src/org/hornetq/tests/integration/client/LargeMessageCompressTest.java
trunk/tests/src/org/hornetq/tests/integration/client/LargeMessageTest.java
trunk/tests/src/org/hornetq/tests/integration/largemessage/LargeMessageTestBase.java
Log:
HORNETQ-538 - Large Message will reconstruct the buffer on client
Modified: trunk/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java 2010-12-08 15:09:06 UTC (rev 10016)
+++ trunk/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -166,7 +166,7 @@
if (largeMessageReceived != null)
{
// Check if there are pending packets to be received
- largeMessageReceived.discardLargeBody();
+ largeMessageReceived.discardBody();
largeMessageReceived = null;
}
@@ -280,7 +280,7 @@
if (expired)
{
- m.discardLargeBody();
+ m.discardBody();
session.expire(id, m.getMessageID());
@@ -538,12 +538,10 @@
flowControl(packet.getPacketSize(), false);
- ClientMessageInternal currentChunkMessage = (ClientMessageInternal)packet.getLargeMessage();
+ ClientLargeMessageInternal currentChunkMessage = (ClientLargeMessageInternal)packet.getLargeMessage();
currentChunkMessage.setDeliveryCount(packet.getDeliveryCount());
- currentChunkMessage.setLargeMessage(true);
-
File largeMessageCache = null;
if (session.isCacheLargeMessageClient())
@@ -557,11 +555,11 @@
if (currentChunkMessage.isCompressed())
{
- currentChunkMessage.setBuffer(new CompressedLargeMessageControllerImpl(currentLargeMessageController));
+ currentChunkMessage.setLargeMessageController(new CompressedLargeMessageControllerImpl(currentLargeMessageController));
}
else
{
- currentChunkMessage.setBuffer(currentLargeMessageController);
+ currentChunkMessage.setLargeMessageController(currentLargeMessageController);
}
currentChunkMessage.setFlowControlSize(0);
@@ -852,7 +850,7 @@
if (message.isLargeMessage())
{
- message.discardLargeBody();
+ message.discardBody();
}
}
else
Added: trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageImpl.java (rev 0)
+++ trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageImpl.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.client.impl;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.hornetq.api.core.HornetQBuffer;
+import org.hornetq.api.core.HornetQException;
+import org.hornetq.core.buffers.impl.ResetLimitWrappedHornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * ClientLargeMessageImpl is only created when receiving large messages. At the time of sending a regular Message is sent as we won't know the message is considered large
+ * until the buffer is filled up or the user set a streaming.
+ *
+ * @author clebertsuconic
+ *
+ *
+ */
+public class ClientLargeMessageImpl extends ClientMessageImpl implements ClientLargeMessageInternal
+{
+
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+
+ // Used only when receiving large messages
+ private LargeMessageController largeMessageController;
+
+ private int largeMessageSize;
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ /**
+ * @return the largeMessageSize
+ */
+ public int getLargeMessageSize()
+ {
+ return largeMessageSize;
+ }
+
+ /**
+ * @param largeMessageSize the largeMessageSize to set
+ */
+ public void setLargeMessageSize(int largeMessageSize)
+ {
+ this.largeMessageSize = largeMessageSize;
+ }
+
+ // we only need this constructor as this is only used at decoding large messages on client
+ public ClientLargeMessageImpl()
+ {
+ super();
+ }
+
+ // Public --------------------------------------------------------
+
+ public int getEncodeSize()
+ {
+ if (bodyBuffer != null)
+ {
+ return super.getEncodeSize();
+ }
+ else
+ {
+ return DataConstants.SIZE_INT + DataConstants.SIZE_INT + getHeadersAndPropertiesEncodeSize();
+ }
+ }
+
+ /**
+ * @return the largeMessage
+ */
+ public boolean isLargeMessage()
+ {
+ return true;
+ }
+
+ public void setLargeMessageController(final LargeMessageController controller)
+ {
+ largeMessageController = controller;
+ }
+
+ public HornetQBuffer getBodyBuffer()
+ {
+ checkBuffer();
+
+ return bodyBuffer;
+ }
+
+
+ public int getBodySize()
+ {
+ checkBuffer();
+ return buffer.writerIndex() - buffer.readerIndex();
+ }
+
+
+
+ public LargeMessageController getLargeMessageController()
+ {
+ return largeMessageController;
+ }
+
+ /* (non-Javadoc)
+ * @see org.hornetq.api.core.client.ClientMessage#saveToOutputStream(java.io.OutputStream)
+ */
+ public void saveToOutputStream(final OutputStream out) throws HornetQException
+ {
+ if (bodyBuffer != null)
+ {
+ // The body was rebuilt on the client, so we need to behave as a regular message on this case
+ super.saveToOutputStream(out);
+ }
+ else
+ {
+ largeMessageController.saveBuffer(out);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.hornetq.api.core.client.ClientMessage#setOutputStream(java.io.OutputStream)
+ */
+ public void setOutputStream(final OutputStream out) throws HornetQException
+ {
+ if (bodyBuffer != null)
+ {
+ super.setOutputStream(out);
+ }
+ else
+ {
+ largeMessageController.setOutputStream(out);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.hornetq.api.core.client.ClientMessage#waitOutputStreamCompletion()
+ */
+ public boolean waitOutputStreamCompletion(final long timeMilliseconds) throws HornetQException
+ {
+ if (bodyBuffer != null)
+ {
+ return super.waitOutputStreamCompletion(timeMilliseconds);
+ }
+ else
+ {
+ return largeMessageController.waitCompletion(timeMilliseconds);
+ }
+ }
+
+ public void discardBody()
+ {
+ if (bodyBuffer != null)
+ {
+ super.discardBody();
+ }
+ else
+ {
+ largeMessageController.discardUnusedPackets();
+ }
+ }
+
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ // Private -------------------------------------------------------
+
+ private void checkBuffer()
+ {
+ if (bodyBuffer == null)
+ {
+ createBody(this.largeMessageSize + BODY_OFFSET);
+
+ bodyBuffer = new ResetLimitWrappedHornetQBuffer(BODY_OFFSET, buffer, this);
+
+ try
+ {
+ largeMessageController.saveBuffer(new HornetQOutputStream(bodyBuffer));
+ }
+ catch (HornetQException e)
+ {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+ }
+
+
+ // Inner classes -------------------------------------------------
+
+ protected class HornetQOutputStream extends OutputStream
+ {
+ HornetQBuffer bufferOut;
+
+ HornetQOutputStream(HornetQBuffer out)
+ {
+ this.bufferOut = out;
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.OutputStream#write(int)
+ */
+ @Override
+ public void write(int b) throws IOException
+ {
+ bufferOut.writeByte((byte)(b & Byte.MAX_VALUE));
+ }
+
+ }
+
+}
Added: trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageInternal.java
===================================================================
--- trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageInternal.java (rev 0)
+++ trunk/src/main/org/hornetq/core/client/impl/ClientLargeMessageInternal.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.client.impl;
+
+
+/**
+ * A ClientLargeMessageInternal
+ *
+ * @author clebertsuconic
+ *
+ *
+ */
+public interface ClientLargeMessageInternal extends ClientMessageInternal
+{
+
+ void setLargeMessageController(LargeMessageController controller);
+
+ LargeMessageController getLargeMessageController();
+
+ void setLargeMessageSize(int size);
+
+ int getLargeMessageSize();
+}
Modified: trunk/src/main/org/hornetq/core/client/impl/ClientMessageImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/client/impl/ClientMessageImpl.java 2010-12-08 15:09:06 UTC (rev 10016)
+++ trunk/src/main/org/hornetq/core/client/impl/ClientMessageImpl.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -46,11 +46,6 @@
private ClientConsumerInternal consumer;
- private boolean largeMessage;
-
- // Used only when receiving large messages
- private LargeMessageController largeMessageController;
-
private int flowControlSize = -1;
/** Used on LargeMessages only */
@@ -80,7 +75,7 @@
{
return false;
}
-
+
public void onReceipt(final ClientConsumerInternal consumer)
{
this.consumer = consumer;
@@ -123,22 +118,14 @@
*/
public boolean isLargeMessage()
{
- return largeMessage;
+ return false;
}
-
+
public boolean isCompressed()
{
return properties.getBooleanProperty(Message.HDR_LARGE_COMPRESSED);
}
- /**
- * @param largeMessage the largeMessage to set
- */
- public void setLargeMessage(final boolean largeMessage)
- {
- this.largeMessage = largeMessage;
- }
-
public int getBodySize()
{
return buffer.writerIndex() - buffer.readerIndex();
@@ -147,12 +134,7 @@
@Override
public String toString()
{
- return "ClientMessage[messageID=" + messageID +
- ", durable=" +
- durable +
- ", address=" +
- getAddress() +
- "]";
+ return "ClientMessage[messageID=" + messageID + ", durable=" + durable + ", address=" + getAddress() + "]";
}
/* (non-Javadoc)
@@ -160,24 +142,16 @@
*/
public void saveToOutputStream(final OutputStream out) throws HornetQException
{
- if (largeMessage)
+ try
{
- ((LargeMessageController)getWholeBuffer()).saveBuffer(out);
+ byte readBuffer[] = new byte[getBodySize()];
+ getBodyBuffer().readBytes(readBuffer);
+ out.write(readBuffer);
}
- else
+ catch (IOException e)
{
- try
- {
- byte readBuffer[] = new byte[getBodySize()];
- getBodyBuffer().readBytes(readBuffer);
- out.write(readBuffer);
- }
- catch (IOException e)
- {
- throw new HornetQException(HornetQException.LARGE_MESSAGE_ERROR_BODY, "Error saving the message body", e);
- }
+ throw new HornetQException(HornetQException.LARGE_MESSAGE_ERROR_BODY, "Error saving the message body", e);
}
-
}
/* (non-Javadoc)
@@ -185,15 +159,7 @@
*/
public void setOutputStream(final OutputStream out) throws HornetQException
{
- if (largeMessage)
- {
- ((LargeMessageController)getWholeBuffer()).setOutputStream(out);
- }
- else
- {
- saveToOutputStream(out);
- }
-
+ saveToOutputStream(out);
}
/* (non-Javadoc)
@@ -201,25 +167,14 @@
*/
public boolean waitOutputStreamCompletion(final long timeMilliseconds) throws HornetQException
{
- if (largeMessage)
- {
- return ((LargeMessageController)getWholeBuffer()).waitCompletion(timeMilliseconds);
- }
- else
- {
- return true;
- }
+ return true;
}
/* (non-Javadoc)
* @see org.hornetq.api.core.client.impl.ClientMessageInternal#discardLargeBody()
*/
- public void discardLargeBody()
+ public void discardBody()
{
- if (largeMessage)
- {
- ((LargeMessageController)getWholeBuffer()).discardUnusedPackets();
- }
}
/**
Modified: trunk/src/main/org/hornetq/core/client/impl/ClientMessageInternal.java
===================================================================
--- trunk/src/main/org/hornetq/core/client/impl/ClientMessageInternal.java 2010-12-08 15:09:06 UTC (rev 10016)
+++ trunk/src/main/org/hornetq/core/client/impl/ClientMessageInternal.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -36,12 +36,10 @@
void onReceipt(ClientConsumerInternal consumer);
- void setLargeMessage(boolean largeMessage);
-
/**
* Discard unused packets (used on large-message)
*/
- void discardLargeBody();
+ void discardBody();
void setBuffer(HornetQBuffer buffer);
Modified: trunk/src/main/org/hornetq/core/client/impl/CompressedLargeMessageControllerImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/client/impl/CompressedLargeMessageControllerImpl.java 2010-12-08 15:09:06 UTC (rev 10016)
+++ trunk/src/main/org/hornetq/core/client/impl/CompressedLargeMessageControllerImpl.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -423,8 +423,7 @@
public long getSize()
{
- // TODO
- return 0;
+ return this.bufferDelegate.getSize();
}
public void writerIndex(final int writerIndex)
Modified: trunk/src/main/org/hornetq/core/message/impl/MessageImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/message/impl/MessageImpl.java 2010-12-08 15:09:06 UTC (rev 10016)
+++ trunk/src/main/org/hornetq/core/message/impl/MessageImpl.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -262,14 +262,7 @@
{
if (bodyBuffer == null)
{
- if (buffer instanceof LargeMessageController == false)
- {
- bodyBuffer = new ResetLimitWrappedHornetQBuffer(BODY_OFFSET, buffer, this);
- }
- else
- {
- return buffer;
- }
+ bodyBuffer = new ResetLimitWrappedHornetQBuffer(BODY_OFFSET, buffer, this);
}
return bodyBuffer;
@@ -938,7 +931,7 @@
bufferValid = true;
}
- private void createBody(final int initialMessageBufferSize)
+ protected void createBody(final int initialMessageBufferSize)
{
buffer = HornetQBuffers.dynamicBuffer(initialMessageBufferSize);
Modified: trunk/src/main/org/hornetq/core/protocol/core/impl/wireformat/SessionReceiveLargeMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/protocol/core/impl/wireformat/SessionReceiveLargeMessage.java 2010-12-08 15:09:06 UTC (rev 10016)
+++ trunk/src/main/org/hornetq/core/protocol/core/impl/wireformat/SessionReceiveLargeMessage.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -14,7 +14,7 @@
package org.hornetq.core.protocol.core.impl.wireformat;
import org.hornetq.api.core.HornetQBuffer;
-import org.hornetq.core.client.impl.ClientMessageImpl;
+import org.hornetq.core.client.impl.ClientLargeMessageImpl;
import org.hornetq.core.logging.Logger;
import org.hornetq.core.message.impl.MessageInternal;
import org.hornetq.core.protocol.core.impl.PacketImpl;
@@ -43,7 +43,7 @@
public SessionReceiveLargeMessage()
{
super(PacketImpl.SESS_RECEIVE_LARGE_MSG);
- this.message = new ClientMessageImpl();
+ this.message = new ClientLargeMessageImpl();
}
public SessionReceiveLargeMessage(final long consumerID,
Modified: trunk/tests/src/org/hornetq/tests/integration/client/LargeMessageCompressTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/client/LargeMessageCompressTest.java 2010-12-08 15:09:06 UTC (rev 10016)
+++ trunk/tests/src/org/hornetq/tests/integration/client/LargeMessageCompressTest.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -277,32 +277,6 @@
}
- // TODO: Fix these tests on LargeMessageCompression
-
- public void testResendSmallStreamMessage() throws Exception
- {
- }
-
- public void testResendLargeStreamMessage() throws Exception
- {
- }
-
- public void testResendCachedSmallStreamMessage() throws Exception
- {
- }
-
- public void testResendCachedLargeStreamMessage() throws Exception
- {
- }
-
- public void testSimpleRollback() throws Exception
- {
- }
-
- public void testSimpleRollbackXA() throws Exception
- {
- }
-
public void testSendServerMessage() throws Exception
{
// doesn't make sense as compressed
Modified: trunk/tests/src/org/hornetq/tests/integration/client/LargeMessageTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/client/LargeMessageTest.java 2010-12-08 15:09:06 UTC (rev 10016)
+++ trunk/tests/src/org/hornetq/tests/integration/client/LargeMessageTest.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -841,6 +841,7 @@
public void internalTestResendMessage(final long messageSize) throws Exception
{
+ clearData();
ClientSession session = null;
try
@@ -879,19 +880,7 @@
producer2.send(msg1);
- boolean failed = false;
- try
- {
- producer2.send(msg1);
- }
- catch (Throwable e)
- {
- failed = true;
- }
-
- Assert.assertTrue("Exception expected", failed);
-
session.commit();
ClientMessage msg2 = consumer2.receive(10000);
@@ -2206,7 +2195,7 @@
Assert.assertNotNull(clientMessage);
- Assert.assertEquals(numberOfBytes, clientMessage.getBodyBuffer().writerIndex());
+ Assert.assertEquals(numberOfBytes, clientMessage.getBodySize());
clientMessage.acknowledge();
Modified: trunk/tests/src/org/hornetq/tests/integration/largemessage/LargeMessageTestBase.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/largemessage/LargeMessageTestBase.java 2010-12-08 15:09:06 UTC (rev 10016)
+++ trunk/tests/src/org/hornetq/tests/integration/largemessage/LargeMessageTestBase.java 2010-12-08 17:21:29 UTC (rev 10017)
@@ -432,9 +432,6 @@
((Integer)message.getObjectProperty(new SimpleString("counter-message"))).intValue());
}
- HornetQBuffer buffer = message.getBodyBuffer();
- buffer.resetReaderIndex();
-
if (useStreamOnConsume)
{
final AtomicLong bytesRead = new AtomicLong(0);
@@ -477,6 +474,9 @@
}
else
{
+ HornetQBuffer buffer = message.getBodyBuffer();
+ buffer.resetReaderIndex();
+
for (long b = 0; b < numberOfBytes; b++)
{
if (b % (1024l * 1024l) == 0l)
15 years, 5 months
JBoss hornetq SVN: r10016 - trunk/docs/user-manual/en.
by do-not-reply@jboss.org
Author: ataylor
Date: 2010-12-08 10:09:06 -0500 (Wed, 08 Dec 2010)
New Revision: 10016
Modified:
trunk/docs/user-manual/en/clusters.xml
Log:
updated the clusters chapter on using server discovery with UDP
Modified: trunk/docs/user-manual/en/clusters.xml
===================================================================
--- trunk/docs/user-manual/en/clusters.xml 2010-12-08 13:47:35 UTC (rev 10015)
+++ trunk/docs/user-manual/en/clusters.xml 2010-12-08 15:09:06 UTC (rev 10016)
@@ -45,250 +45,275 @@
</section>
<section id="clusters.server-discovery">
<title>Server discovery</title>
- <para>Server discovery is a mechanism by which servers can broadcast their connection
- settings across the network. This is useful for two purposes:</para>
+ <para>Server discovery is a mechanism by which servers can propagate their connection details to:</para>
<itemizedlist>
<listitem>
- <para>Discovery by messaging clients. A messaging client wants to be able to connect
+ <para>
+ Messaging clients. A messaging client wants to be able to connect
to the servers of the cluster without having specific knowledge of which servers
- in the cluster are up at any one time. Messaging clients
- <emphasis>can</emphasis> be initialised with an explicit list of the servers
- in a cluster, but this is not flexible or maintainable as servers are added or
- removed from the cluster.</para>
+ in the cluster are up at any one time.
+ </para>
</listitem>
<listitem>
- <para>Discovery by other servers. Servers in a cluster want to be able to create
+ <para>Other servers. Servers in a cluster want to be able to create
cluster connections to each other without having prior knowledge of all the
- other servers in the cluster. </para>
+ other servers in the cluster.</para>
</listitem>
</itemizedlist>
- <para>Server discovery uses <ulink url="http://en.wikipedia.org/wiki/User_Datagram_Protocol"
- >UDP</ulink> multicast to broadcast server connection settings. If UDP is disabled
- on your network you won't be able to use this, and will have to specify servers
- explicitly when setting up a cluster or using a messaging client.</para>
- <section id="clusters.broadcast-groups">
- <title>Broadcast Groups</title>
- <para>A broadcast group is the means by which a server broadcasts connectors over the
- network. A connector defines a way in which a client (or other server) can make
- connections to the server. For more information on what a connector is, please see
- <xref linkend="configuring-transports"/>.</para>
- <para>The broadcast group takes a set of connector pairs, each connector pair contains
- connection settings for a live and (optional) backup server and broadcasts them on
- the network. It also defines the UDP address and port settings. </para>
- <para>Broadcast groups are defined in the server configuration file <literal
- >hornetq-configuration.xml</literal>. There can be many broadcast groups per
- HornetQ server. All broadcast groups must be defined in a <literal
- >broadcast-groups</literal> element.</para>
- <para>Let's take a look at an example broadcast group from <literal
- >hornetq-configuration.xml</literal>:</para>
- <programlisting><broadcast-groups>
- <broadcast-group name="my-broadcast-group">
- <local-bind-address>172.16.9.3</local-bind-address>
- <local-bind-port>5432</local-bind-port>
- <group-address>231.7.7.7</group-address>
- <group-port>9876</group-port>
- <broadcast-period>2000</broadcast-period>
- <connector-ref connector-name="netty-connector"
- backup-connector-name="backup-connector"/>
- </broadcast-group>
-</broadcast-groups></programlisting>
- <para>Some of the broadcast group parameters are optional and you'll normally use the
- defaults, but we specify them all in the above example for clarity. Let's discuss
- each one in turn:</para>
- <itemizedlist>
- <listitem>
- <para><literal>name</literal> attribute. Each broadcast group in the server must
- have a unique name. </para>
- </listitem>
- <listitem>
- <para><literal>local-bind-address</literal>. This is the local bind address that
- the datagram socket is bound to. If you have multiple network interfaces on
- your server, you would specify which one you wish to use for broadcasts by
- setting this property. If this property is not specified then the socket
- will be bound to the wildcard address, an IP address chosen by the
- kernel.</para>
- </listitem>
- <listitem>
- <para><literal>local-bind-port</literal>. If you want to specify a local port to
- which the datagram socket is bound you can specify it here. Normally you
- would just use the default value of <literal>-1</literal> which signifies
- that an anonymous port should be used. This parameter is alawys specified in conjunction with
- <literal>local-bind-address</literal>.</para>
- </listitem>
- <listitem>
- <para><literal>group-address</literal>. This is the multicast address to which
- the data will be broadcast. It is a class D IP address in the range <literal
- >224.0.0.0</literal> to <literal>239.255.255.255</literal>, inclusive.
- The address <literal>224.0.0.0</literal> is reserved and is not available
- for use. This parameter is mandatory.</para>
- </listitem>
- <listitem>
- <para><literal>group-port</literal>. This is the UDP port number used for
- broadcasting. This parameter is mandatory.</para>
- </listitem>
- <listitem>
- <para><literal>broadcast-period</literal>. This is the period in milliseconds
- between consecutive broadcasts. This parameter is optional, the default
- value is <literal>2000</literal> milliseconds.</para>
- </listitem>
- <listitem>
- <para><literal>connector-ref</literal>. This specifies the connector and
- optional backup connector that will be broadcasted (see <xref
- linkend="configuring-transports"/> for more information on connectors).
- The connector to be broadcasted is specified by the <literal
- >connector-name</literal> attribute, and the backup connector to be
- broadcasted is specified by the <literal>backup-connector</literal>
- attribute. The <literal>backup-connector</literal> attribute is
- optional.</para>
- </listitem>
- </itemizedlist>
- </section>
- <section id="clusters.discovery-groups">
- <title>Discovery Groups</title>
- <para>While the broadcast group defines how connector information is broadcasted from a
- server, a discovery group defines how connector information is received from a
- multicast address.</para>
- <para>A discovery group maintains a list of connector pairs - one for each broadcast by
- a different server. As it receives broadcasts on the multicast group address from a
- particular server it updates its entry in the list for that server.</para>
- <para>If it has not received a broadcast from a particular server for a length of time
- it will remove that server's entry from its list.</para>
- <para>Discovery groups are used in two places in HornetQ:</para>
- <itemizedlist>
- <listitem>
- <para>By cluster connections so they know what other servers in the cluster they
- should make connections to.</para>
- </listitem>
- <listitem>
- <para>By messaging clients so they can discovery what servers in the cluster
- they can connect to.</para>
- </listitem>
- </itemizedlist>
- </section>
+ <para>
+ This information, lets call it the Cluster Topology, is actually sent around normal HornetQ
+ connections to clients and to other servers over cluster connections. This being the case we need a
+ way of establishing the initial first connection. This can either be done using
+ <ulink url="http://en.wikipedia.org/wiki/User_Datagram_Protocol" >UDP</ulink> or by
+ providing a list of initial connectors.
+ </para>
<section>
- <title>Defining Discovery Groups on the Server</title>
- <para>For cluster connections, discovery groups are defined in the server side
- configuration file <literal>hornetq-configuration.xml</literal>. All discovery
- groups must be defined inside a <literal>discovery-groups</literal> element. There
- can be many discovery groups defined by HornetQ server. Let's look at an
- example:</para>
- <programlisting><discovery-groups>
- <discovery-group name="my-discovery-group">
- <local-bind-address>172.16.9.7</local-bind-address>
- <group-address>231.7.7.7</group-address>
- <group-port>9876</group-port>
- <refresh-timeout>10000</refresh-timeout>
- </discovery-group>
-</discovery-groups></programlisting>
- <para>We'll consider each parameter of the discovery group:</para>
- <itemizedlist>
- <listitem>
- <para><literal>name</literal> attribute. Each discovery group must have a unique
- name per server.</para>
- </listitem>
- <listitem>
- <para><literal>local-bind-address</literal>. If you are running with multiple network interfaces on the same machine, you
- may want to specify that the discovery group listens only only a specific interface. To do this you can specify the interface
- address with this parameter. This parameter is optional.</para>
- </listitem>
- <listitem>
- <para><literal>group-address</literal>. This is the multicast ip address of the
- group to listen on. It should match the <literal>group-address</literal> in
- the broadcast group that you wish to listen from. This parameter is
- mandatory.</para>
- </listitem>
- <listitem>
- <para><literal>group-port</literal>. This is the UDP port of the multicast
- group. It should match the <literal>group-port</literal> in the broadcast
- group that you wish to listen from. This parameter is mandatory.</para>
- </listitem>
- <listitem>
- <para><literal>refresh-timeout</literal>. This is the period the discovery group
- waits after receiving the last broadcast from a particular server before
- removing that servers connector pair entry from its list. You would normally
- set this to a value significantly higher than the <literal
- >broadcast-period</literal> on the broadcast group otherwise servers
- might intermittently disappear from the list even though they are still
- broadcasting due to slight differences in timing. This parameter is
- optional, the default value is <literal>10000</literal> milliseconds (10
- seconds).</para>
- </listitem>
- </itemizedlist>
- </section>
- <section id="clusters-discovery.groups.clientside">
- <title>Discovery Groups on the Client Side</title>
- <para>Let's discuss how to configure a HornetQ client to use discovery to discover a
- list of servers to which it can connect. The way to do this differs depending on
- whether you're using JMS or the core API.</para>
+ <title>Discovery using UDP</title>
+ <para>
+ Server discovery uses <ulink url="http://en.wikipedia.org/wiki/User_Datagram_Protocol" >UDP</ulink>
+ multicast to broadcast server connection settings. If UDP is disabled
+ on your network you won't be able to use this, and will have to specify servers
+ explicitly when setting up a cluster or using a messaging client.
+ </para>
+ <section id="clusters.broadcast-groups">
+ <title>Broadcast Groups</title>
+ <para>A broadcast group is the means by which a server broadcasts connectors over the
+ network. A connector defines a way in which a client (or other server) can make
+ connections to the server. For more information on what a connector is, please see
+ <xref linkend="configuring-transports"/>.</para>
+ <para>The broadcast group takes a set of connector pairs, each connector pair contains
+ connection settings for a live and backup server (if one exists) and broadcasts them on
+ the network. It also defines the UDP address and port settings. </para>
+ <para>Broadcast groups are defined in the server configuration file <literal
+ >hornetq-configuration.xml</literal>. There can be many broadcast groups per
+ HornetQ server. All broadcast groups must be defined in a <literal
+ >broadcast-groups</literal> element.</para>
+ <para>Let's take a look at an example broadcast group from <literal
+ >hornetq-configuration.xml</literal>:</para>
+ <programlisting><broadcast-groups>
+ <broadcast-group name="my-broadcast-group">
+ <local-bind-address>172.16.9.3</local-bind-address>
+ <local-bind-port>5432</local-bind-port>
+ <group-address>231.7.7.7</group-address>
+ <group-port>9876</group-port>
+ <broadcast-period>2000</broadcast-period>
+ <connector-ref connector-name="netty-connector"/>
+ </broadcast-group>
+ </broadcast-groups></programlisting>
+ <para>Some of the broadcast group parameters are optional and you'll normally use the
+ defaults, but we specify them all in the above example for clarity. Let's discuss
+ each one in turn:</para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>name</literal> attribute. Each broadcast group in the server must
+ have a unique name. </para>
+ </listitem>
+ <listitem>
+ <para><literal>local-bind-address</literal>. This is the local bind address that
+ the datagram socket is bound to. If you have multiple network interfaces on
+ your server, you would specify which one you wish to use for broadcasts by
+ setting this property. If this property is not specified then the socket
+ will be bound to the wildcard address, an IP address chosen by the
+ kernel.</para>
+ </listitem>
+ <listitem>
+ <para><literal>local-bind-port</literal>. If you want to specify a local port to
+ which the datagram socket is bound you can specify it here. Normally you
+ would just use the default value of <literal>-1</literal> which signifies
+ that an anonymous port should be used. This parameter is alawys specified in conjunction with
+ <literal>local-bind-address</literal>.</para>
+ </listitem>
+ <listitem>
+ <para><literal>group-address</literal>. This is the multicast address to which
+ the data will be broadcast. It is a class D IP address in the range <literal
+ >224.0.0.0</literal> to <literal>239.255.255.255</literal>, inclusive.
+ The address <literal>224.0.0.0</literal> is reserved and is not available
+ for use. This parameter is mandatory.</para>
+ </listitem>
+ <listitem>
+ <para><literal>group-port</literal>. This is the UDP port number used for
+ broadcasting. This parameter is mandatory.</para>
+ </listitem>
+ <listitem>
+ <para><literal>broadcast-period</literal>. This is the period in milliseconds
+ between consecutive broadcasts. This parameter is optional, the default
+ value is <literal>2000</literal> milliseconds.</para>
+ </listitem>
+ <listitem>
+ <para><literal>connector-ref</literal>. This specifies the connector and
+ optional backup connector that will be broadcasted (see <xref
+ linkend="configuring-transports"/> for more information on connectors).
+ The connector to be broadcasted is specified by the <literal
+ >connector-name</literal> attribute..</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="clusters.discovery-groups">
+ <title>Discovery Groups</title>
+ <para>While the broadcast group defines how connector information is broadcasted from a
+ server, a discovery group defines how connector information is received from a
+ multicast address.</para>
+ <para>A discovery group maintains a list of connector pairs - one for each broadcast by
+ a different server. As it receives broadcasts on the multicast group address from a
+ particular server it updates its entry in the list for that server.</para>
+ <para>If it has not received a broadcast from a particular server for a length of time
+ it will remove that server's entry from its list.</para>
+ <para>Discovery groups are used in two places in HornetQ:</para>
+ <itemizedlist>
+ <listitem>
+ <para>By cluster connections so they know how to obtain an initial connection to download the topology</para>
+ </listitem>
+ <listitem>
+ <para>By messaging clients so they know how to obtain an initial connection to download the topology</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Although a discovery group will always accept broadcasts, its current list of avaliable live and
+ backup servers is only ever used when an initial connection is made, from then server discovery is
+ done over the normal HornetQ connections.
+ </para>
+ </section>
<section>
- <title>Configuring client discovery using JMS</title>
- <para>If you're using JMS and you're also using the JMS Service on the server to
- load your JMS connection factory instances into JNDI, then you can specify which
- discovery group to use for your JMS connection factory in the server side xml
- configuration <literal>hornetq-jms.xml</literal>. Let's take a look at an
+ <title>Defining Discovery Groups on the Server</title>
+ <para>For cluster connections, discovery groups are defined in the server side
+ configuration file <literal>hornetq-configuration.xml</literal>. All discovery
+ groups must be defined inside a <literal>discovery-groups</literal> element. There
+ can be many discovery groups defined by HornetQ server. Let's look at an
example:</para>
- <programlisting><connection-factory name="ConnectionFactory">
- <discovery-group-ref discovery-group-name="my-discovery-group"/>
- <entries>
- <entry name="ConnectionFactory"/>
- </entries>
-</connection-factory></programlisting>
- <para>The element <literal>discovery-group-ref</literal> specifies the name of a
- discovery group defined in <literal>hornetq-configuration.xml</literal>.</para>
- <para>When this connection factory is downloaded from JNDI by a client application
- and JMS connections are created from it, those connections will be load-balanced
- across the list of servers that the discovery group maintains by listening on
- the multicast address specified in the discovery group configuration.</para>
- <para>If you're using JMS, but you're not using JNDI to lookup a connection factory
- - you're instantiating the JMS connection factory directly then you can specify
- the discovery group parameters directly when creating the JMS connection
- factory. Here's an
- example:<programlisting>final String groupAddress = "231.7.7.7";
+ <programlisting><discovery-groups>
+ <discovery-group name="my-discovery-group">
+ <local-bind-address>172.16.9.7</local-bind-address>
+ <group-address>231.7.7.7</group-address>
+ <group-port>9876</group-port>
+ <refresh-timeout>10000</refresh-timeout>
+ </discovery-group>
+ </discovery-groups></programlisting>
+ <para>We'll consider each parameter of the discovery group:</para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>name</literal> attribute. Each discovery group must have a unique
+ name per server.</para>
+ </listitem>
+ <listitem>
+ <para><literal>local-bind-address</literal>. If you are running with multiple network interfaces on the same machine, you
+ may want to specify that the discovery group listens only only a specific interface. To do this you can specify the interface
+ address with this parameter. This parameter is optional.</para>
+ </listitem>
+ <listitem>
+ <para><literal>group-address</literal>. This is the multicast ip address of the
+ group to listen on. It should match the <literal>group-address</literal> in
+ the broadcast group that you wish to listen from. This parameter is
+ mandatory.</para>
+ </listitem>
+ <listitem>
+ <para><literal>group-port</literal>. This is the UDP port of the multicast
+ group. It should match the <literal>group-port</literal> in the broadcast
+ group that you wish to listen from. This parameter is mandatory.</para>
+ </listitem>
+ <listitem>
+ <para><literal>refresh-timeout</literal>. This is the period the discovery group
+ waits after receiving the last broadcast from a particular server before
+ removing that servers connector pair entry from its list. You would normally
+ set this to a value significantly higher than the <literal
+ >broadcast-period</literal> on the broadcast group otherwise servers
+ might intermittently disappear from the list even though they are still
+ broadcasting due to slight differences in timing. This parameter is
+ optional, the default value is <literal>10000</literal> milliseconds (10
+ seconds).</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="clusters-discovery.groups.clientside">
+ <title>Discovery Groups on the Client Side</title>
+ <para>Let's discuss how to configure a HornetQ client to use discovery to discover a
+ list of servers to which it can connect. The way to do this differs depending on
+ whether you're using JMS or the core API.</para>
+ <section>
+ <title>Configuring client discovery using JMS</title>
+ <para>If you're using JMS and you're also using the JMS Service on the server to
+ load your JMS connection factory instances into JNDI, then you can specify which
+ discovery group to use for your JMS connection factory in the server side xml
+ configuration <literal>hornetq-jms.xml</literal>. Let's take a look at an
+ example:</para>
+ <programlisting><connection-factory name="ConnectionFactory">
+ <discovery-group-ref discovery-group-name="my-discovery-group"/>
+ <entries>
+ <entry name="ConnectionFactory"/>
+ </entries>
+ </connection-factory></programlisting>
+ <para>The element <literal>discovery-group-ref</literal> specifies the name of a
+ discovery group defined in <literal>hornetq-configuration.xml</literal>.</para>
+ <para>When this connection factory is downloaded from JNDI by a client application
+ and JMS connections are created from it, those connections will be load-balanced
+ across the list of servers that the discovery group maintains by listening on
+ the multicast address specified in the discovery group configuration.</para>
+ <para>If you're using JMS, but you're not using JNDI to lookup a connection factory
+ - you're instantiating the JMS connection factory directly then you can specify
+ the discovery group parameters directly when creating the JMS connection
+ factory. Here's an
+ example:<programlisting>final String groupAddress = "231.7.7.7";
-final int groupPort = 9876;
+ final int groupPort = 9876;
-ConnectionFactory jmsConnectionFactory =
- HornetQJMSClient.createConnectionFactory(groupAddress, groupPort);
+ ConnectionFactory jmsConnectionFactory =
+ HornetQJMSClient.createConnectionFactory(new DiscoveryGroupConfiguration(groupAddress, groupPort), , JMSFactoryType.CF);
-Connection jmsConnection1 = jmsConnectionFactory.createConnection();
+ Connection jmsConnection1 = jmsConnectionFactory.createConnection();
-Connection jmsConnection2 = jmsConnectionFactory.createConnection();</programlisting></para>
- <para>The <literal>refresh-timeout</literal> can be set directly on the connection
- factory by using the setter method <literal>setDiscoveryRefreshTimeout()</literal> if you
- want to change the default value.</para>
- <para>There is also a further parameter settable on the connection factory using the
- setter method <literal>setDiscoveryInitialWaitTimeout()</literal>. If the connection
- factory is used immediately after creation then it may not have had enough time
- to received broadcasts from all the nodes in the cluster. On first usage, the
- connection factory will make sure it waits this long since creation before
- creating the first connection. The default value for this parameter is <literal
- >10000</literal> milliseconds.</para>
+ Connection jmsConnection2 = jmsConnectionFactory.createConnection();</programlisting></para>
+ <para>The <literal>refresh-timeout</literal> can be set directly on the DiscoveryGroupConfiguration
+ by using the setter method <literal>setDiscoveryRefreshTimeout()</literal> if you
+ want to change the default value.</para>
+ <para>There is also a further parameter settable on the DiscoveryGroupConfiguration using the
+ setter method <literal>setDiscoveryInitialWaitTimeout()</literal>. If the connection
+ factory is used immediately after creation then it may not have had enough time
+ to received broadcasts from all the nodes in the cluster. On first usage, the
+ connection factory will make sure it waits this long since creation before
+ creating the first connection. The default value for this parameter is <literal
+ >10000</literal> milliseconds.</para>
+ </section>
+ <section>
+ <title>Configuring client discovery using Core</title>
+ <para>If you're using the core API to directly instantiate <literal
+ >ClientSessionFactory</literal> instances, then you can specify the
+ discovery group parameters directly when creating the session factory. Here's an
+ example:
+ <programlisting>
+ final String groupAddress = "231.7.7.7";
+ final int groupPort = 9876;
+ SessionFactory factory = HornetQClient.createClientSessionFactory(new DiscoveryGroupConfiguration(groupAddress, groupPort));
+ ClientSession session1 = factory.createClientSession(...); ClientSession
+ session2 = factory.createClientSession(...);
+
+ </programlisting></para>
+ <para>The <literal>refresh-timeout</literal> can be set directly on the DiscoveryGroupConfiguration
+ by using the setter method <literal>setDiscoveryRefreshTimeout()</literal> if you
+ want to change the default value.</para>
+ <para>There is also a further parameter settable on the DiscoveryGroupConfiguration using the
+ setter method <literal>setDiscoveryInitialWaitTimeout()</literal>. If the session factory
+ is used immediately after creation then it may not have had enough time to
+ received broadcasts from all the nodes in the cluster. On first usage, the
+ session factory will make sure it waits this long since creation before creating
+ the first session. The default value for this parameter is <literal
+ >10000</literal> milliseconds.</para>
+ </section>
</section>
+ </section>
+ <section>
+ <title>Discovery using static Connectors</title>
+ <para>Sometimes it may be impossible to use UDP on the network you are using. In this case its
+ possible to configure a connection with an initial list if possible servers. This could be just
+ one server that you know will always be available or a list of servers where at least one will
+ be available.</para>
+ <para>This doesn't mean that you have to know where all your servers are going to be hosted, you
+ can configure these server to use the reliable servers to connect to. Once they are connected and
+ there where abouts will be propagated via the server it connects to</para>
<section>
- <title>Configuring client discovery using Core</title>
- <para>If you're using the core API to directly instantiate <literal
- >ClientSessionFactory</literal> instances, then you can specify the
- discovery group parameters directly when creating the session factory. Here's an
- example:
- <programlisting>
- final String groupAddress = "231.7.7.7";
- final int groupPort = 9876;
- SessionFactory factory = HornetQClient.createClientSessionFactory(groupAddress, groupPort);
- ClientSession session1 = factory.createClientSession(...); ClientSession
- session2 = factory.createClientSession(...);
-
- </programlisting></para>
- <para>The <literal>refresh-timeout</literal> can be set directly on the session
- factory by using the setter method <literal>setDiscoveryRefreshTimeout()</literal> if you
- want to change the default value.</para>
- <para>There is also a further parameter settable on the session factory using the
- setter method <literal>setDiscoveryInitialWaitTimeout()</literal>. If the session factory
- is used immediately after creation then it may not have had enough time to
- received broadcasts from all the nodes in the cluster. On first usage, the
- session factory will make sure it waits this long since creation before creating
- the first session. The default value for this parameter is <literal
- >10000</literal> milliseconds.</para>
+ <title>Configuring a Cluster Connection</title>
</section>
+ <section>
+ <title>Configuring a Client Connection</title>
+ </section>
</section>
</section>
<section>
15 years, 5 months
JBoss hornetq SVN: r10015 - trunk/docs/user-manual/en.
by do-not-reply@jboss.org
Author: ataylor
Date: 2010-12-08 08:47:35 -0500 (Wed, 08 Dec 2010)
New Revision: 10015
Modified:
trunk/docs/user-manual/en/configuration-index.xml
trunk/docs/user-manual/en/ha.xml
trunk/docs/user-manual/en/management.xml
Log:
updated failover docs
Modified: trunk/docs/user-manual/en/configuration-index.xml
===================================================================
--- trunk/docs/user-manual/en/configuration-index.xml 2010-12-08 10:44:57 UTC (rev 10014)
+++ trunk/docs/user-manual/en/configuration-index.xml 2010-12-08 13:47:35 UTC (rev 10015)
@@ -42,21 +42,6 @@
</thead>
<tbody>
<row>
- <entry><link linkend="configuring.live.backup">backup</link></entry>
- <entry>Boolean</entry>
- <entry>true means that this server is a backup to another node in the
- cluster</entry>
- <entry>false</entry>
- </row>
- <row>
- <entry><link linkend="configuring.live.backup"
- >backup-connector-ref</link></entry>
- <entry>String</entry>
- <entry>the name of the remoting connector to connect to the backup
- node</entry>
- <entry/>
- </row>
- <row>
<entry><link linkend="configuring.bindings.journal"
>bindings-directory</link></entry>
<entry>String</entry>
Modified: trunk/docs/user-manual/en/ha.xml
===================================================================
--- trunk/docs/user-manual/en/ha.xml 2010-12-08 10:44:57 UTC (rev 10014)
+++ trunk/docs/user-manual/en/ha.xml 2010-12-08 13:47:35 UTC (rev 10015)
@@ -24,113 +24,30 @@
<emphasis>ability for client connections to migrate from one server to another in event
of server failure so client applications can continue to operate</emphasis>.</para>
<section>
- <title>Live - Backup Pairs</title>
- <para>HornetQ allows pairs of servers to be linked together as <emphasis>live -
- backup</emphasis> pairs. In this release there is a single backup server for each
- live server. A backup server is owned by only one live server. Backup servers are not
- operational until failover occurs.</para>
+ <title>Live - Backup Groups</title>
+ <para>HornetQ allows servers to be linked together as <emphasis>live -
+ backup</emphasis> groups where each live server can have 1 or more backup servers.
+ A backup server is owned by only one live server. Backup servers are not operational until
+ failover occurs, however 1 chosen backup will be in passive mode announces its status and waiting to take
+ over the live servers work</para>
<para>Before failover, only the live server is serving the HornetQ clients while the backup
- server remains passive. When clients fail over to the backup server, the backup server
- becomes active and starts to service the HornetQ clients.</para>
+ servers remain passive or awaiting to become a backup server. When a live server crashes or is brought down
+ in the correct mode, the backup server currently in passive mode will become live and another backup server
+ will become passive. If a live server restarts after a failover then it will have priority and be the next server
+ to become live when the current live server goes down, if the current live server is configured to allow automatic
+ failback then it will detect the live server coming back up and automatically stop.</para>
<section id="ha.mode">
<title>HA modes</title>
- <para>HornetQ provides two different modes for high availability, either by
- <emphasis>replicating data</emphasis> from the live server journal to the backup
- server or using a <emphasis>shared store</emphasis> for both servers.</para>
+ <para>HornetQ provides only <emphasis>shared store</emphasis> in this release. <emphasis>Replication</emphasis>
+ will be available in the next release.</para>
<note>
<para>Only persistent message data will survive failover. Any non persistent message
data will not be available after failover.</para>
</note>
<section id="ha.mode.replicated">
<title>Data Replication</title>
- <para>In this mode, data stored in the HornetQ journal are replicated from the live
- server's journal to the backup server's journal. Note that we do not replicate
- the entire server state, we only replicate the journal and other persistent
- operations.</para>
- <para>Replication is performed in an asynchronous fashion between live and backup
- server. Data is replicated one way in a stream, and responses that the data has
- reached the backup is returned in another stream. Pipelining replications and
- responses to replications in separate streams allows replication throughput to
- be much higher than if we synchronously replicated data and waited for a
- response serially in an RPC manner before replicating the next piece of
- data.</para>
- <para>When the user receives confirmation that a transaction has committed, prepared
- or rolled back or a durable message has been sent, we can guarantee it has
- reached the backup server and been persisted.</para>
- <para>Data replication introduces some inevitable performance overhead compared to
- non replicated operation, but has the advantage in that it requires no expensive
- shared file system (e.g. a SAN) for failover, in other words it is a <emphasis
- role="italic">shared-nothing</emphasis> approach to high
- availability.</para>
- <para>Failover with data replication is also faster than failover using shared
- storage, since the journal does not have to be reloaded on failover at the
- backup node.</para>
- <graphic fileref="images/ha-replicated-store.png" align="center"/>
- <section id="configuring.live.backup">
- <title>Configuration</title>
- <para>First, on the live server, in <literal
- >hornetq-configuration.xml</literal>, configure the live server with
- knowledge of its backup server. This is done by specifying a <literal
- >backup-connector-ref</literal> element. This element references a
- connector, also specified on the live server which specifies how to connect
- to the backup server.</para>
- <para>Here's a snippet from live server's <literal
- >hornetq-configuration.xml</literal> configured to connect to its backup
- server:</para>
- <programlisting>
- <backup-connector-ref connector-name="backup-connector"/>
-
- <connectors>
- <!-- This connector specifies how to connect to the backup server -->
- <!-- backup server is located on host "192.168.0.11" and port "5445" -->
- <connector name="backup-connector">
- <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
- <param key="host" value="192.168.0.11"/>
- <param key="port" value="5445"/>
- </connector>
- </connectors></programlisting>
- <para>Secondly, on the backup server, we flag the server as a backup and make
- sure it has an acceptor that the live server can connect to. We also make
- sure the shared-store paramater is set to false:</para>
- <programlisting>
- <backup>true</backup>
-
- <shared-store>false<shared-store>
-
- <acceptors>
- <acceptor name="acceptor">
- <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
- <param key="host" value="192.168.0.11"/>
- <param key="port" value="5445"/>
- </acceptor>
- </acceptors>
- </programlisting>
- <para>For a backup server to function correctly it's also important that it has
- the same set of bridges, predefined queues, cluster connections, broadcast
- groups and discovery groups as defined on the live node. The easiest way to
- ensure this is to copy the entire server side configuration from live to
- backup and just make the changes as specified above. </para>
+ <para>Replication will be available in the next release of HornetQ</para>
</section>
- <section>
- <title>Synchronizing a Backup Node to a Live Node</title>
- <para>In order for live - backup pairs to operate properly, they must be
- identical replicas. This means you cannot just use any backup server that's
- previously been used for other purposes as a backup server, since it will
- have different data in its persistent storage. If you try to do so, you will
- receive an exception in the logs and the server will fail to start.</para>
- <para>To create a backup server for a live server that's already been used for
- other purposes, it's necessary to copy the <literal>data</literal> directory
- from the live server to the backup server. This means the backup server will
- have an identical persistent store to the backup server.</para>
- <para>Once a live server has failed over onto a backup server, the old live
- server becomes invalid and cannot just be restarted. To resynchonize the
- pair as a working live backup pair again, both servers need to be stopped,
- the data copied from the live node to the backup node and restarted
- again.</para>
- <para>The next release of HornetQ will provide functionality for automatically
- synchronizing a new backup node to a live node without having to temporarily
- bring down the live node.</para>
- </section>
</section>
<section id="ha.mode.shared">
<title>Shared Store</title>
@@ -138,7 +55,7 @@
<emphasis>same</emphasis> entire data directory using a shared file system.
This means the paging directory, journal directory, large messages and binding
journal.</para>
- <para>When failover occurs and the backup server takes over, it will load the
+ <para>When failover occurs and a backup server takes over, it will load the
persistent storage from the shared file system and clients can connect to
it.</para>
<para>This style of high availability differs from data replication in that it
@@ -159,38 +76,54 @@
<graphic fileref="images/ha-shared-store.png" align="center"/>
<section id="ha/mode.shared.configuration">
<title>Configuration</title>
- <para>To configure the live and backup server to share their store, configure
- both <literal>hornetq-configuration.xml</literal>:</para>
+ <para>To configure the live and backup servers to share their store, configure
+ all <literal>hornetq-configuration.xml</literal>:</para>
<programlisting>
<shared-store>true<shared-store>
</programlisting>
- <para>Additionally, the backup server must be flagged explicitly as a
+ <para>Additionally, each backup server must be flagged explicitly as a
backup:</para>
<programlisting>
<backup>true</backup>
</programlisting>
- <para>In order for live - backup pairs to operate properly with a shared store,
+ <para>In order for live - backup groups to operate properly with a shared store,
both servers must have configured the location of journal directory to point
to the <emphasis>same shared location</emphasis> (as explained in <xref
linkend="configuring.message.journal"/>)</para>
- <para>If clients will use automatic failover with JMS, the live server will need
- to configure a connector to the backup server and reference it from its
- <literal>hornetq-jms.xml</literal> configuration as explained in <xref
- linkend="ha.automatic.failover"/>.</para>
+ <para>Also each node, live and backups, will need to have a cluster connection defined even if not
+ part of a cluster. The Cluster Connection info defines how backup servers announce there presence
+ to it's live server or any other nodes in the cluster. refer to <xref linkend="clusters"/> for details
+ on how this is done.</para>
</section>
<section>
- <title>Synchronizing a Backup Node to a Live Node</title>
- <para>As both live and backup servers share the same journal, they do not need
- to be synchronized. However until, both live and backup servers are up and
- running, high-availability can not be provided with a single server. After
- failover, at first opportunity, stop the backup server (which is active) and
- restart the live and backup servers.</para>
- <para>In the next release of HornetQ we will provide functionality to
- automatically synchronize a new backup server with a running live server
- without having to temporarily bring the live server down.</para>
+ <title>Failing Back to live Server</title>
+ <para>After a live server has failed and a backup taken has taken over its duties, you may want to
+ restart the live server and have clients fail back. To do this simply restart the original live
+ server and kill the new live server. You can do this by killing the process itself or just waiting
+ for the server to crash naturally </para>
+ <para>
+ It is also possible to cause failover to occur on normal server shutdown, to enable
+ this set the following property to true in the <literal>hornetq-configuration.xml</literal>
+ configuration file like so:
+ </para>
+ <programlisting>
+ <failover-on-shutdown>true</failover-on-shutdown>
+ </programlisting>
+ <para>
+ By default this is set to false, if by some chance you have set this to false but still
+ want to stop the server normally and cause failover then you can do this by using the management
+ API as explained at <xref linkend="management.core.server"/>
+ </para>
+ <para>
+ You can also force the new live server to shutdown when the old live server comes back up allowing
+ the original live server to take over automatically by setting the following property in the
+ <literal>hornetq-configuration.xml</literal> configuration file as follows:
+ </para>
+ <programlisting>
+ <allow-failback>true</allow-failback>
+ </programlisting>
</section>
</section>
- </section>
</section>
<section id="failover">
<title>Failover Modes</title>
@@ -212,7 +145,7 @@
since the backup node will not have any knowledge of non persistent queues.</para>
<section id="ha.automatic.failover">
<title>Automatic Client Failover</title>
- <para>HornetQ clients can be configured with knowledge of live and backup servers, so
+ <para>HornetQ clients can be configured to receive knowledge of all live and backup servers, so
that in event of connection failure at the client - live server connection, the
client will detect this and reconnect to the backup server. The backup server will
then automatically recreate any sessions and consumers that existed on each
@@ -222,52 +155,46 @@
the server within the time given by <literal>client-failure-check-period</literal>
as explained in section <xref linkend="connection-ttl"/>. If the client does not
receive data in good time, it will assume the connection has failed and attempt
- failover.</para>
- <para>HornetQ clients can be configured with the list of live-backup server pairs in a
+ failover. Also if the socket is closed by the OS, usually if the server process is
+ killed rather than the machine itself crashing, then the client will failover straight away.
+ </para>
+ <para>HornetQ clients can be configured to discover the list of live-backup server groups in a
number of different ways. They can be configured explicitly or probably the most
common way of doing this is to use <emphasis>server discovery</emphasis> for the
client to automatically discover the list. For full details on how to configure
server discovery, please see <xref linkend="clusters.server-discovery"/>.
- Alternatively, the clients can explicitly specifies pairs of live-backup server as
- explained in <xref linkend="clusters.static.servers"/>.</para>
+ Alternatively, the clients can explicitly connect to a specific server and download
+ the current servers and backups see <xref linkend="clusters.static.servers"/>.</para>
<para>To enable automatic client failover, the client must be configured to allow
non-zero reconnection attempts (as explained in <xref linkend="client-reconnection"
/>).</para>
- <para>Sometimes you want a client to failover onto a backup server even if the live
- server is just cleanly shutdown rather than having crashed or the connection failed.
- To configure this you can set the property <literal
- >FailoverOnServerShutdown</literal> to true either on the <literal
- >HornetQConnectionFactory</literal> if you're using JMS or in the <literal
- >hornetq-jms.xml (failover-on-server-shutdown property)</literal> file when you
- define the connection factory, or if using core by setting the property directly on
- the <literal>ClientSessionFactoryImpl</literal> instance after creation. The default
- value for this property is <literal>false</literal>, this means that by default
- <emphasis>HornetQ clients will not failover to a backup server if the live
- server is simply shutdown cleanly.</emphasis></para>
- <para>
- <note>
- <para>By default, cleanly shutting down the server <emphasis role="bold">will
- not</emphasis> trigger failover on the client.</para>
- <para>Using CTRL-C on a HornetQ server or JBoss AS instance causes the server to
- <emphasis role="bold">cleanly shut down</emphasis>, so will not trigger
- failover on the client. </para>
- <para>If you want the client to failover when its server is cleanly shutdown
- then you must set the property <literal>FailoverOnServerShutdown</literal>
- to true</para>
- </note>
- </para>
<para>By default failover will only occur after at least one connection has been made to
the live server. In other words, by default, failover will not occur if the client
fails to make an initial connection to the live server - in this case it will simply
retry connecting to the live server according to the reconnect-attempts property and
fail after this number of attempts.</para>
- <para>In some cases, you may want the client to automatically try the backup server it
- fails to make an initial connection to the live server. In this case you can set the
- property <literal>FailoverOnInitialConnection</literal>, or <literal
- >failover-on-initial-connection</literal> in xml, on the <literal
- >ClientSessionFactoryImpl</literal> or <literal
- >HornetQConnectionFactory</literal>. The default value for this parameter is
- <literal>false</literal>. </para>
+ <section>
+ <title>Failing over on the Initial Connection</title>
+ <para>
+ Since the client doesn't learn about the full topology until after the first
+ connection is made there is a window where it doesn't know about the backup. If a failure happens at
+ this point the client can only try reconnecting to the original live server. To configure
+ how many attempts the client will make you can set the property <literal>initialConnectAttempts</literal>
+ on the <literal>ClientSessionFactoryImpl</literal> or <literal >HornetQConnectionFactory</literal> or
+ <literal>initial-connect-attempts</literal> in xml. The default for this is <literal>0</literal>, that
+ is try only once. Once the number of attempts has been made an exception will be thrown.
+ </para>
+ <para>
+ Similarly, when a cluster topology changed, i.e. a live server crashes and a backup becomes live,
+ there is a window where the topology has changes but the client has yet to be notified. Again as
+ above the client will try an initial number of connect attempts with the live server but after that
+ it is possible to try to connect to the backup server (if the client knows of it). To do this
+ set the property <literal>FailoverOnInitialConnection</literal>, or <literal>failover-on-initial-connection</literal>
+ in xml, on the <literal>ClientSessionFactoryImpl</literal> or <literal>HornetQConnectionFactory</literal>.
+ The default value for this parameter is <literal>false</literal>. The client will use the property
+ reconnect attempts to decide how many times to try the backup server.
+ </para>
+ </section>
<para>For examples of automatic failover with transacted and non-transacted JMS
sessions, please see <xref linkend="examples.transaction-failover"/> and <xref
linkend="examples.non-transaction-failover"/>.</para>
Modified: trunk/docs/user-manual/en/management.xml
===================================================================
--- trunk/docs/user-manual/en/management.xml 2010-12-08 10:44:57 UTC (rev 10014)
+++ trunk/docs/user-manual/en/management.xml 2010-12-08 13:47:35 UTC (rev 10015)
@@ -71,7 +71,7 @@
<title>Core Management API</title>
<para>HornetQ defines a core management API to manage core resources. For full details of
the API please consult the javadoc. In summary:</para>
- <section>
+ <section id="management.core.server">
<title>Core Server Management</title>
<itemizedlist>
<listitem>
@@ -142,7 +142,17 @@
>org.hornetq:module=Core,type=Server</literal> or the resource name <literal
>core.server</literal>).</para>
</listitem>
-
+ <listitem>
+ <para>It is possible to stop the server and force failover to occur with any currently attached clients.</para>
+ <para>to do this use the <literal>forceFailover()</literal> on the <literal
+ >HornetQServerControl</literal> (with the ObjectName <literal
+ >org.hornetq:module=Core,type=Server</literal> or the resource name <literal
+ >core.server</literal>) </para>
+ <para>
+ <note>Since this method actually stops the server you will probably receive some sort of error
+ depending on which management service you use to call it.</note>
+ </para>
+ </listitem>
</itemizedlist>
</section>
<section>
15 years, 5 months
JBoss hornetq SVN: r10014 - in trunk: tests/src/org/hornetq/tests/util and 1 other directory.
by do-not-reply@jboss.org
Author: pslavice(a)redhat.com
Date: 2010-12-08 05:44:57 -0500 (Wed, 08 Dec 2010)
New Revision: 10014
Modified:
trunk/examples/common/src/org/hornetq/common/example/SpawnedVMSupport.java
trunk/tests/src/org/hornetq/tests/util/SpawnedVMSupport.java
Log:
Fixed test suite for Solaris platform HORNETQ-518
Modified: trunk/examples/common/src/org/hornetq/common/example/SpawnedVMSupport.java
===================================================================
--- trunk/examples/common/src/org/hornetq/common/example/SpawnedVMSupport.java 2010-12-08 09:53:15 UTC (rev 10013)
+++ trunk/examples/common/src/org/hornetq/common/example/SpawnedVMSupport.java 2010-12-08 10:44:57 UTC (rev 10014)
@@ -74,7 +74,11 @@
sb.append("java").append(' ');
String vmarg = vmargs;
- if (System.getProperty("os.name").contains("Windows"))
+
+ String osName = System.getProperty("os.name");
+ osName = (osName != null) ? osName.toLowerCase() : "";
+ boolean isWindows = osName.contains("win");
+ if (isWindows)
{
vmarg = vmarg.replaceAll("/", "\\\\");
}
@@ -82,7 +86,6 @@
String pathSeparater = System.getProperty("path.separator");
classPath = classPath + pathSeparater + ".";
- boolean isWindows = System.getProperty("os.name").contains("Windows");
if (isWindows)
{
sb.append("-cp").append(" \"").append(classPath).append("\" ");
Modified: trunk/tests/src/org/hornetq/tests/util/SpawnedVMSupport.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/util/SpawnedVMSupport.java 2010-12-08 09:53:15 UTC (rev 10013)
+++ trunk/tests/src/org/hornetq/tests/util/SpawnedVMSupport.java 2010-12-08 10:44:57 UTC (rev 10014)
@@ -91,14 +91,16 @@
String classPath = System.getProperty("java.class.path");
- // I guess it'd be simpler to check if the OS is Windows...
- if (System.getProperty("os.name").equals("Linux") || System.getProperty("os.name").equals("Mac OS X"))
+ String osName = System.getProperty("os.name");
+ osName = (osName != null) ? osName.toLowerCase() : "";
+ boolean isWindows = osName.contains("win");
+ if (isWindows)
{
- sb.append("-cp").append(" ").append(classPath).append(" ");
+ sb.append("-cp").append(" \"").append(classPath).append("\" ");
}
else
{
- sb.append("-cp").append(" \"").append(classPath).append("\" ");
+ sb.append("-cp").append(" ").append(classPath).append(" ");
}
sb.append("-Djava.io.tmpdir=" + System.getProperty("java.io.tmpdir", "./tmp")).append(" ");
15 years, 5 months
JBoss hornetq SVN: r10013 - in trunk/examples/jms: stop-server-failover and 7 other directories.
by do-not-reply@jboss.org
Author: ataylor
Date: 2010-12-08 04:53:15 -0500 (Wed, 08 Dec 2010)
New Revision: 10013
Added:
trunk/examples/jms/stop-server-failover/
trunk/examples/jms/stop-server-failover/build.bat
trunk/examples/jms/stop-server-failover/build.sh
trunk/examples/jms/stop-server-failover/build.xml
trunk/examples/jms/stop-server-failover/readme.html
trunk/examples/jms/stop-server-failover/server0/
trunk/examples/jms/stop-server-failover/server0/client-jndi.properties
trunk/examples/jms/stop-server-failover/server0/hornetq-beans.xml
trunk/examples/jms/stop-server-failover/server0/hornetq-configuration.xml
trunk/examples/jms/stop-server-failover/server0/hornetq-jms.xml
trunk/examples/jms/stop-server-failover/server0/hornetq-users.xml
trunk/examples/jms/stop-server-failover/server1/
trunk/examples/jms/stop-server-failover/server1/client-jndi.properties
trunk/examples/jms/stop-server-failover/server1/hornetq-beans.xml
trunk/examples/jms/stop-server-failover/server1/hornetq-configuration.xml
trunk/examples/jms/stop-server-failover/server1/hornetq-jms.xml
trunk/examples/jms/stop-server-failover/server1/hornetq-users.xml
trunk/examples/jms/stop-server-failover/src/
trunk/examples/jms/stop-server-failover/src/org/
trunk/examples/jms/stop-server-failover/src/org/hornetq/
trunk/examples/jms/stop-server-failover/src/org/hornetq/jms/
trunk/examples/jms/stop-server-failover/src/org/hornetq/jms/example/
trunk/examples/jms/stop-server-failover/src/org/hornetq/jms/example/StopServerFailoverExample.java
Log:
added failover demonstrating forcing failover
Added: trunk/examples/jms/stop-server-failover/build.bat
===================================================================
--- trunk/examples/jms/stop-server-failover/build.bat (rev 0)
+++ trunk/examples/jms/stop-server-failover/build.bat 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,13 @@
+@echo off
+
+set "OVERRIDE_ANT_HOME=..\..\..\tools\ant"
+
+if exist "..\..\..\src\bin\build.bat" (
+ rem running from TRUNK
+ call ..\..\..\src\bin\build.bat %*
+) else (
+ rem running from the distro
+ call ..\..\..\bin\build.bat %*
+)
+
+set "OVERRIDE_ANT_HOME="
Added: trunk/examples/jms/stop-server-failover/build.sh
===================================================================
--- trunk/examples/jms/stop-server-failover/build.sh (rev 0)
+++ trunk/examples/jms/stop-server-failover/build.sh 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+OVERRIDE_ANT_HOME=../../../tools/ant
+export OVERRIDE_ANT_HOME
+
+if [ -f "../../../src/bin/build.sh" ]; then
+ # running from TRUNK
+ ../../../src/bin/build.sh "$@"
+else
+ # running from the distro
+ ../../../bin/build.sh "$@"
+fi
+
+
+
Property changes on: trunk/examples/jms/stop-server-failover/build.sh
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/examples/jms/stop-server-failover/build.xml
===================================================================
--- trunk/examples/jms/stop-server-failover/build.xml (rev 0)
+++ trunk/examples/jms/stop-server-failover/build.xml 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2009 Red Hat, Inc.
+ ~ Red Hat licenses this file to you under the Apache License, version
+ ~ 2.0 (the "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ ~ implied. See the License for the specific language governing
+ ~ permissions and limitations under the License.
+ -->
+
+<!DOCTYPE project [
+ <!ENTITY libraries SYSTEM "../../../thirdparty/libraries.ent">
+ ]>
+
+<project default="run" name="HornetQ JMS Non-transaction Failover Example">
+
+ <import file="../../common/build.xml"/>
+
+ <target name="run" depends="delete-files">
+ <antcall target="runExample">
+ <param name="example.classname" value="org.hornetq.jms.example.StopServerFailoverExample"/>
+ <param name="hornetq.example.beans.file" value="server0 server1"/>
+ </antcall>
+ </target>
+
+ <target name="runRemote" depends="delete-files">
+ <antcall target="runExample">
+ <param name="example.classname" value="org.hornetq.jms.example.StopServerFailoverExample"/>
+ <param name="hornetq.example.runServer" value="false"/>
+ </antcall>
+ </target>
+
+ <target name="delete-files" depends="clean">
+ <delete file="./server0/KILL_ME"/>
+ </target>
+
+</project>
Added: trunk/examples/jms/stop-server-failover/readme.html
===================================================================
--- trunk/examples/jms/stop-server-failover/readme.html (rev 0)
+++ trunk/examples/jms/stop-server-failover/readme.html 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,136 @@
+<html>
+ <head>
+ <title>HornetQ JMS Failover Without Transactions Example</title>
+ <link rel="stylesheet" type="text/css" href="../../common/common.css" />
+ <link rel="stylesheet" type="text/css" href="../../common/prettify.css" />
+ <script type="text/javascript" src="../../common/prettify.js"></script>
+ </head>
+ <body onload="prettyPrint()">
+ <h1>JMS Failover Without Transactions Example</h1>
+
+ <p>This example demonstrates two servers coupled as a live-backup pair for high availability (HA), and a client
+ connection failing over from live to backup when the live server is crashed.</p>
+ <p>Failover behavior differs wether the JMS session is transacted or not.</p>
+ <p>When a <em>non-transacted</em> JMS session is used, once and only once delivery is not guaranteed
+ and it is possible some messages will be lost or delivered twice, depending when the failover to the backup server occurs.</p>
+ <p>It is up to the client to deal with such cases. To ensure once and only once delivery, the client must
+ use transacted JMS sessions (as shown in the example for <a href="../transaction-failover/readme.html">failover with transactions</a>).</p>
+ <p>For more information on HornetQ failover and HA, and clustering in general, please see the clustering
+ section of the user manual.</p>
+
+ <h2>Example step-by-step</h2>
+ <p><i>To run the example, simply type <code>./build.sh</code> (or <code>build.bat</code> on windows) from this directory</i></p>
+ <p>In this example, the live server is server 1, and the backup server is server 0</p>
+ <p>The connection will initially be created to server1, server 1 will crash, and the client will carry on
+ seamlessly on server 0, the backup server.</p>
+ <ol>
+ <li>Get an initial context for looking up JNDI from server #1.</li>
+ <pre class="prettyprint">
+ initialContext = getContext(1);
+ </pre>
+
+ <li>Look up the JMS resources from JNDI on server #1.</li>
+ <pre class="prettyprint">
+ Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");
+ ConnectionFactory connectionFactory = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
+ </pre>
+
+ <li>Create a JMS Connection</li>
+ <pre class="prettyprint">
+ connection = connectionFactory.createConnection();
+ </pre>
+
+ <li>Create a JMS <em>non-transacted</em> Session with client acknowledgement</li>
+ <pre class="prettyprint">
+ Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ </pre>
+
+ <li>Start the connection to ensure delivery occurs</li>
+ <pre class="prettyprint">
+ connection.start();
+ </pre>
+
+ <li>Create a JMS MessageProducer and MessageConsumer</li>
+ <pre class="prettyprint">
+ MessageProducer producer = session.createProducer(queue);
+ MessageConsumer consumer = session.createConsumer(queue);
+ </pre>
+
+ <li>Send some messages to server #1</li>
+ <pre class="prettyprint">
+ for (int i = 0; i < numMessages; i++)
+ {
+ TextMessage message = session.createTextMessage("This is text message " + i);
+ producer.send(message);
+ System.out.println("Sent message: " + message.getText());
+ }
+ </pre>
+
+ <li>Receive and acknowledge half of the sent messages</li>
+ <pre class="prettyprint">
+ TextMessage message0 = null;
+ for (int i = 0; i < numMessages / 2; i++)
+ {
+ message0 = (TextMessage)consumer.receive(5000);
+ System.out.println("Got message: " + message0.getText());
+ }
+ message0.acknowledge();
+ </pre>
+
+ <li>Receive the second half of the sent messages but <em>do not acknowledge them yet</em></li>
+ <pre class="prettyprint">
+ for (int i = numMessages / 2; i < numMessages; i++)
+ {
+ message0 = (TextMessage)consumer.receive(5000);
+ System.out.println("Got message: " + message0.getText());
+ }
+ </pre>
+
+ <li>Crash server #1, the live server, and wait a little while to make sure it has really crashed.</li>
+ <pre class="prettyprint">
+ killServer(1);
+ Thread.sleep(2000);
+ </pre>
+
+ <li>Acknowledging the second half of the sent messages will fail as failover to the backup server has occured</li>
+ <pre class="prettyprint">
+ try
+ {
+ message0.acknowledge();
+ }
+ catch (JMSException e)
+ {
+ System.err.println("Got exception while acknowledging message: " + e.getMessage());
+ }
+ </pre>
+
+ <li>Consume again the second half of the messages againg. Note that they are not considered as redelivered</li>
+ <pre class="prettyprint">
+ for (int i = numMessages / 2; i < numMessages; i++)
+ {
+ message0 = (TextMessage)consumer.receive(5000);
+ System.out.printf("Got message: %s (redelivered?: %s)\n", message0.getText(), message0.getJMSRedelivered());
+ }
+ message0.acknowledge();
+ </pre>
+
+ <li>And finally, <strong>always</strong> remember to close your resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li>
+
+ <pre class="prettyprint">
+ finally
+ {
+ if (connection != null)
+ {
+ connection.close();
+ }
+
+ if (initialContext != null)
+ {
+ initialContext.close();
+ }
+ }
+ </pre>
+
+ </ol>
+ </body>
+</html>
Added: trunk/examples/jms/stop-server-failover/server0/client-jndi.properties
===================================================================
--- trunk/examples/jms/stop-server-failover/server0/client-jndi.properties (rev 0)
+++ trunk/examples/jms/stop-server-failover/server0/client-jndi.properties 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,3 @@
+java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+java.naming.provider.url=jnp://localhost:1099
+java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
Added: trunk/examples/jms/stop-server-failover/server0/hornetq-beans.xml
===================================================================
--- trunk/examples/jms/stop-server-failover/server0/hornetq-beans.xml (rev 0)
+++ trunk/examples/jms/stop-server-failover/server0/hornetq-beans.xml 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Copyright 2009 Red Hat, Inc.
+ ~ Red Hat licenses this file to you under the Apache License, version
+ ~ 2.0 (the "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ ~ implied. See the License for the specific language governing
+ ~ permissions and limitations under the License.
+ -->
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="Naming" class="org.jnp.server.NamingBeanImpl"/>
+
+ <!-- JNDI server. Disable this if you don't want JNDI -->
+ <bean name="JNDIServer" class="org.jnp.server.Main">
+ <property name="namingInfo">
+ <inject bean="Naming"/>
+ </property>
+ <property name="port">1099</property>
+ <property name="bindAddress">localhost</property>
+ <property name="rmiPort">1098</property>
+ <property name="rmiBindAddress">localhost</property>
+ </bean>
+
+ <!-- MBean server -->
+ <bean name="MBeanServer" class="javax.management.MBeanServer">
+ <constructor factoryClass="java.lang.management.ManagementFactory"
+ factoryMethod="getPlatformMBeanServer"/>
+ </bean>
+
+ <!-- The core configuration -->
+ <bean name="Configuration" class="org.hornetq.core.config.impl.FileConfiguration"/>
+
+ <!-- The security manager -->
+ <bean name="HornetQSecurityManager" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl">
+ <start ignored="true"/>
+ <stop ignored="true"/>
+ </bean>
+
+ <!-- The core server -->
+ <bean name="HornetQServer" class="org.hornetq.core.server.impl.HornetQServerImpl">
+ <constructor>
+ <parameter>
+ <inject bean="Configuration"/>
+ </parameter>
+ <parameter>
+ <inject bean="MBeanServer"/>
+ </parameter>
+ <parameter>
+ <inject bean="HornetQSecurityManager"/>
+ </parameter>
+ </constructor>
+ <start ignored="true"/>
+ <stop ignored="true"/>
+ </bean>
+
+ <!-- The JMS server -->
+ <bean name="JMSServerManager" class="org.hornetq.jms.server.impl.JMSServerManagerImpl">
+ <constructor>
+ <parameter>
+ <inject bean="HornetQServer"/>
+ </parameter>
+ </constructor>
+ </bean>
+
+</deployment>
Added: trunk/examples/jms/stop-server-failover/server0/hornetq-configuration.xml
===================================================================
--- trunk/examples/jms/stop-server-failover/server0/hornetq-configuration.xml (rev 0)
+++ trunk/examples/jms/stop-server-failover/server0/hornetq-configuration.xml 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,67 @@
+<configuration xmlns="urn:hornetq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd">
+
+ <clustered>true</clustered>
+
+ <!--we kill the server process so don't need this set to true-->
+ <failover-on-shutdown>false</failover-on-shutdown>
+
+ <shared-store>true</shared-store>
+
+ <!-- Connectors -->
+
+ <connectors>
+ <connector name="netty-connector">
+ <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
+ <param key="port" value="5445"/>
+ </connector>
+ </connectors>
+
+ <!-- Acceptors -->
+ <acceptors>
+ <acceptor name="netty-acceptor">
+ <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
+ <param key="port" value="5445"/>
+ </acceptor>
+ </acceptors>
+
+ <broadcast-groups>
+ <broadcast-group name="bg-group1">
+ <group-address>231.7.7.7</group-address>
+ <group-port>9876</group-port>
+ <broadcast-period>1000</broadcast-period>
+ <connector-ref>netty-connector</connector-ref>
+ </broadcast-group>
+ </broadcast-groups>
+
+ <discovery-groups>
+ <discovery-group name="dg-group1">
+ <group-address>231.7.7.7</group-address>
+ <group-port>9876</group-port>
+ <refresh-timeout>60000</refresh-timeout>
+ </discovery-group>
+ </discovery-groups>
+
+ <cluster-connections>
+ <cluster-connection name="my-cluster">
+ <address>jms</address>
+ <connector-ref>netty-connector</connector-ref>
+ <discovery-group-ref discovery-group-name="dg-group1"/>
+ </cluster-connection>
+ </cluster-connections>
+ <!-- Other config -->
+
+ <security-settings>
+ <!--security for example queue-->
+ <security-setting match="jms.queue.exampleQueue">
+ <permission type="createDurableQueue" roles="guest"/>
+ <permission type="deleteDurableQueue" roles="guest"/>
+ <permission type="createNonDurableQueue" roles="guest"/>
+ <permission type="deleteNonDurableQueue" roles="guest"/>
+ <permission type="consume" roles="guest"/>
+ <permission type="send" roles="guest"/>
+ </security-setting>
+ </security-settings>
+
+</configuration>
Added: trunk/examples/jms/stop-server-failover/server0/hornetq-jms.xml
===================================================================
--- trunk/examples/jms/stop-server-failover/server0/hornetq-jms.xml (rev 0)
+++ trunk/examples/jms/stop-server-failover/server0/hornetq-jms.xml 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,32 @@
+<configuration xmlns="urn:hornetq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd">
+ <!--the connection factory used by the example-->
+ <connection-factory name="ConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="netty-connector"/>
+ </connectors>
+
+ <entries>
+ <entry name="ConnectionFactory"/>
+ </entries>
+
+ <ha>true</ha>
+ <!-- Pause 1 second between connect attempts -->
+ <retry-interval>1000</retry-interval>
+
+ <!-- Multiply subsequent reconnect pauses by this multiplier. This can be used to
+ implement an exponential back-off. For our purposes we just set to 1.0 so each reconnect
+ pause is the same length -->
+ <retry-interval-multiplier>1.0</retry-interval-multiplier>
+
+ <!-- Try reconnecting an unlimited number of times (-1 means "unlimited") -->
+ <reconnect-attempts>-1</reconnect-attempts>
+ </connection-factory>
+
+ <!--the queue used by the example-->
+ <queue name="exampleQueue">
+ <entry name="/queue/exampleQueue"/>
+ </queue>
+
+</configuration>
Added: trunk/examples/jms/stop-server-failover/server0/hornetq-users.xml
===================================================================
--- trunk/examples/jms/stop-server-failover/server0/hornetq-users.xml (rev 0)
+++ trunk/examples/jms/stop-server-failover/server0/hornetq-users.xml 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,7 @@
+<configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd">
+ <!-- the default user. this is used where username is null-->
+ <defaultuser name="guest" password="guest">
+ <role name="guest"/>
+ </defaultuser>
+</configuration>
\ No newline at end of file
Added: trunk/examples/jms/stop-server-failover/server1/client-jndi.properties
===================================================================
--- trunk/examples/jms/stop-server-failover/server1/client-jndi.properties (rev 0)
+++ trunk/examples/jms/stop-server-failover/server1/client-jndi.properties 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,3 @@
+java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+java.naming.provider.url=jnp://localhost:2099
+java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
Added: trunk/examples/jms/stop-server-failover/server1/hornetq-beans.xml
===================================================================
--- trunk/examples/jms/stop-server-failover/server1/hornetq-beans.xml (rev 0)
+++ trunk/examples/jms/stop-server-failover/server1/hornetq-beans.xml 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Copyright 2009 Red Hat, Inc.
+ ~ Red Hat licenses this file to you under the Apache License, version
+ ~ 2.0 (the "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ ~ implied. See the License for the specific language governing
+ ~ permissions and limitations under the License.
+ -->
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="Naming" class="org.jnp.server.NamingBeanImpl"/>
+
+ <!-- JNDI server. Disable this if you don't want JNDI -->
+ <bean name="JNDIServer" class="org.jnp.server.Main">
+ <property name="namingInfo">
+ <inject bean="Naming"/>
+ </property>
+ <property name="port">2099</property>
+ <property name="bindAddress">localhost</property>
+ <property name="rmiPort">2098</property>
+ <property name="rmiBindAddress">localhost</property>
+ </bean>
+
+ <!-- MBean server -->
+ <bean name="MBeanServer" class="javax.management.MBeanServer">
+ <constructor factoryClass="java.lang.management.ManagementFactory"
+ factoryMethod="getPlatformMBeanServer"/>
+ </bean>
+
+ <!-- The core configuration -->
+ <bean name="Configuration" class="org.hornetq.core.config.impl.FileConfiguration"/>
+
+ <!-- The security manager -->
+ <bean name="HornetQSecurityManager" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl">
+ <start ignored="true"/>
+ <stop ignored="true"/>
+ </bean>
+
+ <!-- The core server -->
+ <bean name="HornetQServer" class="org.hornetq.core.server.impl.HornetQServerImpl">
+ <constructor>
+ <parameter>
+ <inject bean="Configuration"/>
+ </parameter>
+ <parameter>
+ <inject bean="MBeanServer"/>
+ </parameter>
+ <parameter>
+ <inject bean="HornetQSecurityManager"/>
+ </parameter>
+ </constructor>
+ <start ignored="true"/>
+ <stop ignored="true"/>
+ </bean>
+
+ <!-- The JMS server -->
+ <bean name="JMSServerManager" class="org.hornetq.jms.server.impl.JMSServerManagerImpl">
+ <constructor>
+ <parameter>
+ <inject bean="HornetQServer"/>
+ </parameter>
+ </constructor>
+ </bean>
+
+</deployment>
Added: trunk/examples/jms/stop-server-failover/server1/hornetq-configuration.xml
===================================================================
--- trunk/examples/jms/stop-server-failover/server1/hornetq-configuration.xml (rev 0)
+++ trunk/examples/jms/stop-server-failover/server1/hornetq-configuration.xml 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,75 @@
+<configuration xmlns="urn:hornetq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq ../../../src/schema/hornetq-configuration.xsd">
+
+ <clustered>true</clustered>
+
+ <backup>true</backup>
+
+ <!--we kill the server process so don't need this set to true-->
+ <failover-on-shutdown>false</failover-on-shutdown>
+
+ <shared-store>true</shared-store>
+
+ <!-- Connectors -->
+
+ <connectors>
+ <connector name="netty-connector">
+ <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
+ <param key="port" value="5446"/>
+ </connector>
+ </connectors>
+
+ <!-- Acceptors -->
+ <acceptors>
+ <acceptor name="netty-acceptor">
+ <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
+ <param key="port" value="5446"/>
+ </acceptor>
+ </acceptors>
+
+ <broadcast-groups>
+ <broadcast-group name="bg-group1">
+ <group-address>231.7.7.7</group-address>
+ <group-port>9876</group-port>
+ <broadcast-period>1000</broadcast-period>
+ <connector-ref>netty-connector</connector-ref>
+ </broadcast-group>
+ </broadcast-groups>
+
+ <discovery-groups>
+ <discovery-group name="dg-group1">
+ <group-address>231.7.7.7</group-address>
+ <group-port>9876</group-port>
+ <refresh-timeout>60000</refresh-timeout>
+ </discovery-group>
+ </discovery-groups>
+
+ <cluster-connections>
+ <cluster-connection name="my-cluster">
+ <address>jms</address>
+ <connector-ref>netty-connector</connector-ref>
+ <discovery-group-ref discovery-group-name="dg-group1"/>
+ </cluster-connection>
+ </cluster-connections>
+
+ <large-messages-directory>../server0/data/large-messages</large-messages-directory>
+ <bindings-directory>../server0/data/bindings</bindings-directory>
+ <journal-directory>../server0/data/journal</journal-directory>
+ <paging-directory>../server0/data/paging</paging-directory>
+
+ <!-- Other config -->
+
+ <security-settings>
+ <!--security for example queue-->
+ <security-setting match="jms.queue.exampleQueue">
+ <permission type="createDurableQueue" roles="guest"/>
+ <permission type="deleteDurableQueue" roles="guest"/>
+ <permission type="createNonDurableQueue" roles="guest"/>
+ <permission type="deleteNonDurableQueue" roles="guest"/>
+ <permission type="consume" roles="guest"/>
+ <permission type="send" roles="guest"/>
+ </security-setting>
+ </security-settings>
+
+</configuration>
Added: trunk/examples/jms/stop-server-failover/server1/hornetq-jms.xml
===================================================================
--- trunk/examples/jms/stop-server-failover/server1/hornetq-jms.xml (rev 0)
+++ trunk/examples/jms/stop-server-failover/server1/hornetq-jms.xml 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,32 @@
+<configuration xmlns="urn:hornetq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd">
+ <!--the connection factory used by the example-->
+ <connection-factory name="ConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="netty-connector"/>
+ </connectors>
+
+ <entries>
+ <entry name="ConnectionFactory"/>
+ </entries>
+
+ <ha>true</ha>
+ <!-- Pause 1 second between connect attempts -->
+ <retry-interval>1000</retry-interval>
+
+ <!-- Multiply subsequent reconnect pauses by this multiplier. This can be used to
+ implement an exponential back-off. For our purposes we just set to 1.0 so each reconnect
+ pause is the same length -->
+ <retry-interval-multiplier>1.0</retry-interval-multiplier>
+
+ <!-- Try reconnecting an unlimited number of times (-1 means "unlimited") -->
+ <reconnect-attempts>-1</reconnect-attempts>
+ </connection-factory>
+
+ <!--the queue used by the example-->
+ <queue name="exampleQueue">
+ <entry name="/queue/exampleQueue"/>
+ </queue>
+
+</configuration>
Added: trunk/examples/jms/stop-server-failover/server1/hornetq-users.xml
===================================================================
--- trunk/examples/jms/stop-server-failover/server1/hornetq-users.xml (rev 0)
+++ trunk/examples/jms/stop-server-failover/server1/hornetq-users.xml 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,7 @@
+<configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd">
+ <!-- the default user. this is used where username is null-->
+ <defaultuser name="guest" password="guest">
+ <role name="guest"/>
+ </defaultuser>
+</configuration>
\ No newline at end of file
Added: trunk/examples/jms/stop-server-failover/src/org/hornetq/jms/example/StopServerFailoverExample.java
===================================================================
--- trunk/examples/jms/stop-server-failover/src/org/hornetq/jms/example/StopServerFailoverExample.java (rev 0)
+++ trunk/examples/jms/stop-server-failover/src/org/hornetq/jms/example/StopServerFailoverExample.java 2010-12-08 09:53:15 UTC (rev 10013)
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.hornetq.jms.example;
+
+import org.hornetq.common.example.HornetQExample;
+
+import javax.jms.*;
+import javax.naming.InitialContext;
+
+/**
+ * A simple example that demonstrates failover of the JMS connection from one node to another
+ * when the live server crashes using a JMS <em>non-transacted</em> session.
+ *
+ * @author <a href="mailto:jmesnil@redhat.com">Jeff Mesnil</a>
+ */
+public class StopServerFailoverExample extends HornetQExample
+{
+ public static void main(final String[] args)
+ {
+ new StopServerFailoverExample().run(args);
+ }
+
+ @Override
+ public boolean runExample() throws Exception
+ {
+ final int numMessages = 10;
+
+ Connection connection = null;
+
+ InitialContext initialContext = null;
+
+ try
+ {
+ // Step 1. Get an initial context for looking up JNDI from the server #1
+ initialContext = getContext(0);
+
+ // Step 2. Look up the JMS resources from JNDI
+ Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");
+ ConnectionFactory connectionFactory = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
+
+ // Step 3. Create a JMS Connection
+ connection = connectionFactory.createConnection();
+
+ // Step 4. Create a *non-transacted* JMS Session with client acknwoledgement
+ Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+ // Step 5. Start the connection to ensure delivery occurs
+ connection.start();
+
+ // Step 6. Create a JMS MessageProducer and a MessageConsumer
+ MessageProducer producer = session.createProducer(queue);
+ MessageConsumer consumer = session.createConsumer(queue);
+
+ // Step 7. Send some messages to server #1, the live server
+ for (int i = 0; i < numMessages; i++)
+ {
+ TextMessage message = session.createTextMessage("This is text message " + i);
+ producer.send(message);
+ System.out.println("Sent message: " + message.getText());
+ }
+
+ // Step 8. Receive and acknowledge half of the sent messages
+ TextMessage message0 = null;
+ for (int i = 0; i < numMessages / 2; i++)
+ {
+ message0 = (TextMessage)consumer.receive(5000);
+ System.out.println("Got message: " + message0.getText());
+ }
+ message0.acknowledge();
+
+ // Step 9. Receive the 2nd half of the sent messages but *do not* acknowledge them yet
+ for (int i = numMessages / 2; i < numMessages; i++)
+ {
+ message0 = (TextMessage)consumer.receive(5000);
+ System.out.println("Got message: " + message0.getText());
+ }
+
+ // Step 10. Crash server #1, the live server, and wait a little while to make sure
+ // it has really crashed
+ Thread.sleep(2000);
+ System.out.println("stop the server by logging into jconsole");
+ System.in.read();
+
+ // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the
+ // backup server has occured
+ try
+ {
+ message0.acknowledge();
+ }
+ catch (JMSException e)
+ {
+ System.err.println("Got exception while acknowledging message: " + e.getMessage());
+ }
+
+ // Step 12. Consume again the 2nd half of the messages again. Note that they are not considered as redelivered.
+ for (int i = numMessages / 2; i < numMessages; i++)
+ {
+ message0 = (TextMessage)consumer.receive(5000);
+ System.out.printf("Got message: %s (redelivered?: %s)\n", message0.getText(), message0.getJMSRedelivered());
+ }
+ message0.acknowledge();
+
+ return true;
+ }
+ finally
+ {
+ // Step 13. Be sure to close our resources!
+
+ if (connection != null)
+ {
+ connection.close();
+ }
+
+ if (initialContext != null)
+ {
+ initialContext.close();
+ }
+ }
+ }
+
+}
15 years, 5 months
JBoss hornetq SVN: r10012 - trunk/examples/jms/non-transaction-failover/server1.
by do-not-reply@jboss.org
Author: ataylor
Date: 2010-12-08 03:55:48 -0500 (Wed, 08 Dec 2010)
New Revision: 10012
Removed:
trunk/examples/jms/non-transaction-failover/server1/KILL_ME
Log:
removed unwanted KILL_ME file
Deleted: trunk/examples/jms/non-transaction-failover/server1/KILL_ME
===================================================================
15 years, 5 months