5.5. Configuring the Post Office

The post office routes messages to their destination or destinations. It maintains the mappings between the addresses to which a message can be sent, and the final queue. For example, when sending a message with an address that represents a JMS queue, the post office routes the message to that JMS queue. When sending a message with an address that represents a JMS topic, the post office routes the message to a set of queues — one for each JMS subscription.
The post office also handles the persistence for address mapping.
JBoss Messaging post offices are cluster-aware. In a cluster, they automatically route (push) and pull messages between nodes in order to provide fully-distributed JMS queues and topics.
Configure the post office in the <database type>-persistence-service.xml file. For example:
<mbean code="org.jboss.messaging.core.jmx.MessagingPostOfficeService"
  name="jboss.messaging:service=PostOffice"
  xmbean-dd="xmdesc/MessagingPostOffice-xmbean.xml">
      
  <depends optional-attribute-name="ServerPeer">
    jboss.messaging:service=ServerPeer
  </depends>
                
  <depends>
    jboss.jca:service=DataSourceBinding,name=DefaultDS
  </depends>
      
  <depends optional-attribute-name="TransactionManager">
    jboss:service=TransactionManager
  </depends>
      
  <!-- The name of the post office -->                  
    
  <attribute name="PostOfficeName">JMS post office</attribute>
      
  <!-- The datasource used by the post office to access it's 
       binding information -->                     
      
  <attribute name="DataSource">java:/DefaultDS</attribute>
      
  <!-- If true will attempt to create tables and indexes on 
       every start-up -->
                        
  <attribute name="CreateTablesOnStartup">true</attribute>
      
  <!-- If true then we will automatically detect and reject 
       duplicate messages sent during failover -->
      
  <attribute name="DetectDuplicates">true</attribute>
      
  <!-- The size of the id cache to use when detecting duplicate 
       messages -->
      
  <attribute name="IDCacheSize">500</attribute>
      
  <attribute name="SqlProperties">
    CREATE_POSTOFFICE_TABLE=CREATE TABLE JBM_POSTOFFICE 
      (POSTOFFICE_NAME VARCHAR(255), 
      NODE_ID INTEGER, QUEUE_NAME VARCHAR(255), COND VARCHAR(1023), 
      SELECTOR VARCHAR(1023), CHANNEL_ID BIGINT, CLUSTERED CHAR(1), 
      ALL_NODES CHAR(1), 
      PRIMARY KEY(POSTOFFICE_NAME, NODE_ID, QUEUE_NAME)) ENGINE = INNODB

    INSERT_BINDING=INSERT INTO JBM_POSTOFFICE 
      (POSTOFFICE_NAME, NODE_ID, QUEUE_NAME, COND, SELECTOR, 
       CHANNEL_ID, CLUSTERED, ALL_NODES) 
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)

    DELETE_BINDING=DELETE FROM JBM_POSTOFFICE WHERE 
      POSTOFFICE_NAME=? AND NODE_ID=? AND QUEUE_NAME=?

    LOAD_BINDINGS=SELECT QUEUE_NAME, COND, SELECTOR, 
      CHANNEL_ID, CLUSTERED, ALL_NODES FROM 
   JBM_POSTOFFICE WHERE POSTOFFICE_NAME=? AND NODE_ID=?
  </attribute>
      
  <!-- This post office is clustered. If you do not want a clustered post 
       office then set to false -->
      
  <attribute name="Clustered">true</attribute>
      
  <!-- All the remaining properties only have to be specified if the post 
       office is clustered. You can safely comment them out if your post 
       office is non clustered -->
      
  <!-- The JGroups group name that the post office will use -->            
      
  <attribute name="GroupName">
    ${jboss.messaging.groupname:MessagingPostOffice}
  </attribute>
      
  <!-- Max time to wait for state to arrive when the post office 
       joins the cluster -->            
                  
  <attribute name="StateTimeout">5000</attribute>
      
  <!-- Max time to wait for a synchronous call to node members using 
       the MessageDispatcher -->            
                  
  <attribute name="CastTimeout">50000</attribute>
      
  <!-- Set this to true if you want failover of connections to occur 
       when a node is shut down -->
      
  <attribute name="FailoverOnNodeLeave">false</attribute>
      
  <!-- JGroups stack configuration for the data channel - used for sending 
       data across the cluster --> 
                   
  <!-- By default we use the TCP stack for data -->                  
  <attribute name="DataChannelConfig">
    <config>
      <TCP start_port="7900"
        loopback="true"
        recv_buf_size="20000000"
        send_buf_size="640000"
        discard_incompatible_packets="true"
        max_bundle_size="64000"
        max_bundle_timeout="30"
        use_incoming_packet_handler="true"
        use_outgoing_packet_handler="false"
        down_thread="false" up_thread="false"
        enable_bundling="false"
        use_send_queues="false"
        sock_conn_timeout="300"
        skip_suspected_members="true"/>
      <MPING timeout="4000"
        bind_to_all_interfaces="true"
        mcast_addr="${jboss.messaging.datachanneludpaddress:228.6.6.6}"
        mcast_port="${jboss.messaging.datachanneludpport:45567}"
        ip_ttl="8"
        num_initial_members="2"
        num_ping_requests="1"/>                     
      <MERGE2 max_interval="100000"
        down_thread="false" up_thread="false" min_interval="20000"/>
      <FD_SOCK down_thread="false" up_thread="false"/>            
      <VERIFY_SUSPECT timeout="1500" down_thread="false" 
       up_thread="false"/>
      <pbcast.NAKACK max_xmit_size="60000"
        use_mcast_xmit="false" gc_lag="0"
        retransmit_timeout="300,600,1200,2400,4800"
        down_thread="false" up_thread="false"
        discard_delivered_msgs="true"/>
      <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
        down_thread="false" up_thread="false"
        max_bytes="400000"/>
      <pbcast.GMS print_local_addr="true" join_timeout="3000"
        down_thread="false" up_thread="false"
        join_retry_timeout="2000" shun="false"
        view_bundling="true"/>
    </config>        
  </attribute>
      
  <!-- JGroups stack configuration to use for 
       the control channel - used for control messages -->         
              
  <!-- We use udp stack for the control channel -->
  <attribute name="ControlChannelConfig">
    <config>
      <UDP
        mcast_addr="${jboss.messaging.controlchanneludpaddress:228.7.7.7}"
        mcast_port="${jboss.messaging.controlchanneludpport:45568}"
        tos="8"
        ucast_recv_buf_size="20000000"
        ucast_send_buf_size="640000"
        mcast_recv_buf_size="25000000"
        mcast_send_buf_size="640000"
        loopback="false"
        discard_incompatible_packets="true"
        max_bundle_size="64000"
        max_bundle_timeout="30"
        use_incoming_packet_handler="true"
        use_outgoing_packet_handler="false"
        ip_ttl="2"
        down_thread="false" up_thread="false"
        enable_bundling="false"/>
      <PING timeout="2000"
        down_thread="false" up_thread="false" num_initial_members="3"/>
      <MERGE2 max_interval="100000"
        down_thread="false" up_thread="false" min_interval="20000"/>
      <FD_SOCK down_thread="false" up_thread="false"/>
      <FD timeout="10000" max_tries="5" down_thread="false" 
        up_thread="false" shun="true"/>
      <VERIFY_SUSPECT timeout="1500" down_thread="false" 
       up_thread="false"/>
      <pbcast.NAKACK max_xmit_size="60000"
        use_mcast_xmit="false" gc_lag="0"
        retransmit_timeout="300,600,1200,2400,4800"
        down_thread="false" up_thread="false"
        discard_delivered_msgs="true"/>
      <UNICAST timeout="300,600,1200,2400,3600"
        down_thread="false" up_thread="false"/>
      <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
        down_thread="false" up_thread="false"
        max_bytes="400000"/>
      <pbcast.GMS print_local_addr="true" join_timeout="3000" 
        use_flush="true" flush_timeout="3000"
        down_thread="false" up_thread="false"
        join_retry_timeout="2000" shun="false"
        view_bundling="true"/>
      <FRAG2 frag_size="60000" down_thread="false" up_thread="false"/>
      <pbcast.STATE_TRANSFER down_thread="false" up_thread="false" 
        use_flush="true" flush_timeout="3000"/>
      <pbcast.FLUSH down_thread="false" up_thread="false" timeout="20000" 
        auto_flush_conf="false"/>
    </config>
  </attribute>    
      
</mbean>

5.5.1. MessagingPostOffice Attributes

MessagingPostOffice Service Attributes are described in the following list.
DataSource
The datasource the postoffice should use for persisting its mapping data.
SQLProperties
This is where the DDL and DML for the particular database is specified. If a particular DDL or DML statement is not overridden, the default Hypersonic configuration will be used for that statement.
CreateTablesOnStartup
Set this to true if you wish the post office to attempt to create the tables (and indexes) when it starts. If the tables (or indexes) already exist a SQLException will be thrown by the JDBC driver and ignored by the Persistence Manager, allowing it to continue.
By default the value of CreateTablesOnStartup attribute is set to true
DetectDuplicates
Set this to true if you wish the post office detect duplicate messages that may sent when a send is retried on a different node after server failure.
By default the value of DetectDuplicates attribute is set to true
IDCacheSize
If duplicate detection is enabled. (See DetectDuplicates), then the server will remember the last n message ids sent, to prevent duplicate messages sent after failover has occurred. The value of n is determined by this attribute.
By default the value of IDCacheSize attribute is set to 500
PostOfficeName
The name of the post office.
NodeIDView
This returns set containing the node ids of all the nodes in the cluster.
GroupName
All post offices in the cluster with the same group name will form a cluster together. Make sure the group name matches with all the nodes in the cluster you want to form a cluster with.
Clustered
If true the post office will take part in a cluster to form distributed queues and topics. If false then it will not participate in the cluster. If false, then all the cluster related attributes will be ignored.
StateTimeout
The maximum time to wait when waiting for the group state to arrive when a node joins a pre-existing cluster.
The default value is 5000 milliseconds.
CastTimeout
The maximum time to wait for a reply casting message synchronously.
The default value is 5000 milliseconds.
FailoverOnNodeLeave
Specifies how messages stored on a node are redistributed when a node is cleanly shutdown. The default value is false. If true, when a server node is shut down cleanly (using Ctrl+C in the terminal) all messages stored on the node are moved to another node in the cluster.

Important

Clients originally connected to the cleanly shutdown node are not automatically reconnected to the failover node in the cluster. Clients return an exception upon message failover.
MaxConcurrentReplications
The maximum number of concurrent replication requests to make before blocking for replies to come back. This prevents us overwhelming JGroups. This is rarely a good reason to change this.
The default value is 50
ControlChannelConfig
JBoss Messaging uses JGroups for all group management. This contains the JGroups stack configuration for the control channel.
The control channel is used for sending request/receiving responses from other nodes in the cluster
The details of the JGroups configuration will not be discussed here since it is standard JGroups configuration. Detailed information on JGroups can be found in JGroups release documentation or on-line at http://www.jgroups.org or http://wiki.jboss.org/wiki/Wiki.jsp?page=JGroups.
DataChannelConfig
JBoss Messaging uses JGroups for all group management. This contains the JGroups stack configuration for the data channel.
The data channel is used for sending sending/receiving messages from other nodes in the cluster and for replicating session data.
The details of the JGroups configuration will not be discussed here since it is standard JGroups configuration. Detailed information on JGroups can be found in JGroups release documentation or on-line at http://www.jgroups.org or http://wiki.jboss.org/wiki/Wiki.jsp?page=JGroups.
Database Connection Retry Parameters control whether a connection should be re-established when a connection failure is detected, how many attempts to reconnect should be made, and at what interval each attempt should be made.
RetryOnConnectionFailure
Specifies whether the MBean should attempt to reconnect to the database. The default is false.
MaxRetry
Specifies the maximum limit for DataSource connection failures. The default is 25. Set the parameter to -1 to activate "retry forever" mode. This parameter is valid when RetryOnConnectionFailure is set to true.

Important

Clients that consume messages from a clustered destination can become unresponsive when closed. This happens if the node has the value MaxRetry set to -1, and loses the connection to the database. To avoid the problem, set the node parameter MaxRetry to a value greater than -1. You can set the attribute value in the MBeans PersistenceManager, PostOffice, and JMSUserManager in the file [database]-persistence-service.xml
RetryInterval
Specifies the retry interval between two consecutive retries. The default is 1000 (milliseconds). This parameter is valid when RetryOnConnectionFailure is set to true.
If a node becomes unresponsive for a few seconds while still being stable (for example during a minor network malfunction), past failover behavior reported the node had left the cluster. This scenario can be avoided by specifying the following parameters in the MessagePostOffice bean. The following parameters provide the MessagePostOffice access to the cluster timestamp table, which is used to more accurately determine the state of a node.

Important

The timestamp table parameters should be used in conjunction with the MessagingClusterHealthMBean MBean. You deploy this MBean in the ServerPeer MBean. Refer to Section 5.1, “Configuring the ServerPeer” for a full overview of the supported parameters and operations.
KeepOldFailoverMode
Specifies whether the timestamp table failover mode should be used. The default is true (disable new failover behavior).
NodeStateRefreshInterval
Specifies the maximum duration (in milliseconds) a cluster will wait for a node to refresh its timestamp before the cluster marks the node as disabled. The default is 30000 (30 seconds).