[jboss-cvs] JBoss Messaging SVN: r6431 - in trunk: examples/jms and 21 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Apr 15 08:27:48 EDT 2009


Author: timfox
Date: 2009-04-15 08:27:47 -0400 (Wed, 15 Apr 2009)
New Revision: 6431

Added:
   trunk/examples/jms/reconnect-same-node/
   trunk/examples/jms/reconnect-same-node/build.xml
   trunk/examples/jms/reconnect-same-node/readme.html
   trunk/examples/jms/reconnect-same-node/server0/
   trunk/examples/jms/reconnect-same-node/server0/client-jndi.properties
   trunk/examples/jms/reconnect-same-node/server0/jbm-configuration.xml
   trunk/examples/jms/reconnect-same-node/server0/jbm-jms.xml
   trunk/examples/jms/reconnect-same-node/server0/jbm-queues.xml
   trunk/examples/jms/reconnect-same-node/server0/jbm-security.xml
   trunk/examples/jms/reconnect-same-node/server0/jbm-standalone-beans.xml
   trunk/examples/jms/reconnect-same-node/src/
   trunk/examples/jms/reconnect-same-node/src/org/
   trunk/examples/jms/reconnect-same-node/src/org/jboss/
   trunk/examples/jms/reconnect-same-node/src/org/jboss/jms/
   trunk/examples/jms/reconnect-same-node/src/org/jboss/jms/example/
   trunk/examples/jms/reconnect-same-node/src/org/jboss/jms/example/ReconnectSameNodeExample.java
Modified:
   trunk/.classpath
   trunk/examples/jms/clustered-durable-subscription/src/org/jboss/jms/example/ClusteredDurableSubscriptionExample.java
   trunk/examples/jms/clustered-queue/src/org/jboss/jms/example/ClusteredQueueExample.java
   trunk/examples/jms/clustered-topic/src/org/jboss/jms/example/ClusteredTopicExample.java
   trunk/examples/jms/common/src/org/jboss/jms/example/JMSExample.java
   trunk/examples/jms/queue/src/org/jboss/jms/example/QueueExample.java
   trunk/src/main/org/jboss/messaging/core/client/impl/ConnectionManagerImpl.java
   trunk/src/main/org/jboss/messaging/core/deployers/impl/AddressSettingsDeployer.java
   trunk/src/main/org/jboss/messaging/core/management/impl/ManagementServiceImpl.java
   trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java
   trunk/src/main/org/jboss/messaging/integration/transports/netty/NettyAcceptor.java
   trunk/src/main/org/jboss/messaging/jms/server/impl/JMSServerDeployer.java
   trunk/src/main/org/jboss/messaging/jms/server/management/impl/JMSManagementHelper.java
   trunk/src/schemas/jbm-configuration.xsd
   trunk/src/schemas/jbm-jms.xsd
   trunk/tests/src/org/jboss/messaging/tests/integration/cluster/failover/ReconnectTest.java
Log:
reconnect example

Modified: trunk/.classpath
===================================================================
--- trunk/.classpath	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/.classpath	2009-04-15 12:27:47 UTC (rev 6431)
@@ -26,6 +26,7 @@
 	<classpathentry kind="src" path="examples/jms/clustered-durable-subscription/src"/>
 	<classpathentry kind="src" path="examples/jms/queue-message-redistribution/src"/>
 	<classpathentry kind="src" path="examples/jms/client-side-load-balancing/src"/>
+	<classpathentry kind="src" path="examples/jms/reconnect-same-node/src"/>
 	<classpathentry kind="src" path="examples/jms/browser/src"/>
 	<classpathentry kind="src" path="examples/jms/durable-subscription/src"/>
 	<classpathentry kind="src" path="examples/jms/common/src"/>

Modified: trunk/examples/jms/clustered-durable-subscription/src/org/jboss/jms/example/ClusteredDurableSubscriptionExample.java
===================================================================
--- trunk/examples/jms/clustered-durable-subscription/src/org/jboss/jms/example/ClusteredDurableSubscriptionExample.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/examples/jms/clustered-durable-subscription/src/org/jboss/jms/example/ClusteredDurableSubscriptionExample.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -36,6 +36,7 @@
  * The same durable subscription can exist on more than one node of the cluster, and messages
  * sent to the topic will be load-balanced in a round-robin fashion between the two nodes
  *
+ * @author <a href="tim.fox at jboss.com>Tim Fox</a>
  */
 public class ClusteredDurableSubscriptionExample extends JMSExample
 {

Modified: trunk/examples/jms/clustered-queue/src/org/jboss/jms/example/ClusteredQueueExample.java
===================================================================
--- trunk/examples/jms/clustered-queue/src/org/jboss/jms/example/ClusteredQueueExample.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/examples/jms/clustered-queue/src/org/jboss/jms/example/ClusteredQueueExample.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -23,7 +23,6 @@
 
 import javax.jms.Connection;
 import javax.jms.ConnectionFactory;
-import javax.jms.Message;
 import javax.jms.MessageConsumer;
 import javax.jms.MessageProducer;
 import javax.jms.Queue;

Modified: trunk/examples/jms/clustered-topic/src/org/jboss/jms/example/ClusteredTopicExample.java
===================================================================
--- trunk/examples/jms/clustered-topic/src/org/jboss/jms/example/ClusteredTopicExample.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/examples/jms/clustered-topic/src/org/jboss/jms/example/ClusteredTopicExample.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -34,6 +34,7 @@
  * A simple example that shows a JMS Topic clustered across two nodes of a cluster.
  * Messages are sent on one node and received by consumers on both nodes.
  *
+ * @author <a href="tim.fox at jboss.com>Tim Fox</a>
  */
 public class ClusteredTopicExample extends JMSExample
 {

Modified: trunk/examples/jms/common/src/org/jboss/jms/example/JMSExample.java
===================================================================
--- trunk/examples/jms/common/src/org/jboss/jms/example/JMSExample.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/examples/jms/common/src/org/jboss/jms/example/JMSExample.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -23,8 +23,6 @@
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Properties;
 import java.util.logging.Logger;
 
@@ -48,20 +46,38 @@
    private boolean failure = false;
 
    public abstract boolean runExample() throws Exception;
-
-   protected void run(String[] serverVMArgs, String[] args)
+   
+   private boolean logServerOutput;
+   
+   private String[] allVMArgs;
+   
+   private String[] configs;
+   
+   protected void run(String[] serverVMArgs, String[] configs)
    {
       String runServerProp = System.getProperty("jbm.example.runServer");
       String logServerOutputProp = System.getProperty("jbm.example.logserveroutput");
       boolean runServer = runServerProp == null ? true : Boolean.valueOf(runServerProp);
-      boolean logServerOutput = logServerOutputProp == null?false:Boolean.valueOf(logServerOutputProp);
+      logServerOutput = logServerOutputProp == null?false:Boolean.valueOf(logServerOutputProp);
       log.info("jbm.example.runServer is " + runServer);
+            
+      allVMArgs = new String[serverVMArgs == null ? 1 : serverVMArgs.length + 1];
+      if (serverVMArgs != null)
+      {
+         System.arraycopy(serverVMArgs, 0, allVMArgs, 0, serverVMArgs.length);
+      }      
+      String logProps = System.getProperty("java.util.logging.config.file");
+      allVMArgs[allVMArgs.length - 1] = "-Djava.util.logging.config.file=" + logProps;
+      
+      this.configs = configs;
+
       try
       {
          if (runServer)
          {
-            startServers(serverVMArgs, args, logServerOutput);
+            startServers();
          }
+         
          if (!runExample())
          {
             failure = true;
@@ -89,7 +105,7 @@
          {
             try
             {
-               stopServer();
+               stopServers();
             }
             catch (Throwable throwable)
             {
@@ -117,6 +133,13 @@
       file.createNewFile();
    }
    
+   protected void stopServer(int id) throws Exception 
+   {
+      System.out.println("Stopping server " + id);
+      
+      stopServer(servers[id]);
+   }
+   
    protected InitialContext getContext(int serverId) throws Exception
    {
       String jndiFilename = "server" + serverId + "/client-jndi.properties";
@@ -138,52 +161,52 @@
       }
       return new InitialContext(props);
    }
-  
-   private void startServers(String[] vmArgs, String[] args, boolean logServerOutput) throws Throwable
+   
+   protected void startServer(int index) throws Exception
    {
-      List<String> allVMArgsList = new ArrayList<String>();
-      if (vmArgs != null)
+      String config = configs[index];
+      log.info("starting server with config '" + config + "' " + "logServerOutput " + logServerOutput);
+      servers[index] = SpawnedVMSupport.spawnVM(
+            SpawnedJMSServer.class.getName(),
+            allVMArgs,
+            logServerOutput,
+            "STARTED::",
+            "FAILED::",
+            config,
+            "jbm-standalone-beans.xml");   
+   }
+   
+   private void startServers() throws Exception
+   {     
+      servers = new Process[configs.length];
+      for (int i = 0; i < configs.length; i++)
       {
-         for (String arg : vmArgs)
-         {
-            allVMArgsList.add(arg);
-         }
-      }
-      String logProps = System.getProperty("java.util.logging.config.file");
-      allVMArgsList.add("-Djava.util.logging.config.file=" + logProps);
-      String[] allVMArgs = (String[])allVMArgsList.toArray(new String[allVMArgsList.size()]);
-      
-      servers = new Process[args.length];
-      for (int i = 0; i < args.length; i++)
-      {
-         log.info("starting server with config '" + args[i] + "' " + "logServerOutput " + logServerOutput);
-         servers[i] = SpawnedVMSupport.spawnVM(
-               SpawnedJMSServer.class.getName(),
-               allVMArgs,
-               logServerOutput,
-               "STARTED::",
-               "FAILED::",
-               args[i],
-               "jbm-standalone-beans.xml");
+         startServer(i);
       }      
    }
-
-   private void stopServer() throws Throwable
+   
+   private void stopServers() throws Exception
    {
       for (Process server : servers)
       {
-         if (server.getInputStream() != null)
-         {
-            server.getInputStream().close();
-         }
-         if (server.getErrorStream() != null)
-         {
-            server.getErrorStream().close();
-         }
-         server.destroy();
+         stopServer(server);
       }
    }
    
+   private void stopServer(Process server) throws Exception
+   {
+      if (server.getInputStream() != null)
+      {
+         server.getInputStream().close();
+      }
+      if (server.getErrorStream() != null)
+      {
+         server.getErrorStream().close();
+      }
+      server.destroy();
+   }
+
+   
    private void reportResultAndExit()
    {
       if (failure)

Modified: trunk/examples/jms/queue/src/org/jboss/jms/example/QueueExample.java
===================================================================
--- trunk/examples/jms/queue/src/org/jboss/jms/example/QueueExample.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/examples/jms/queue/src/org/jboss/jms/example/QueueExample.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -85,8 +85,6 @@
 
          System.out.println("Received message: " + messageReceived.getText());
 
-         initialContext.close();
-         
          return true;
       }
       finally

Added: trunk/examples/jms/reconnect-same-node/build.xml
===================================================================
--- trunk/examples/jms/reconnect-same-node/build.xml	                        (rev 0)
+++ trunk/examples/jms/reconnect-same-node/build.xml	2009-04-15 12:27:47 UTC (rev 6431)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE project [
+      <!ENTITY libraries SYSTEM "../../../thirdparty/libraries.ent">
+      ]>
+
+<!-- =========================================================================================== -->
+<!--                                                                                             -->
+<!-- JBoss, Home of Professional Open Source                                                     -->
+<!-- Copyright 2005, JBoss Inc., and individual contributors as indicated                        -->
+<!-- by the @authors tag. See the copyright.txt in the distribution for a                        -->
+<!-- full listing of individual contributors.                                                    -->
+<!--                                                                                             -->
+<!-- This is free software; you can redistribute it and/or modify it                             -->
+<!-- under the terms of the GNU Lesser General Public License as                                 -->
+<!-- published by the Free Software Foundation; either version 2.1 of                            -->
+<!-- the License, or (at your option) any later version.                                         -->
+<!--                                                                                             -->
+<!-- This software is distributed in the hope that it will be useful,                            -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of                              -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU                            -->
+<!-- Lesser General Public License for more details.                                             -->
+<!--                                                                                             -->
+<!-- You should have received a copy of the GNU Lesser General Public                            -->
+<!-- License along with this software; if not, write to the Free                                 -->
+<!-- Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA                          -->
+<!-- 02110-1301 USA, or see the FSF site: http://www.fsf.org.                                    -->
+<!--                                                                                             -->
+<!-- =========================================================================================== -->
+
+
+<project default="run" name="JBoss Messaging Reconnect Same Node Example">
+
+   <import file="../common/build.xml"/>
+
+   <target name="run">
+      <antcall target="runExample">
+         <param name="example.classname" value="org.jboss.jms.example.ReconnectSameNodeExample"/>
+      </antcall>
+   </target>
+
+   <target name="runRemote">
+      <antcall target="runExample">
+         <param name="example.classname" value="org.jboss.jms.example.ReconnectSameNodeExample"/>
+         <param name="jbm.example.runServer" value="false"/>
+      </antcall>
+   </target>
+
+</project>
\ No newline at end of file

Added: trunk/examples/jms/reconnect-same-node/readme.html
===================================================================
--- trunk/examples/jms/reconnect-same-node/readme.html	                        (rev 0)
+++ trunk/examples/jms/reconnect-same-node/readme.html	2009-04-15 12:27:47 UTC (rev 6431)
@@ -0,0 +1,134 @@
+<html>
+  <head>
+    <title>JBoss Messaging JMS Automatic Reconnect Same Server Example</title>
+    <link rel="stylesheet" type="text/css" href="../common/common.css">
+  </head>
+  <body>
+     <h1>JBoss Messaging JMS Reconnect Same Server Example</h1>
+     <br>
+     <p>This example demonstrates how JBoss Messaging connections can be configured to be resilient to
+     temporary network failures.</p>
+     <p>In the case of a network failure being detected, either as a result of a failure to read/write to the connection,
+     or the failure of a pong to arrive back from the server in good time after a ping is sent, instead of
+     failing the connection immediately and notifying any user ExceptionListener objects, JBoss Messaging
+     can be configured to automatically retry the connection, and reconnect to the server when it becomes
+     available again across the network.</p>
+     <p>In the case that the server didn't actually crash, i.e. the network was temporarily unavailable, the client will
+     be able to resume all its sessions and connections where it left off, 100% transparently.</p>
+     <p>This is very similar to automatic failover, the difference being with automatic failover the reconnection
+     is to a different server, but in this cases the reconnection is to the <b>same</b> server</p>
+     <p>In the case that the server <b>did</b> crash and was restarted, on reconnection the server session
+     clearly won't still exist, so the session will be unable to continue transparently, and any registered
+     ExceptionListener will be called, to allow any application layer reconnect logic to be called.</p>
+     <p>This example starts a single server, connects to it and performs some JMS operations. We then
+     simulate failure of the network connection by temporarily stopping the network acceptor on the server.
+     (This is done by sending management messages, but that is not central to the purpose of the example).</p>
+     <p>We then wait a few seconds, then restart the acceptor. The client reconnects and the session resumes
+     as if nothing happened.</p>
+     <p>The JMS Connection Factory is configured to reconnect automatically by specifying the various reconnect
+     related attributes in the <code>jbm-jms.xml</code> file.</p>  
+             
+     <p>For more details on how to configure this and for clustering in general
+     please consult the JBoss Messaging user manual.</p>
+          
+     <br>
+     <h2>Example step-by-step</h2>
+     <p><i>To run the example, simply type <code>ant</code> from this directory</i></p>
+     <br>
+     <ol>
+        <li>Create an initial context to perform the JNDI lookup.</li>
+        <pre>
+           <code>initialContext = getContext(0);</code>
+        </pre>
+
+        <li>Perform a lookup on the queue</li>
+        <pre>
+           <code>Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");</code>
+        </pre>
+
+        <li>Perform a lookup on the Connection Factory</li>
+        <pre>
+           <code>ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");</code>
+        </pre>
+
+        <li>We create a JMS connection</li>
+        <pre>
+           <code>connection = cf.createConnection();</code>
+        </pre>
+
+        <li>We create a JMS session. </li>
+        <pre>
+           <code>Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);</code>
+        </pre>
+
+        <li>We create a JMS message producer.</li>
+        <pre>
+          <code>MessageProducer messageProducer = session.createProducer(topic);</code>
+       </pre>
+
+        <li>We create a JMS text message that we are going to send.</li>
+        <pre>
+           <code>TextMessage message = session.createTextMessage("This is a text message");</code>
+        </pre>
+
+        <li>We send message to the queue</li>
+        <pre>
+           <code>messageProducer.send(message);</code>
+        </pre>
+
+        <li>We create a JMS Message Consumer to receive the message.</li>
+          <pre>
+           <code>MessageConsumer messageConsumer = session.createConsumer(queue);</code>
+        </pre>
+
+        <li>We start the connection. In order for delivery to occur on any consumers or subscribers on a connection, the connection must be started</li>
+        <pre>
+           <code>connection.start();</code>
+        </pre>
+
+        <li>To simulate a temporary problem on the network, we stop the remoting acceptor on the
+         server which will casue all client connections to fail.</li>
+        <pre>
+           <code>stopAcceptor(initialContext);</code>
+        </pre>
+        
+        <li>We wait 10 seconds, before restarting the acceptor. During this period the client will be retrying
+        to connect. When the acceptor is restarted it will be successful in reconnecting.</li>
+        
+        <pre>
+           <code>
+            Thread.sleep(10000);
+
+            startAcceptor(initialContext);
+           </code>
+        </pre>
+        
+        <li>We receive the message after reconnection! Note that no exceptions were received by the client.</li>
+        
+        <pre>
+           <code>
+           TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000);
+           </code>
+        </pre>
+
+        <li>And finally, <b>always</b> remember to close your JMS connections and 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>
+           <code>finally
+           {
+              if (initialContext != null)
+              {
+                initialContext.close();
+              }
+              if (connection != null)
+              {
+                 connection.close();
+              }
+           }</code>
+        </pre>
+
+
+
+     </ol>
+  </body>
+</html>
\ No newline at end of file

Added: trunk/examples/jms/reconnect-same-node/server0/client-jndi.properties
===================================================================
--- trunk/examples/jms/reconnect-same-node/server0/client-jndi.properties	                        (rev 0)
+++ trunk/examples/jms/reconnect-same-node/server0/client-jndi.properties	2009-04-15 12:27:47 UTC (rev 6431)
@@ -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/reconnect-same-node/server0/jbm-configuration.xml
===================================================================
--- trunk/examples/jms/reconnect-same-node/server0/jbm-configuration.xml	                        (rev 0)
+++ trunk/examples/jms/reconnect-same-node/server0/jbm-configuration.xml	2009-04-15 12:27:47 UTC (rev 6431)
@@ -0,0 +1,40 @@
+<deployment xmlns="urn:jboss:messaging"
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+            xsi:schemaLocation="urn:jboss:messaging ../schemas/jbm-configuration.xsd">
+   <configuration>
+
+      <!-- Connectors -->
+
+      <connector name="netty-connector">
+         <factory-class>org.jboss.messaging.integration.transports.netty.NettyConnectorFactory</factory-class>
+         <param key="jbm.remoting.netty.port" value="5445" type="Integer"/>
+      </connector>
+      
+      <!-- We just use this connector so we can send management operations while the other acceptor
+      is stopped -->
+	   <connector name="netty-connector2">
+         <factory-class>org.jboss.messaging.integration.transports.netty.NettyConnectorFactory</factory-class>
+         <param key="jbm.remoting.netty.port" value="5446" type="Integer"/>
+      </connector>
+
+      <!-- Acceptors -->
+
+      <acceptor name="netty-acceptor">
+         <factory-class>org.jboss.messaging.integration.transports.netty.NettyAcceptorFactory</factory-class>
+         <param key="jbm.remoting.netty.port" value="5445" type="Integer"/>
+      </acceptor>
+
+      <!-- We just use this acceptor so we can send management operations while the other acceptor
+      is stopped -->
+      <acceptor name="netty-acceptor2">
+         <factory-class>org.jboss.messaging.integration.transports.netty.NettyAcceptorFactory</factory-class>
+         <param key="jbm.remoting.netty.port" value="5446" type="Integer"/>
+      </acceptor>
+
+      <!-- Other config -->
+
+      <journal-min-files>2</journal-min-files>
+
+   </configuration>
+
+</deployment>

Added: trunk/examples/jms/reconnect-same-node/server0/jbm-jms.xml
===================================================================
--- trunk/examples/jms/reconnect-same-node/server0/jbm-jms.xml	                        (rev 0)
+++ trunk/examples/jms/reconnect-same-node/server0/jbm-jms.xml	2009-04-15 12:27:47 UTC (rev 6431)
@@ -0,0 +1,40 @@
+<deployment xmlns="urn:jboss:messaging"
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+            xsi:schemaLocation="urn:jboss:messaging ../schemas/jbm-jms.xsd ">
+   <!--the connection factory used by the example-->
+   <connection-factory name="ConnectionFactory">
+      <connector-ref connector-name="netty-connector"/>
+      <entry name="ConnectionFactory"/>
+      <entry name="XAConnectionFactory"/>
+      <entry name="java:/ConnectionFactory"/>
+      <entry name="java:/XAConnectionFactory"/>
+                  
+      <!-- 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>
+      
+      <!-- When the server is cleanly shutdown we don't want to give up, we want to continue
+      to try to reconnect -->
+      <failover-on-server-shutdown>true</failover-on-server-shutdown>
+      
+   </connection-factory>
+   
+   <!-- This is used by the example to send the management operations, it's not central to the example -->
+   <connection-factory name="ConnectionFactory2">
+      <connector-ref connector-name="netty-connector2"/>
+      <entry name="ConnectionFactory2"/>                     
+   </connection-factory>
+
+   <!--the queue used by the example-->
+   <queue name="exampleQueue">
+      <entry name="/queue/exampleQueue"/>
+   </queue>
+
+</deployment>
\ No newline at end of file

Added: trunk/examples/jms/reconnect-same-node/server0/jbm-queues.xml
===================================================================
--- trunk/examples/jms/reconnect-same-node/server0/jbm-queues.xml	                        (rev 0)
+++ trunk/examples/jms/reconnect-same-node/server0/jbm-queues.xml	2009-04-15 12:27:47 UTC (rev 6431)
@@ -0,0 +1,22 @@
+<settings xmlns="urn:jboss:messaging"
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+            xsi:schemaLocation="urn:jboss:messaging ../schemas/jbm-queues.xsd ">
+
+   <!--security for example queue-->
+   <security match="jms.queue.exampleQueue">
+      <permission type="createDurableQueue" roles="guest"/>
+      <permission type="deleteDurableQueue" roles="guest"/>
+      <permission type="createTempQueue" roles="guest"/>
+      <permission type="deleteTempQueue" roles="guest"/>
+      <permission type="consume" roles="guest"/>
+      <permission type="send" roles="guest"/>
+   </security>
+   
+   <security match="jbm.management">
+      <!--  only the admin role can interact with the management address  -->
+      <permission type="consume" roles="admin"/>
+      <permission type="send" roles="admin"/>
+      <permission type="manage" roles="admin"/>
+   </security>
+
+</settings>

Added: trunk/examples/jms/reconnect-same-node/server0/jbm-security.xml
===================================================================
--- trunk/examples/jms/reconnect-same-node/server0/jbm-security.xml	                        (rev 0)
+++ trunk/examples/jms/reconnect-same-node/server0/jbm-security.xml	2009-04-15 12:27:47 UTC (rev 6431)
@@ -0,0 +1,11 @@
+<deployment xmlns="urn:jboss:messaging" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+            xsi:schemaLocation="urn:jboss:messaging ../schemas/jbm-security.xsd ">
+   <!-- the default user.  this is used where username is null-->
+   <defaultuser name="guest" password="guest">
+      <role name="guest"/>
+      
+      <!-- We give guest the admin role so it can do management operations for the example -
+      you don't want to do this in real life -->
+      <role name="admin"/>
+   </defaultuser>
+</deployment>
\ No newline at end of file

Added: trunk/examples/jms/reconnect-same-node/server0/jbm-standalone-beans.xml
===================================================================
--- trunk/examples/jms/reconnect-same-node/server0/jbm-standalone-beans.xml	                        (rev 0)
+++ trunk/examples/jms/reconnect-same-node/server0/jbm-standalone-beans.xml	2009-04-15 12:27:47 UTC (rev 6431)
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<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.jboss.messaging.core.config.impl.FileConfiguration"/>
+
+   <!-- The security manager -->
+   <bean name="JBMSecurityManager" class="org.jboss.messaging.core.security.impl.JBMSecurityManagerImpl">
+      <start ignored="true"/>
+      <stop ignored="true"/>
+   </bean>
+
+   <!-- The core server -->
+   <bean name="MessagingServer" class="org.jboss.messaging.core.server.impl.MessagingServerImpl"> 
+      <constructor>
+         <parameter>
+            <inject bean="Configuration"/>
+         </parameter>
+         <parameter>
+            <inject bean="MBeanServer"/>
+         </parameter>
+         <parameter>
+            <inject bean="JBMSecurityManager"/>
+         </parameter>        
+      </constructor>         
+   </bean>
+   
+   <!-- The JMS server -->
+   <bean name="JMSServerManager" class="org.jboss.messaging.jms.server.impl.JMSServerManagerImpl">
+      <constructor>         
+         <parameter>
+            <inject bean="MessagingServer"/>
+         </parameter>
+      </constructor>
+   </bean>
+
+</deployment>

Added: trunk/examples/jms/reconnect-same-node/src/org/jboss/jms/example/ReconnectSameNodeExample.java
===================================================================
--- trunk/examples/jms/reconnect-same-node/src/org/jboss/jms/example/ReconnectSameNodeExample.java	                        (rev 0)
+++ trunk/examples/jms/reconnect-same-node/src/org/jboss/jms/example/ReconnectSameNodeExample.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -0,0 +1,174 @@
+/*
+   * JBoss, Home of Professional Open Source
+   * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
+   * by the @authors tag. See the copyright.txt in the distribution for a
+   * full listing of individual contributors.
+   *
+   * This is free software; you can redistribute it and/or modify it
+   * under the terms of the GNU Lesser General Public License as
+   * published by the Free Software Foundation; either version 2.1 of
+   * the License, or (at your option) any later version.
+   *
+   * This software is distributed in the hope that it will be useful,
+   * but WITHOUT ANY WARRANTY; without even the implied warranty of
+   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   * Lesser General Public License for more details.
+   *
+   * You should have received a copy of the GNU Lesser General Public
+   * License along with this software; if not, write to the Free
+   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+   */
+package org.jboss.jms.example;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.naming.InitialContext;
+
+import org.jboss.messaging.jms.JBossQueue;
+import org.jboss.messaging.jms.server.management.impl.JMSManagementHelper;
+
+/**
+ * This examples demonstrates a connection created to a server. Failure of the network connection is then simulated
+ * 
+ * The network is brought back up and the client reconnects and resumes transparently.
+ *
+ * @author <a href="tim.fox at jboss.com>Tim Fox</a>
+ */
+public class ReconnectSameNodeExample extends JMSExample
+{
+   public static void main(String[] args)
+   {
+      new ReconnectSameNodeExample().run(args);
+   }
+
+   public boolean runExample() throws Exception
+   {
+      Connection connection = null;
+      InitialContext initialContext = null;
+
+      try
+      {
+         // Step 1. Create an initial context to perform the JNDI lookup.
+         initialContext = getContext(0);
+
+         // Step 2. Perform a lookup on the queue
+         Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");
+
+         // Step 3. Perform a lookup on the Connection Factory
+         ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
+
+         // Step 4. Create a JMS Connection
+         connection = cf.createConnection();
+
+         // Step 5. Create a JMS Session
+         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+         // Step 6. Create a JMS Message Producer
+         MessageProducer producer = session.createProducer(queue);
+
+         // Step 7. Create a Text Message
+         TextMessage message = session.createTextMessage("This is a text message");
+
+         System.out.println("Sent message: " + message.getText());
+
+         // Step 8. Send the Message
+         producer.send(message);
+
+         // Step 9. Create a JMS Message Consumer
+         MessageConsumer messageConsumer = session.createConsumer(queue);
+
+         // Step 10. Start the Connection
+         connection.start();
+
+         // Step 11. To simulate a temporary problem on the network, we stop the remoting acceptor on the
+         // server which will close all connections
+         stopAcceptor(initialContext);
+
+         System.out.println("Acceptor now stopped, will wait for 10 seconds. This simulates the network connection failing for a while");
+
+         // Step 12. Wait a while then restart the acceptor
+         Thread.sleep(10000);
+
+         System.out.println("Re-starting acceptor");
+
+         startAcceptor(initialContext);
+
+         System.out.println("Restarted acceptor. The client will now reconnect.");
+
+         // Step 13. We receive the message
+         TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000);
+
+         System.out.println("Received message: " + messageReceived.getText());
+
+         return true;
+      }
+      finally
+      {
+         // Step 14. Be sure to close our JMS resources!
+         if (initialContext != null)
+         {
+            initialContext.close();
+         }
+
+         if (connection != null)
+         {
+            connection.close();
+         }
+      }
+   }
+
+   private void stopAcceptor(InitialContext ic) throws Exception
+   {
+      this.stopStartAcceptor(ic, true);
+   }
+
+   private void startAcceptor(InitialContext ic) throws Exception
+   {
+      this.stopStartAcceptor(ic, false);
+   }
+
+   // To do this we send a management message to close the acceptor, we do this on a different
+   // connection factory which uses a different remoting connection so we can still send messages
+   // when the main connection has been stopped
+   private void stopStartAcceptor(InitialContext initialContext, boolean stop) throws Exception
+   {
+      ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory2");
+
+      Connection connection = null;
+      try
+      {
+         connection = cf.createConnection();
+
+         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+         Queue managementQueue = new JBossQueue("jbm.management", "jbm.management");
+
+         MessageProducer producer = session.createProducer(managementQueue);
+
+         connection.start();
+
+         Message m = session.createMessage();
+
+         String oper = stop ? "stop" : "start";
+
+         JMSManagementHelper.putOperationInvocation(m, "core.acceptor.netty-acceptor", oper);
+
+         producer.send(m);
+      }
+      finally
+      {
+         if (connection != null)
+         {
+            connection.close();
+         }
+      }
+   }
+
+}

Modified: trunk/src/main/org/jboss/messaging/core/client/impl/ConnectionManagerImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/client/impl/ConnectionManagerImpl.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/src/main/org/jboss/messaging/core/client/impl/ConnectionManagerImpl.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -150,8 +150,6 @@
 
    private boolean inFailoverOrReconnect;
 
-   private volatile boolean failureSignalled;
-
    // debug
 
    private static Map<TransportConfiguration, Set<RemotingConnection>> debugConns;
@@ -278,21 +276,9 @@
 
                   if (connection == null)
                   {
-                     if (!failureSignalled)
-                     {
-                        // This can happen if the connection manager gets closed - e.g. the server gets shut down
+                     // This can happen if the connection manager gets closed - e.g. the server gets shut down
 
-                        throw new MessagingException(MessagingException.NOT_CONNECTED, "Unable to connect to server");
-                     }
-                     else
-                     {
-                        // This means an async failure came in while getConnectionForCreateSession was executing, we
-                        // need
-                        // to allow the failover/reconnection to occur and let the create session retry after
-                        retry = true;
-
-                        continue;
-                     }
+                     throw new MessagingException(MessagingException.NOT_CONNECTED, "Unable to connect to server");
                   }
 
                   channel1 = connection.getChannel(1, -1, false);
@@ -468,10 +454,8 @@
    // --------------------------------------------------------------------------------------
 
    private boolean handleConnectionFailure(final MessagingException me, final Object connectionID)
-   {
-      boolean callNext = !failoverOrReconnect(me, connectionID);
-
-      return callNext;
+   {     
+      return !failoverOrReconnect(me, connectionID);
    }
 
    private boolean failoverOrReconnect(final MessagingException me, final Object connectionID)
@@ -482,23 +466,17 @@
          return false;
       }
 
-      if (connectionID != null && !connections.containsKey(connectionID))
-      {
-         // We already failed over/reconnected - probably the first failure came in, all the connections were failed
-         // over then a async connection exception or disconnect
-         // came in for one of the already closed connections, so we return true - we don't want to call the
-         // listeners again
-
-         return true;
-      }
-
-      failureSignalled = true;
-
       synchronized (failoverLock)
       {
-         failureSignalled = false;
+         if (connectionID != null && !connections.containsKey(connectionID))
+         {
+            // We already failed over/reconnected - probably the first failure came in, all the connections were failed
+            // over then a async connection exception or disconnect
+            // came in for one of the already closed connections, so we return true - we don't want to call the
+            // listeners again
 
-         inFailoverOrReconnect = true;
+            return true;
+         }
 
          // Now get locks on all channel 1s, whilst holding the failoverLock - this makes sure
          // There are either no threads executing in createSession, or one is blocking on a createSession
@@ -599,10 +577,12 @@
                done = reattachSessions(reconnectAttempts == -1 ? -1 : reconnectAttempts + 1);
             }
             else if (reconnectAttempts != 0)
-            {
+            {              
                done = reattachSessions(reconnectAttempts);
             }
 
+            inFailoverOrReconnect = true;
+
             if (done)
             {
                // Destroy the old connections
@@ -728,7 +708,7 @@
 
       while (true)
       {
-         if (closed || failureSignalled)
+         if (closed)
          {
             return null;
          }

Modified: trunk/src/main/org/jboss/messaging/core/deployers/impl/AddressSettingsDeployer.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/deployers/impl/AddressSettingsDeployer.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/src/main/org/jboss/messaging/core/deployers/impl/AddressSettingsDeployer.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -98,8 +98,7 @@
     * @throws Exception .
     */
    public void deploy(Node node) throws Exception
-   {
-      log.info("** address setings deployer, deploying");
+   {      
       String match = node.getAttributes().getNamedItem(getKeyAttribute()).getNodeValue();
 
       NodeList children = node.getChildNodes();

Modified: trunk/src/main/org/jboss/messaging/core/management/impl/ManagementServiceImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/management/impl/ManagementServiceImpl.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/src/main/org/jboss/messaging/core/management/impl/ManagementServiceImpl.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -426,6 +426,7 @@
       {
          return;
       }
+      
       synchronized (mbeanServer)
       {
          unregisterFromJMX(objectName);
@@ -436,6 +437,7 @@
    public synchronized void registerInRegistry(final String resourceName, final Object managedResource)
    {
       unregisterFromRegistry(resourceName);
+      
       registry.put(resourceName, managedResource);
    }
 
@@ -643,6 +645,12 @@
       try
       {
          Object resource = registry.get(resourceName);
+         
+         if (resource == null)
+         {
+            throw new IllegalArgumentException("Cannot find resource with name " + resourceName);
+         }
+         
          Method method = null;
 
          try
@@ -671,6 +679,12 @@
    private Object invokeOperation(final String resourceName, final String operation, final List<Object> params) throws Exception
    {
       Object resource = registry.get(resourceName);
+      
+      if (resource == null)
+      {
+         throw new IllegalArgumentException("Cannot find resource with name " + resourceName);
+      }
+      
       Method method = null;
 
       Method[] methods = resource.getClass().getMethods();

Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -1655,9 +1655,7 @@
          {
             // Error - didn't get pong back
             final MessagingException me = new MessagingException(MessagingException.NOT_CONNECTED,
-                                                                 "Did not receive pong from server, active " + createdActive +
-                                                                          " client " +
-                                                                          client);
+                                                                 "Did not receive pong from server");
 
             future.cancel(true);
             

Modified: trunk/src/main/org/jboss/messaging/integration/transports/netty/NettyAcceptor.java
===================================================================
--- trunk/src/main/org/jboss/messaging/integration/transports/netty/NettyAcceptor.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/src/main/org/jboss/messaging/integration/transports/netty/NettyAcceptor.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -213,10 +213,10 @@
    }
 
    public synchronized void start() throws Exception
-   {
+   {      
       if (channelFactory != null)
       {
-         // Already started
+         // Already started        
          return;
       }
       bossExecutor = Executors.newCachedThreadPool(new org.jboss.messaging.utils.JBMThreadFactory("jbm-netty-acceptor-boss-threads"));

Modified: trunk/src/main/org/jboss/messaging/jms/server/impl/JMSServerDeployer.java
===================================================================
--- trunk/src/main/org/jboss/messaging/jms/server/impl/JMSServerDeployer.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/src/main/org/jboss/messaging/jms/server/impl/JMSServerDeployer.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -77,7 +77,7 @@
 
    private static final String RETRY_INTERVAL_MULTIPLIER = "retry-interval-multiplier";
 
-   private static final String CONNECT_ATTEMPTS = "reconnect-attempts";
+   private static final String RECONNECT_ATTEMPTS = "reconnect-attempts";
    
    private static final String FAILOVER_ON_NODE_SHUTDOWN = "failover-on-server-shutdown";
 
@@ -256,7 +256,7 @@
             {
                retryIntervalMultiplier = org.jboss.messaging.utils.XMLUtil.parseDouble(child);
             }
-            else if (CONNECT_ATTEMPTS.equals(child.getNodeName()))
+            else if (RECONNECT_ATTEMPTS.equals(child.getNodeName()))
             {
                reconnectAttempts = org.jboss.messaging.utils.XMLUtil.parseInt(child);;
             }

Modified: trunk/src/main/org/jboss/messaging/jms/server/management/impl/JMSManagementHelper.java
===================================================================
--- trunk/src/main/org/jboss/messaging/jms/server/management/impl/JMSManagementHelper.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/src/main/org/jboss/messaging/jms/server/management/impl/JMSManagementHelper.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -50,6 +50,13 @@
       message.setStringProperty(HDR_RESOURCE_NAME.toString(), resourceName);
       message.setStringProperty(HDR_ATTRIBUTE.toString(), attribute);
    }
+   
+   public static void putOperationInvocation(final Message message,
+                                             final String resourceName,
+                                             final String operationName) throws JMSException
+   {
+      putOperationInvocation(message, resourceName, operationName, (Object[])null);
+   }
 
    public static void putOperationInvocation(final Message message,
                                              final String resourceName,
@@ -60,13 +67,16 @@
       message.setStringProperty(HDR_RESOURCE_NAME.toString(), resourceName);
       message.setStringProperty(HDR_OPERATION_NAME.toString(), operationName);
       // ... and all the parameters (preserving their types)
-      for (int i = 0; i < parameters.length; i++)
+      if (parameters != null)
       {
-         Object parameter = parameters[i];
-         // use a zero-filled 2-padded index:
-         // if there is more than 10 parameters, order is preserved (e.g. 02 will be before 10)
-         String key = String.format("%s%02d", HDR_OPERATION_PREFIX, i);
-         storeTypedProperty(message, key, parameter);
+         for (int i = 0; i < parameters.length; i++)
+         {
+            Object parameter = parameters[i];
+            // use a zero-filled 2-padded index:
+            // if there is more than 10 parameters, order is preserved (e.g. 02 will be before 10)
+            String key = String.format("%s%02d", HDR_OPERATION_PREFIX, i);
+            storeTypedProperty(message, key, parameter);
+         }
       }
    }
 

Modified: trunk/src/schemas/jbm-configuration.xsd
===================================================================
--- trunk/src/schemas/jbm-configuration.xsd	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/src/schemas/jbm-configuration.xsd	2009-04-15 12:27:47 UTC (rev 6431)
@@ -41,7 +41,7 @@
 					maxOccurs="1" minOccurs="0">
 				</xsd:element>
 				<xsd:element name="security-invalidation-interval"
-					type="period" maxOccurs="1" minOccurs="0">
+					type="xsd:unsignedLong" maxOccurs="1" minOccurs="0">
 				</xsd:element>
 				<xsd:element name="wild-card-routing-enabled"
 					type="xsd:boolean" maxOccurs="1" minOccurs="0">
@@ -56,7 +56,7 @@
                     type="xsd:string" maxOccurs="1" minOccurs="0">
                 </xsd:element>				
                 <xsd:element name="management-request-timeout"
-                    type="period" maxOccurs="1" minOccurs="0">
+                    type="xsd:unsignedLong" maxOccurs="1" minOccurs="0">
                 </xsd:element>              
 				<xsd:element name="jmx-management-enabled"
 					type="xsd:boolean" maxOccurs="1" minOccurs="0">
@@ -65,19 +65,19 @@
 					type="xsd:boolean" maxOccurs="1" minOccurs="0">
 				</xsd:element>
 				<xsd:element name="connection-scan-period"
-					type="period" maxOccurs="1" minOccurs="0">
+					type="xsd:unsignedLong" maxOccurs="1" minOccurs="0">
 				</xsd:element>
 				<xsd:element name="connection-ttl-override"
 					type="xsd:long" maxOccurs="1" minOccurs="0">
 				</xsd:element>
-				<xsd:element name="transaction-timeout" type="period"
+				<xsd:element name="transaction-timeout" type="xsd:unsignedLong"
 					maxOccurs="1" minOccurs="0">
 				</xsd:element>
 				<xsd:element name="transaction-timeout-scan-period"
-					type="period" maxOccurs="1" minOccurs="0">
+					type="xsd:unsignedLong" maxOccurs="1" minOccurs="0">
 				</xsd:element>
 				<xsd:element name="message-expiry-scan-period"
-					type="period" maxOccurs="1" minOccurs="0">
+					type="xsd:unsignedLong" maxOccurs="1" minOccurs="0">
 				</xsd:element>
 				<xsd:element name="message-expiry-thread-priority"
 					type="xsd:positiveInteger" maxOccurs="1" minOccurs="0">
@@ -197,7 +197,7 @@
 
 	<xsd:element name="group-port" type="portRange"></xsd:element>
 
-	<xsd:element name="broadcast-period" type="period"></xsd:element>
+	<xsd:element name="broadcast-period" type="xsd:unsignedLong"></xsd:element>
 
 	<xsd:element name="connector-ref" type="connector-refType">
 	</xsd:element>
@@ -225,7 +225,7 @@
 		</xsd:complexType>
 	</xsd:element>
 
-	<xsd:element name="refresh-timeout" type="period"></xsd:element>
+	<xsd:element name="refresh-timeout" type="xsd:unsignedLong"></xsd:element>
 
 	<xsd:element name="discovery-group">
 		<xsd:complexType>
@@ -326,14 +326,14 @@
 			<xsd:element name="transformer-class-name" type="xsd:string"
 				maxOccurs="1" minOccurs="0">
 			</xsd:element>
-			<xsd:element name="retry-interval" type="period"
+			<xsd:element name="retry-interval" type="xsd:unsignedLong"
 				maxOccurs="1" minOccurs="0">
 			</xsd:element>
 			<xsd:element name="retry-interval-multiplier"
 				type="xsd:double" maxOccurs="1" minOccurs="0">
 			</xsd:element>
 			<xsd:element name="reconnect-attempts"
-				type="xsd:nonNegativeInteger" maxOccurs="1" minOccurs="0">
+				type="minusOneOrMoreInteger" maxOccurs="1" minOccurs="0">
 			</xsd:element>
 			<xsd:element name="failover-on-server-shutdown"
 				type="xsd:boolean" maxOccurs="1" minOccurs="0">
@@ -363,7 +363,7 @@
 			<xsd:element name="address" type="xsd:string"
 				maxOccurs="1" minOccurs="1">
 			</xsd:element>
-			<xsd:element name="retry-interval" type="period"
+			<xsd:element name="retry-interval" type="xsd:unsignedLong"
 				maxOccurs="1" minOccurs="0">
 			</xsd:element>			
 			<xsd:element name="use-duplicate-detection"
@@ -434,14 +434,16 @@
 		<xsd:attribute name="string" type="xsd:string" use="required"></xsd:attribute>
 	</xsd:complexType>
 
-
 	<xsd:simpleType name="portRange">
 		<xsd:restriction base="xsd:int">
 		      <xsd:minExclusive value="1024"></xsd:minExclusive>
 		</xsd:restriction>
 	</xsd:simpleType>
+	
+   <xsd:simpleType name="minusOneOrMoreInteger">
+      <xsd:restriction base="xsd:int">
+         <xsd:minInclusive value="-1"></xsd:minInclusive>
+      </xsd:restriction>
+   </xsd:simpleType>	
 
-    <xsd:simpleType name="period">
-        <xsd:restriction base="xsd:unsignedLong"></xsd:restriction>
-    </xsd:simpleType>
 </xsd:schema>

Modified: trunk/src/schemas/jbm-jms.xsd
===================================================================
--- trunk/src/schemas/jbm-jms.xsd	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/src/schemas/jbm-jms.xsd	2009-04-15 12:27:47 UTC (rev 6431)
@@ -92,7 +92,7 @@
    			<xsd:element name="retry-interval-multiplier" type="xsd:float"
    				maxOccurs="1" minOccurs="0">
    			</xsd:element>            
-            <xsd:element name="connect-attempts" type="xsd:positiveInteger"
+            <xsd:element name="reconnect-attempts" type="minusOneOrMoreInteger"
                 maxOccurs="1" minOccurs="0">
             </xsd:element>
             <xsd:element name="failover-on-server-shutdown" type="xsd:boolean"
@@ -135,4 +135,10 @@
 
     <xsd:element name="topic" type="destinationType"></xsd:element>
     
+    <xsd:simpleType name="minusOneOrMoreInteger">
+      <xsd:restriction base="xsd:int">
+         <xsd:minInclusive value="-1"></xsd:minInclusive>
+      </xsd:restriction>
+   </xsd:simpleType>	
+    
 </xsd:schema>

Modified: trunk/tests/src/org/jboss/messaging/tests/integration/cluster/failover/ReconnectTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/integration/cluster/failover/ReconnectTest.java	2009-04-15 07:38:07 UTC (rev 6430)
+++ trunk/tests/src/org/jboss/messaging/tests/integration/cluster/failover/ReconnectTest.java	2009-04-15 12:27:47 UTC (rev 6431)
@@ -34,6 +34,7 @@
 import org.jboss.messaging.core.config.impl.ConfigurationImpl;
 import org.jboss.messaging.core.exception.MessagingException;
 import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.core.remoting.FailureListener;
 import org.jboss.messaging.core.remoting.RemotingConnection;
 import org.jboss.messaging.core.remoting.impl.invm.InVMConnector;
 import org.jboss.messaging.core.remoting.impl.invm.InVMRegistry;
@@ -80,7 +81,7 @@
 
       final double retryMultiplier = 1d;
 
-      final int reconnectAttempts = 1;      
+      final int reconnectAttempts = 1;
 
       ClientSessionFactoryInternal sf = new ClientSessionFactoryImpl(new TransportConfiguration("org.jboss.messaging.core.remoting.impl.invm.InVMConnectorFactory"),
                                                                      retryInterval,
@@ -90,15 +91,15 @@
       ClientSession session = sf.createSession(false, true, true);
 
       session.createQueue(ADDRESS, ADDRESS, null, false);
-      
+
       final int numIterations = 100;
-      
+
       for (int j = 0; j < numIterations; j++)
-      {  
+      {
          ClientProducer producer = session.createProducer(ADDRESS);
-   
+
          final int numMessages = 1000;
-                    
+
          for (int i = 0; i < numMessages; i++)
          {
             ClientMessage message = session.createClientMessage(JBossTextMessage.TYPE,
@@ -112,40 +113,40 @@
          }
 
          ClientConsumer consumer = session.createConsumer(ADDRESS);
-   
+
          RemotingConnection conn = ((ClientSessionImpl)session).getConnection();
-   
+
          conn.fail(new MessagingException(MessagingException.NOT_CONNECTED));
-   
+
          session.start();
-   
+
          for (int i = 0; i < numMessages; i++)
          {
             ClientMessage message = consumer.receive(500);
-   
+
             assertNotNull(message);
-   
+
             assertEquals("aardvarks", message.getBody().readString());
-   
+
             assertEquals(i, message.getProperty(new SimpleString("count")));
-   
+
             message.acknowledge();
          }
-   
+
          ClientMessage message = consumer.receiveImmediate();
-   
+
          assertNull(message);
-         
+
          producer.close();
-         
+
          consumer.close();
       }
-      
+
       session.close();
-      
+
       sf.close();
    }
-   
+
    /*
     * Test failure on connection, simulate failure to create connection for a while, then 
     * allow connection to be recreated
@@ -157,10 +158,10 @@
       final double retryMultiplier = 1d;
 
       final int reconnectAttempts = -1;
-      
+
       ClientSessionFactoryInternal sf = new ClientSessionFactoryImpl(new TransportConfiguration("org.jboss.messaging.core.remoting.impl.invm.InVMConnectorFactory"),
                                                                      retryInterval,
-                                                                     retryMultiplier,                                                                     
+                                                                     retryMultiplier,
                                                                      reconnectAttempts);
 
       ClientSession session = sf.createSession(false, true, true);
@@ -186,9 +187,9 @@
       ClientConsumer consumer = session.createConsumer(ADDRESS);
 
       InVMConnector.failOnCreateConnection = true;
-      
+
       RemotingConnection conn = ((ClientSessionImpl)session).getConnection();
-      
+
       Thread t = new Thread()
       {
          public void run()
@@ -198,13 +199,13 @@
                Thread.sleep(retryInterval * 3);
             }
             catch (InterruptedException ignore)
-            {               
+            {
             }
-            
+
             InVMConnector.failOnCreateConnection = false;
          }
       };
-      
+
       t.start();
 
       conn.fail(new MessagingException(MessagingException.NOT_CONNECTED));
@@ -227,21 +228,145 @@
       ClientMessage message = consumer.receiveImmediate();
 
       assertNull(message);
+
+      session.close();
+
+      sf.close();
+
+      t.join();
+   }
+
+   // Test an async (e.g. pinger) failure coming in while a connection manager is already reconnecting
+   public void testAsyncFailureWhileReconnecting() throws Exception
+   {
+      final long retryInterval = 500;
+
+      final double retryMultiplier = 1d;
+
+      final int reconnectAttempts = -1;
+
+      final long asyncFailDelay = 2000;
+
+      ClientSessionFactoryInternal sf = new ClientSessionFactoryImpl(new TransportConfiguration("org.jboss.messaging.core.remoting.impl.invm.InVMConnectorFactory"),
+                                                                     retryInterval,
+                                                                     retryMultiplier,
+                                                                     reconnectAttempts);
+
+      ClientSession session = sf.createSession(false, true, true);
+           
+      ClientSession session2 = sf.createSession(false, true, true);
       
+      class MyFailureListener implements FailureListener
+      {
+         volatile boolean failed;
+         
+         public boolean connectionFailed(MessagingException me)
+         {
+            failed = true;
+            
+            return true;
+         }
+      }
+      
+      MyFailureListener listener = new MyFailureListener();
+      
+      session2.addFailureListener(listener);
+
+      session.createQueue(ADDRESS, ADDRESS, null, false);
+
+      ClientProducer producer = session.createProducer(ADDRESS);
+
+      final int numMessages = 1000;
+
+      for (int i = 0; i < numMessages; i++)
+      {
+         ClientMessage message = session.createClientMessage(JBossTextMessage.TYPE,
+                                                             false,
+                                                             0,
+                                                             System.currentTimeMillis(),
+                                                             (byte)1);
+         message.putIntProperty(new SimpleString("count"), i);
+         message.getBody().writeString("aardvarks");
+         producer.send(message);
+      }
+
+      ClientConsumer consumer = session.createConsumer(ADDRESS);
+
+      InVMConnector.numberOfFailures = 10;
+      InVMConnector.failOnCreateConnection = true;
+
+      //We need to fail on different connections.
+      
+      //We fail on one connection then the connection manager tries to reconnect all connections
+      //Then we fail the other, and the connection  manager is then called while the reconnection is occurring
+      //We can't use the same connection since RemotingConnectionImpl only allows one fail to be in process
+      //at same time
+      
+      final RemotingConnection conn = ((ClientSessionImpl)session).getConnection();
+      
+      final RemotingConnection conn2 = ((ClientSessionImpl)session2).getConnection();
+      
+      assertTrue(conn != conn2);
+
+      Thread t = new Thread()
+      {
+         public void run()
+         {
+            try
+            {
+               Thread.sleep(asyncFailDelay);
+            }
+            catch (InterruptedException ignore)
+            {
+            }
+            
+            log.info("calling fail async");
+
+            conn2.fail(new MessagingException(MessagingException.NOT_CONNECTED, "Did not receive pong from server"));
+         }
+      };
+
+      t.start();
+      
+      conn.fail(new MessagingException(MessagingException.NOT_CONNECTED));
+      
+      assertFalse(listener.failed);
+      
+      session.start();            
+
+      for (int i = 0; i < numMessages; i++)
+      {
+         ClientMessage message = consumer.receive(500);
+
+         assertNotNull(message);
+
+         assertEquals("aardvarks", message.getBody().readString());
+
+         assertEquals(i, message.getProperty(new SimpleString("count")));
+
+         message.acknowledge();
+      }
+
+      ClientMessage message = consumer.receiveImmediate();
+
+      assertNull(message);
+
       session.close();
       
+      session2.close();
+
       sf.close();
-      
+
       t.join();
    }
-   
+
    public void testReconnectAttemptsFailsToReconnect() throws Exception
    {
       final long retryInterval = 500;
 
       final double retryMultiplier = 1d;
 
-      final int reconnectAttempts = 3;      
+      final int reconnectAttempts = 3;
 
       ClientSessionFactoryInternal sf = new ClientSessionFactoryImpl(new TransportConfiguration("org.jboss.messaging.core.remoting.impl.invm.InVMConnectorFactory"),
                                                                      retryInterval,
@@ -271,11 +396,11 @@
       ClientConsumer consumer = session.createConsumer(ADDRESS);
 
       InVMConnector.failOnCreateConnection = true;
-      
+
       RemotingConnection conn = ((ClientSessionImpl)session).getConnection();
-      
-      //Sleep for longer than max retries so should fail to reconnect
-      
+
+      // Sleep for longer than max retries so should fail to reconnect
+
       Thread t = new Thread()
       {
          public void run()
@@ -285,42 +410,42 @@
                Thread.sleep(retryInterval * (reconnectAttempts + 1));
             }
             catch (InterruptedException ignore)
-            {               
+            {
             }
-            
+
             InVMConnector.failOnCreateConnection = false;
          }
       };
-      
+
       t.start();
 
       conn.fail(new MessagingException(MessagingException.NOT_CONNECTED));
 
       session.start();
 
-      //Should be null since failed to reconnect
+      // Should be null since failed to reconnect
       ClientMessage message = consumer.receive(500);
 
       assertNull(message);
-      
+
       session.close();
-      
+
       sf.close();
-      
+
       t.join();
    }
-   
+
    public void testReconnectAttemptsSucceedsInReconnecting() throws Exception
    {
       final long retryInterval = 500;
 
       final double retryMultiplier = 1d;
 
-      final int reconnectAttempts = 10;      
+      final int reconnectAttempts = 10;
 
       ClientSessionFactoryInternal sf = new ClientSessionFactoryImpl(new TransportConfiguration("org.jboss.messaging.core.remoting.impl.invm.InVMConnectorFactory"),
                                                                      retryInterval,
-                                                                     retryMultiplier,                                                      
+                                                                     retryMultiplier,
                                                                      reconnectAttempts);
 
       ClientSession session = sf.createSession(false, true, true);
@@ -347,11 +472,11 @@
 
       InVMConnector.failOnCreateConnection = true;
       InVMConnector.numberOfFailures = reconnectAttempts - 1;
-      
+
       RemotingConnection conn = ((ClientSessionImpl)session).getConnection();
-      
+
       conn.fail(new MessagingException(MessagingException.NOT_CONNECTED));
-      
+
       session.start();
 
       for (int i = 0; i < numMessages; i++)
@@ -370,23 +495,23 @@
       ClientMessage message = consumer.receiveImmediate();
 
       assertNull(message);
-      
+
       session.close();
-      
+
       sf.close();
    }
-     
+
    public void testRetryInterval() throws Exception
    {
       final long retryInterval = 500;
 
       final double retryMultiplier = 1d;
 
-      final int reconnectAttempts = -1;      
+      final int reconnectAttempts = -1;
 
       ClientSessionFactoryInternal sf = new ClientSessionFactoryImpl(new TransportConfiguration("org.jboss.messaging.core.remoting.impl.invm.InVMConnectorFactory"),
                                                                      retryInterval,
-                                                                     retryMultiplier,                                                                    
+                                                                     retryMultiplier,
                                                                      reconnectAttempts);
 
       ClientSession session = sf.createSession(false, true, true);
@@ -412,11 +537,11 @@
       ClientConsumer consumer = session.createConsumer(ADDRESS);
 
       InVMConnector.failOnCreateConnection = true;
-      
+
       RemotingConnection conn = ((ClientSessionImpl)session).getConnection();
-      
+
       long start = System.currentTimeMillis();
-      
+
       Thread t = new Thread()
       {
          public void run()
@@ -426,16 +551,16 @@
                Thread.sleep(retryInterval / 2);
             }
             catch (InterruptedException ignore)
-            {               
+            {
             }
             InVMConnector.failOnCreateConnection = false;
          }
       };
-      
+
       t.start();
-      
+
       conn.fail(new MessagingException(MessagingException.NOT_CONNECTED));
-                  
+
       session.start();
 
       for (int i = 0; i < numMessages; i++)
@@ -454,29 +579,29 @@
       ClientMessage message = consumer.receiveImmediate();
 
       assertNull(message);
-      
+
       long end = System.currentTimeMillis();
-      
+
       assertTrue((end - start) >= retryInterval);
-      
+
       session.close();
-      
+
       sf.close();
-      
+
       t.join();
    }
-   
+
    public void testExponentialBackoff() throws Exception
    {
       final long retryInterval = 500;
 
       final double retryMultiplier = 4d;
 
-      final int reconnectAttempts = -1;      
+      final int reconnectAttempts = -1;
 
       ClientSessionFactoryInternal sf = new ClientSessionFactoryImpl(new TransportConfiguration("org.jboss.messaging.core.remoting.impl.invm.InVMConnectorFactory"),
                                                                      retryInterval,
-                                                                     retryMultiplier,                                                  
+                                                                     retryMultiplier,
                                                                      reconnectAttempts);
 
       ClientSession session = sf.createSession(false, true, true);
@@ -502,11 +627,11 @@
       ClientConsumer consumer = session.createConsumer(ADDRESS);
 
       InVMConnector.failOnCreateConnection = true;
-      
+
       RemotingConnection conn = ((ClientSessionImpl)session).getConnection();
-      
+
       long start = System.currentTimeMillis();
-      
+
       Thread t = new Thread()
       {
          public void run()
@@ -516,17 +641,17 @@
                Thread.sleep(retryInterval * 2);
             }
             catch (InterruptedException ignore)
-            {               
+            {
             }
-            
+
             InVMConnector.failOnCreateConnection = false;
          }
       };
-      
+
       t.start();
-      
+
       conn.fail(new MessagingException(MessagingException.NOT_CONNECTED));
-                  
+
       session.start();
 
       for (int i = 0; i < numMessages; i++)
@@ -545,15 +670,15 @@
       ClientMessage message = consumer.receiveImmediate();
 
       assertNull(message);
-      
+
       long end = System.currentTimeMillis();
-      
+
       assertTrue((end - start) >= retryInterval * (1 + retryMultiplier));
-      
+
       session.close();
-      
+
       sf.close();
-      
+
       t.join();
    }
 
@@ -565,7 +690,7 @@
    protected void setUp() throws Exception
    {
       super.setUp();
-      
+
       Configuration liveConf = new ConfigurationImpl();
       liveConf.setSecurityEnabled(false);
       liveConf.getAcceptorConfigurations()
@@ -578,11 +703,11 @@
    protected void tearDown() throws Exception
    {
       InVMConnector.resetFailures();
-      
+
       service.stop();
 
       assertEquals(0, InVMRegistry.instance.size());
-      
+
       super.tearDown();
    }
 




More information about the jboss-cvs-commits mailing list