After setting up the HTTP/HTTPS configuration for JBoss server cluster, the next assignment on my table was to set up the HA-JMS on the server cluster.
My JBoss installation folder structure is as below:
2 |
JBOSS_HOME\server\default |
3 |
JBOSS_HOME\server\minimal |
The “all” folder has everything configured for HA, however to understand the process, I have set up HA JMS within default folder. Go to the following folder JBOSS_HOME\server\default\deploy\jms
Remove all the files within the jms folder except jms-ra.rar. Please take a backup of these files some files might be required later. Within the default folder create a new folder named deploy-hasingleton within this folder create a sub-folder named jms. The contents of this folder will be similar to contents of the jms folder we had cleaned up earlier. The contents are as follows:
01 |
Folder - jbossmq-httpil.sar |
02 |
File - hsqldb-jdbc-state-service.xml |
03 |
No change from the default file except change the following tag |
04 |
<depends optional-attribute-name="ConnectionManager">jboss.jca:service=DataSourceBinding,name=MySqlDS</depends> |
05 |
My data source name is MySqlDS, please point to your appropriate data source name. |
06 |
File - jbossmq-destinations-service.xml |
07 |
I have retained the original file please feel free alter this file to |
08 |
reflect your queues/topics. |
09 |
File - jbossmq-service.xml |
13 |
File - jvm-il-service.xml |
15 |
File - mysql-jdbc2-service.xml |
16 |
Change the following tag to point to the correct data source |
17 |
<depends optional-attribute-name="ConnectionManager">jboss.jca:service=DataSourceBinding,name=MySqlDS</depends> |
18 |
File - uil2-service.xml No change |
Check if the JBOSS_HOME\server\default\lib has the following two jars: jbossha.jar, jgroups.jar. If not add them from the JBOSS_HOME\server\all\lib folder.
Open the login-config.xml file from the folder JBOSS_HOME\server\default\conf.
Search for the following tag:
01 |
<!-- Security domain for JBossMQ --> |
02 |
< application-policy name = "jbossmq" > |
04 |
< login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule" |
06 |
< module-option name = "unauthenticatedIdentity" >guest</ module-option > |
07 |
< module-option name = "dsJndiName" >java:/MySqlDS</ module-option > |
08 |
< module-option name = "principalsQuery" >SELECT PASSWD FROM JMS_USERS WHERE USERID=?</ module-option > |
09 |
< module-option name = "rolesQuery" >SELECT ROLEID, 'Roles' FROM JMS_ROLES WHERE USERID=?</ module-option > |
And change the dsJndiName to correct data source. Ensure that the name retains java:/ portion.
Copy cluster-service.xml and deploy-hasingleton-service.xml in the JBOSS_HOME\server\default\deploy folder. The sample files are available in JBOSS_HOME\all\default\deploy folder. In my case both the instances are deployed on the same machine, therefore you might need to change the port numbers in the cluster-service.xml.
Configure your datasource. I have created mysql-ds.xml remove the hsqldb-ds.xml file. Sample files for different types of databases are available at JBOSS_HOME\docs\jca directory.
Now start the two instances. In case, the deployment is correct, during startup of the first instance you will see the following statements in the log files:
01 |
------------------------------------------------------- |
02 |
GMS: address is 122.22.22.22:3576 |
03 |
------------------------------------------------------- |
04 |
2009-04-21 17:52:58,419 DEBUG [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] ViewAccepted: initial members set |
05 |
2009-04-21 17:52:58,435 DEBUG [org.jboss.ha.framework.server.ClusterPartition] Starting channel |
06 |
2009-04-21 17:52:58,435 DEBUG [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] get nodeName |
07 |
2009-04-21 17:52:58,435 DEBUG [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] Get current members |
08 |
2009-04-21 17:52:58,435 INFO [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] Number of cluster members: 1 |
09 |
2009-04-21 17:52:58,435 INFO [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] Other members: 0 |
10 |
2009-04-21 17:52:58,435 INFO [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] Fetching state (will wait for 30000 milliseconds): |
And in the second instance startup, the following logs are
created:
01 |
------------------------------------------------------- |
02 |
GMS: address is 122.22.22.22:3589 |
03 |
------------------------------------------------------- |
04 |
2009-04-21 17:55:51,780 DEBUG [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] ViewAccepted: initial members set |
05 |
2009-04-21 17:55:51,780 DEBUG [org.jboss.ha.framework.server.ClusterPartition] Starting channel |
06 |
2009-04-21 17:55:51,780 DEBUG [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] get nodeName |
07 |
2009-04-21 17:55:51,780 DEBUG [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] Get current members |
08 |
2009-04-21 17:55:51,780 INFO [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] Number of cluster members: 2 |
09 |
2009-04-21 17:55:51,780 INFO [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] Other members: 1 |
10 |
2009-04-21 17:55:51,780 INFO [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] Fetching state (will wait for 30000 milliseconds): |
11 |
2009-04-21 17:55:51,811 DEBUG [org.jboss.ha.framework.interfaces.HAPartition.DefaultPartition] setState called |
You can use a sample JMS client to insert messages in queue. You can verify that only one queue is created on the cluster and if the master server fails, the backup server will create the queue. The JMS client application will however need to know both the JNDI URLs i.e for the master and the slave. That intelligence will need to be built in by the developer. Please find below my JNDI client and jndi.properties file for your ready reference.
JNDI properties file contents:
1 |
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory |
4 |
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces |
JNDI client contents:
03 |
import javax.jms.JMSException; |
04 |
import javax.jms.MessageProducer; |
05 |
import javax.jms.Queue; |
06 |
import javax.jms.QueueConnection; |
07 |
import javax.jms.QueueSession; |
08 |
import javax.jms.Session; |
09 |
import javax.jms.TextMessage; |
10 |
import javax.naming.NamingException; |
12 |
public class JNDIClient { |
14 |
public static void main(String[] args) { |
15 |
// create a new intial context, which loads from jndi.properties file |
16 |
javax.naming.Context ctx; |
18 |
ctx = new javax.naming.InitialContext(); |
19 |
// lookup the connection factory |
20 |
javax.jms.QueueConnectionFactory factory |
21 |
= (javax.jms.QueueConnectionFactory)ctx.lookup( "ConnectionFactory" ); |
23 |
// create a new TopicConnection for pub/sub messaging |
24 |
QueueConnection conn = factory.createQueueConnection(); |
25 |
Queue queue = (Queue)ctx.lookup( "queue/A" ); |
27 |
Session session = conn.createQueueSession( false , QueueSession.AUTO_ACKNOWLEDGE); |
28 |
MessageProducer producer = session.createProducer(queue); |
29 |
TextMessage msg = session.createTextMessage(); |
30 |
msg.setStringProperty( "Name" , "Cooler Dude" ); |
31 |
producer.send(queue, msg); |
36 |
} catch (NamingException e) { |
38 |
} catch (JMSException e) { |
Recent Comments