Oct 07 2010

Commons Daemon Procrun as a Java Service Wrapper for ActiveMQ

Category: ActiveMQRussell Pitre @ 9:58 pm

Apache Commons Daemon consists of two parts for managing daemon processes on both Unix and Windows systems. The first of two is a C library for interacting with the operating system and the second part is a Java API for interacting with the daemon. On Windows systems the C part is called Procrun and we’ll be using it to create a service wrapper for Apache ActiveMQ. Procrun consists of two executables prunsrv.exe and prunmgr.exe. The later is GUI application to manage the windows service after it has been installed.

I was lead to Procrun while setting up ActiveMQ on Windows 2008 server 64-bit. ActiveMQ ships with the popular java service wrapper by Tanuki Software but the community version of the wrapper isn’t available for 64-bit versions of windows.

If you do go ahead and install the service wrapper that ships with ActiveMQ you’ll see this warning in the wrapper.log file after starting the ActiveMQ service.

 WARNING - Unable to load the Wrapper's native library 'wrapper.dll'.
           The file is located on the path at the following location but
           could not be loaded:
             C:\JAVA\apache-activemq-5.3.1\bin\win32\..\..\bin\win32\wrapper.dll
           Please verify that the file is readable by the current user
           and that the file has not been corrupted in any way.
           One common cause of this problem is running a 32-bit version
           of the Wrapper with a 64-bit version of Java, or vica versa.
           This is a 64-bit JVM.
           Reported cause:
             C:\JAVA\apache-activemq-5.3.1\bin\win32\wrapper.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
           System signals will not be handled correctly.

I’m assuming you have already downloaded and extracted ActiveMQ.

Download native binaries

First, you’ll need to download Commons Daemon native binaries and then extract the zip file.

Copy and Rename

Navigate to the folder specific to the architecture of the OS your installing the service on, in my case it was amd64. Copy prunsrv.exe to ACTIVEMQ_HOME/bin and then rename the .exe to ActiveMQ.exe. This file is the service wrapper executable Windows will launch when the OS boots up. Next is to copy prunmgr.exe to ACTIVEMQ_HOME/bin and rename that to ActiveMQw.exe. Whatever name you choose for renaming prunsrv.exe to, make sure to rename prunmgr.exe to the same name with ‘w’ appended. This is the executable to configure and manage the windows service after it has been installed.

Install Service

Open a command prompt in Administrator mode by right-clicking and selecting “Run as Administrator”, this may only be specific to Server 2008. Navigate to ACTIVEMQ_HOME\bin where you copied the executables to. Run the following command substituting the path of your installation of ActiveMQ:

C:\Java\apache-activemq-5.4.1\bin>ActiveMQ.exe //IS//ActiveMQ 
		\ --DisplayName="Apache ActiveMQ" 
		\ --Description="Apache ActiveMQ Java Messaging Server" 
		\ --Startup=auto 
		\ --LogPath=C:\Java\apache-activemq-5.4.1\logs 
		\ --LogLevel=INFO 
		\ --LogPrefix=activemq-daemon 
		\ --StdOutput=auto 
		\ --StdError=auto 
		\ --StartPath=C:\Java\apache-activemq-5.4.1 
		\ --StartClass=org.apache.activemq.console.Main 
		\ --StartMethod=main 
		\ --StartParams=start
		\ --StartMode=jvm 
		\ --StopPath=C:\Java\apache-activemq-5.4.1 
		\ --StopClass=org.apache.activemq.console.Main 
		\ --StopMethod=main 
		\ --StopParams=shutdown 
		\ --StopMode=jvm 
		\ --Jvm=C:\Java\jdk1.6.0_18\jre\bin\server\jvm.dll 
		\ --Classpath=C:\Java\apache-activemq-5.4.1\bin\run.jar 
		\ --JvmOptions=-Xmx512M 
		\ ++JvmOptions=-Dorg.apache.activemq.UseDedicatedTaskRunner=true 
		\ ++JvmOptions=-Djava.util.logging.config.file=logging.properties 
		\ ++JvmOptions=-Dactivemq.home=C:\Java\apache-activemq-5.4.1 
		\ ++JvmOptions=-Dactivemq.base=C:\Java\apache-activemq-5.4.1 
		\ ++JvmOptions=-Dactivemq.classpath=C:\Java\apache-activemq-5.4.1\conf 
		\ ++JvmOptions=-Dcom.sun.management.jmxremote.port=9004 
		\ ++JvmOptions=-Dcom.sun.management.jmxremote.authenticate=false 
		\ ++JvmOptions=-Dcom.sun.management.jmxremote.ssl=false

The above command should get you 90% of the way there to a fully configured ActiveMQ windows service. The last 10% of configuration may be easier with the GUI in a trial and error scenario.

GUI

Launch the service manager (the executable you renamed ending with ‘w’) in Administrator mode. Below are the screenshots of each of the tabs in the service manager of fully configured ActiveMQ windows service.

 

 

 

 

 

 

UPDATE:

The above screenshot of the shutdown tab is misconfigured, use these as the arguments instead adjusting the jmx port if needed:

stop
--all
--jmxurl
service:jmx:rmi:///jndi/rmi://localhost:9004/jmxrmi


Apr 30 2010

Atomikos + ActiveMQ + Hibernate

Category: ActiveMQ,Atomikos,Java,Maven,Spring FrameworkRussell Pitre @ 9:37 pm

I recently tasked myself to put together a sample project using Atomikos TransactionsEssentials. This sample project consists of Spring 3, Hibernate 3.4, Apache ActiveMQ 5.3, and of course Atomikos TransactionsEssentials.

TransactionEssentials is an open source XA transaction manager built on top of their transaction kernel called ‘icatch‘. Essentials has basic support for JDBC/XA, JMS/XA, & JTA/XA. Once you register with Atomikos you will receive a link to download TransactionEsentials and a Maven repository url via email, we’ll proceed with the later.

Once you have the Atomikos maven repository url, either add it to the repository section of your pom.xml or add it to your internal maven repository.


<properties>
	<atomikos.version>3.5.11</atomikos.version>
	<activemq.version>5.3.1</activemq.version>
	<springframework.version>3.0.2.RELEASE</springframework.version>
</properties>

<!-- 
	Atomikos dependencies used for XA
-->
<dependency>
	<groupId>com.atomikos</groupId>
	<artifactId>transactions-jms</artifactId>
	<version>${atomikos.version}</version>
</dependency>
<dependency>
	<groupId>com.atomikos</groupId>
	<artifactId>transactions-hibernate3</artifactId>
	<version>${atomikos.version}</version>
	<exclusions>
		<exclusion>
			<artifactId>hibernate</artifactId>
			<groupId>org.hibernate</groupId>
		</exclusion>
	</exclusions>
</dependency>

<!-- 
	Microsoft JDBC driver
-->
<dependency>
	<groupId>com.microsoft</groupId>
	<artifactId>sqljdbc</artifactId>
	<version>2.0.0</version>
</dependency>

<!-- 
	Spring framework dependencies
-->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-orm</artifactId>
	<version>${springframework.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jms</artifactId>
	<version>${springframework.version}</version>
</dependency>

<!-- 
	Hibernate dependencies
 -->
<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-entitymanager</artifactId>
	<version>3.4.0.GA</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.4.2</version>
</dependency>

<!-- 
	ActiveMQ dependencies
 -->
<dependency>
	<groupId>org.apache.activemq</groupId>
	<artifactId>activemq-core</artifactId>
	<version>${activemq.version}</version>
</dependency>

Here’s the spring configuration:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

	<bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp" init-method="init" destroy-method="shutdownForce">
		<constructor-arg>
			<props>
				<prop key="com.atomikos.icatch.service">com.atomikos.icatch.standalone.UserTransactionServiceFactory</prop>
			</props>
		</constructor-arg>
	</bean>

	<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close" depends-on="userTransactionService"> 
	   <!--  When close is called, should we force transactions to terminate or not?  --> 
	   <property name="forceShutdown" value="false" /> 
	</bean>
 
	<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" depends-on="userTransactionService"> 
	   <property name="transactionTimeout" value="300" /> 
	</bean>
	
	<!--  
	   Configure the Spring framework to use JTA transactions from Atomikos   
	-->
	<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" depends-on="userTransactionService">
		<property name="transactionManager" ref="AtomikosTransactionManager" />
		<property name="userTransaction" ref="AtomikosUserTransaction" />
	</bean>

	<bean id="datasource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
		<property name="uniqueResourceName" value="XADBMS" />
		<property name="xaDataSourceClassName" value="com.microsoft.sqlserver.jdbc.SQLServerXADataSource" />
		<property name="xaProperties">
			<!--
				set the driver-specific XADataSource properties (check your driver docs for more info)
			-->
			<props>
				<prop key="user">dbuser</prop>
				<prop key="password">dbpass</prop>
				<prop key="URL">jdbc:sqlserver://dev-server;databaseName=SomeDB;applicationName=XA-Sample</prop>
			</props>
		</property>
		<property name="minPoolSize" value="1" />
		<property name="maxPoolSize" value="50" />
	</bean>

	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="configLocation" value="classpath:hibernate.cfg.xml" />
		<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
		<property name="dataSource" ref="datasource" />
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.transaction.factory_class">com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory</prop>
				<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
			</props>
		</property>
	</bean>

	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
   
   <!-- ActiveMQ Setup -->
   
	<bean id="jmsXaConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
		<property name="brokerURL" value="tcp://dev-server:61616" />
		<property name="userName" value="user"/>
		<property name="password" value="password"/>
	</bean>
   
	<!-- Configure the JMS connector; call init to register for recovery! -->
	
	<bean id="amqConnectionFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean" init-method="init">
		<property name="uniqueResourceName" value="XAactiveMQ" />
		<property name="xaConnectionFactory" ref="jmsXaConnectionFactory" />
		<property name="poolSize" value="5"/>
	</bean>

	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="amqConnectionFactory"/>
		<property name="receiveTimeout" value="2000" />
		<property name="sessionTransacted" value="true" />
	</bean>
        
	<tx:annotation-driven transaction-manager="jtaTransactionManager" />
	
	<context:component-scan base-package="com.company.application"/>
	
	<context:annotation-config/>

And that’s about it for the setup of the infrastructure components. You should be able to @Autowire a JmsTemplate, PlatformTransactionManager (or use @Transactional) and SessionFactory in your application classes.


@Repository
public class SomeEntityDaoHibernateImpl implements SomeEntityDao {

	@Autowired
	private SessionFactory sessionFactory;

	@Autowired
	private JmsTemplate jmsTemplate;
	
	@Transactional(readOnly=true)
	public SomeEntity getSomeEntity(Integer entityId) {
		return (SomeEntity ) sessionFactory.getCurrentSession().get(SomeEntity .class, entityId);
	}

	@Transactional(propagation=Propagation.REQUIRED)
	public void updateSomeEntity (SomeEntity someEntity ) {
		sessionFactory.getCurrentSession().update(someEntity );
		jmsTemplate.convertAndSend("MyCompany.SomeCompany.UPDATE", "Entity updated ["+new Date()+"]: " + someEntity.toString() );
	}


Feb 24 2010

An Event Driven Service Oriented Solution – Introduction

Category: ActiveMQ,Camel,Java,Spring Framework,SQL ServerRussell Pitre @ 7:55 pm

This is the first post in a series on the design and implementation of an event-driven service oriented solution using SQL Server 2008, Apache ActiveMQ, Apache Camel, and Spring Web Services along with a whole slew of other technologies.

Introduction

I work for a medium-sized construction management firm in the New England area. We use an off-the-shelf closed source software product to facilitate our core business processes. This is a typical fat client, whereby the business logic is executed on the client side and the data is then persisted to a central SQL Server database.

We’ve been able to mitigate our lack of integration options by using server-side SQL Server triggers and stored procedures. We use INSERT, UPDATE, & DELETE triggers to execute some of our own custom business logic. We’ve been able to do financial calculations, update columns based upon conditions of other columns, insert new records into “queue” tables, your typical SQL trigger use cases. This is about as far as we’ve been able to push the use of triggers without compromising the performance of the system and even today, on high transactional days, we see sporadic performance issues. Triggers are very powerful but do have their limitations such as being synchronous in nature and can cause some serious problems if you don’t know what you’re doing.

Today, we are running SQL Server 2000 with plans to upgrade in the very near future to SQL Server 2008 . One new feature we’ll be seeing is the Service Broker, which can be utilized for asynchronous triggers.

With the use of CLR stored procedures we have the power of the .Net framework at our hands to call services hosted outside of SQL Server and then by combining CLR stored procedures with the Service Broker we can design very powerful and scalable business solutions.

The Big Idea

Below is the system diagram of our SQL server event-driven service oriented solution. The diagram is pretty self-explanatory but we’ll go through a narrative anyhow. The basic idea is that when a record is created, updated, or deleted in SQL server, an event will be

 

 

generated through the use of a trigger. As I mentioned earlier, triggers are synchronous and if we try to call a service outside of SQL server we’ll surely run into performance issues, and not to mention what would happen if the external service went down for maintenance or system failure. In more ways than one, that would have been a poor design decision. So here’s where the Service Broker will help us out and allow us to make an asynchronous calls outside of SQL server. The trigger will be programmed to use the SQL Server Service Broker whereby messages will be sent to a queue asynchronously within the same database. A CLR stored procedure will be activated (and pooled) when messages arrive on the queue and then here is where we’ll make our call to the external service.

The external service we’ll be calling is a SOAP-based web service that serves as a SOAP API to ActiveMQ. I understand there is a .Net Messaging API called ActiveMQ NMS which we could use inside SQL Server to connect directly to ActiveMQ, perhaps we’ll refactor our system to NMS instead. The SOAP-based web service will then connect ActiveMQ and put the event message on a queue. To the right of ActiveMQ we have a OSGI based runtime that will host Apache Camel routes. Apache Camel is an integration framework implementing most of the Enterprise Integration Patterns. We’ll be using the message dispatcher functionality to dispatch our event messages to other network based services.

In a nutshell, that’s the system we’ll be building; there’s a lot to be done so let’s get started!