Using Template to Deploy a JBoss Queue

Currently I am involved in a project, where I have to use Velocity template engine to deploy queues and message-driven beans to JBoss. Velocity is a template engine that can be used for many purposes, and in my case I am using it to generate XML descriptor for a JBoss queue, hence: some-queue-name-service.xml. Its a simple scripting language and the XML descriptor template looks quite similar to the resulting XML descriptor.

Why do we use a template for deployment?
Because some of our deployments occur at runtime, where properties for the queues and MDB’s are generated on the fly and we need a templating engine to be able generate the deployments.

So i decided to describe a process of deploying a JBoss queue. I am hoping that I will be clear enough, since i am quite new to this my self.

The setup of my system:

/opt/mitto/jboss/server/mitto/

Root directory for my JBoss instance. (the [.])

My Velocity templates sit under the root, inside dynamic-templates directory:

./dynamic-templates/

JBoss deployment service will look under the root of my JBoss instance for the dynamic-templates directory.

JBoss deployment service depends on Velocity library (velocity.jar) that must be included under the root of:

./deploy/deployment-service.sar/

XML descriptor of JBoss deployment service (jboss-service.xml) sits under:

./deploy/deployment-service.sar/META-INF/

You can see below the jboss-service.xml:

	<mbean code="org.jboss.services.deployment.DeploymentService" name="jboss:service=DeploymentService">
		<attribute name="TemplateDir">dynamic-templates</attribute>
		<attribute name="DeployDir">dynamic-deploy</attribute>
		<attribute name="UndeployDir">dynamic-undeploy</attribute>
	</mbean>

The three directories mentioned above in jboss-service.xml, sit under the root of my JBoss instance.
TemplateDir – where my deployment generation templates can be found.
UndeployDir – the generated modules go there.

DeployDir – the directory to use when I ask to deploy a generated module.

Now, inside the:

./dynamic-templates/

I have following structure:

	jbossmessaging-queue/
		            /vm/
		               jbossmessaging-queue.xml.vm
		            template-config.xml

jbossmessaging-queue – directory that contains Velocity XML descriptor template for my queue. Also it represents the name of the deployment template that should be used, when createModule() method of deployment service will be called.

template-config.xml specifies the properties for Velocity template XML descriptor for our queue. Deployment service will be able to access those properties when rendering the Velocity template and to retrieve the values of JNDIName and QueueName properties.

Below you can see the descriptor for the template-config.xml:

	<template-config template="vm/jbossmessaging-queue.xml.vm" extension="-service.xml">
		<property-list>
		<property name="QueueName" type="java.lang.String" optional="false"/>
		</property-list>
	</template-config>

jbossmessaging-queue.xml.vm mentioned above, is the name of the actual Velocity template XML descriptor for the queue, which you can see below:

	<?xml version="1.0" encoding="UTF-8"?>
	<!--  ===================  QueueName - $QueueName ======= -->
	<server>
		<mbean code="org.jboss.jms.server.destination.QueueService"
						name="jboss.messaging.destination:service=Queue,
						name=$QueueName" xmbean-dd="xmdesc/Queue-xmbean.xml">

		<depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
		<attribute name="Clustered">true</attribute>
		<depends>jboss.messaging:service=PostOffice</depends>
		</mbean>
	</server>

Implementation:
I created a service bean that will acquire proxies for the JBoss MainDeployerMBean and JBoss DeploymentServiceMBean. I will use JBoss deployment service to construct a queue module in the file system, and I will use JBoss main deployer to deploy the queue, by pointing it to the module in the file system. My implementation of my service bean as follows:

public class DeploymentService
	extends ServiceMBeanSupport
		implements DeploymentServiceMBean {

	private static final String
		JBOSS_MAIN_DEPLOYER_SERVICE = "jboss.system:service=MainDeployer";
	private static final String
		JBOSS_DEPLOYMENT_SERVICE = "jboss:service=DeploymentService";

	private MainDeployerMBean mainDeployerService = null;
	private DeploymentServiceMBean jbossDeploymentService = null;

	public void startService() throws Exception {

		try {
			//get proxy for main deployer service bean
			mainDeployerService = getJBossMainDeployer();
		}
		catch (MBeanProxyCreationException e)  {
			e.printStackTrace();
		}

		try {

			//get proxy for deployemnt service bean
			jbossDeploymentService = getJBossDeploymentService();
		}
		catch (MBeanProxyCreationException e)  {
			e.printStackTrace();
		}

		deploy();
	}

	public void stopService() {

	}

	private void deploy()  {

	//hashmap contains properties for the queue template
	HashMap<String, Object> properties = new HashMap<String, Object>();

	//short file name of my queue
	String destination = "myqueue-service.xml";

	//directory name where the queue Velocity template is kept,
	//inside 'dynamic-templates' dir
	String template = "jbossmessaging-queue";

	//property that holds a queue name for the Velocity template
	properties.put("QueueName", "myqueue");

	String resultingFileName = "";

	//create a queue module in a filesystem, at this stage queue
	//is not deployed yet.
	try {
		resultingFileName = jbossDeploymentService
				.createModule(destination, template, properties);
	} catch (Exception e) {
			e.printStackTrace();
	}

	String path = constructPath(destination);

	try {
		//check whether deployment exists for the given
		//module queue in the file system
		if (!mainDeployerService.isDeployed(path)) {

			mainDeployerService.deploy(path);
		}
	} catch (MalformedURLException e) {
		e.printStackTrace();
	}

	}

	//construct an absolute path to the queue module in a filesystem
	//for a given name.
	private String constructPath(String shortName) {
	String path = ServerConfigLocator.locate().getServerHomeDir()
				.getAbsolutePath()
				+ "/"
				+ jbossDeploymentService.getUndeployDir()
				+ "/"
				+ shortName;
		return path;
		}

	//Constructs and returns a proxy for MainDeployerMBean
	private MainDeployerMBean getJBossMainDeployer()
						throws MBeanProxyCreationException
	{
		MBeanServer server = getServer();

		ObjectName serviceName = new ObjectName(JBOSS_MAIN_DEPLOYER_SERVICE);

	//'false' -> dont make the returned proxy implement NotificationEmitter interface
		MainDeployerMBean mainDeployer =
		(MainDeployerMBean) MBeanServerInvocationHandler
					.newProxyInstance(server, serviceName,
						MainDeployerMBean.class, false);

	  return mainDeployer;
	}

	//Constructs and returns a proxy for DeploymentServiceMBean
	private DeploymentServiceMBean getJBossDeploymentService()
						throws MBeanProxyCreationException
	{
		MBeanServer server = getServer();

		ObjectName serviceName = new ObjectName(JBOSS_DEPLOYMENT_SERVICE);

	//'false' -> dont make the returned proxy implement NotificationEmitter interface
		DeploymentServiceMBean deploymentService =
		(DeploymentServiceMBean) MBeanServerInvocationHandler
					.newProxyInstance(server, serviceName,
						DeploymentServiceMBean.class, false);

	  return deploymentService;
	}

}

Two main points that i want to explain here are:
createModule() method of JBoss deployment service and
deploy() of JBoss main deployer.

createModule() - accepts three arguments: resulting file name (in this case is myqueue-service.xml), the directory name where the Velocity template is kept and a HashMap object which contains properties for the template.

JBoss deployment service will use the Velocity template to generate myqueue-service.xml module under dynamic-undeploy directory.

deploy() – accepts a path to the module in the system and deploys the module. In this case the path to the module is:

/opt/mitto/jboss/server/mitto/dynamic-undeploy/myqueue-service.xml

Thats about it :) You can use Velocity templates to deploy queues, message-driven and other types of beans. Basically anything that has XML descriptors.

I really hope I was clear enough in this example, since it is quite con-sized.