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() );
	}


Mar 05 2010

JAXB, XmlRootElement, and XML case sensitivity

Category: Java,JAXB,Spring Framework,XMLRussell Pitre @ 1:51 pm

Today I started to incorporate our organization’s canonical data model (a SOA design pattern) defined in XSD into a Java web app with the use of JAXB annotations. JAXB is a framework for binding Java objects to XML elements and vice versa through the use of JAXB annotations. The domain layer within our web application closely matches the canonical data model already so refactoring the web application was not necessary. The purpose of this exercise is to prepare for the development of soap-based web services.

I ran into a 2 hour wall while developing a unit test for the domain object. I want the unit test to ensure that my JAXB annotations are setup correctly and that they should be honoring the xsd document.

Here’s a look at a xsd snippet.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	targetNamespace="http://acme.com/schema/type/project/v1" 
	xmlns:project="http://acme.com/schema/type/project/v1" 
	xmlns:company="http://acme.com/schema/type/company/v1"
	elementFormDefault="qualified">

	<xsd:import namespace="http://acme.com/schema/type/company/v1" schemaLocation="../company/company.xsd"/>

	<xsd:element name="Project" type="project:ProjectType"/>
	
	<xsd:complexType name="ProjectType">
		<xsd:annotation>
			<xsd:documentation>Represents a project that acme manages.  This data is stored in the Prolog database.</xsd:documentation>
		</xsd:annotation>
		<xsd:sequence>
			<xsd:element name="name" type="xsd:string"/>
			<xsd:element name="number" type="xsd:string"/>
			<xsd:element name="status" type="xsd:string"/>
		</xsd:sequence>
		<xsd:attribute name="projectId" type="xsd:int"/>
	</xsd:complexType>
	
</xsd:schema>

Here’s a look at the domain java object.

package com.acme.model.project;

// imports removed for brevitiy

@XmlAccessorType(XmlAccessType.NONE)
@XmlType(name = "ProjectType", propOrder = {
		"name",
		"number",
		"status"
})
@XmlRootElement
public class Project extends BaseObject {

	private static final long serialVersionUID = 7189638916879376326L;

	@XmlAttribute
	private Integer projectId;
	
	@XmlElement(required = true)
	private String name;
	
	@XmlElement(required = true)
	private String number;
	
	@XmlElement(required = true)
	private String status;
	
	// getters/setters removed for brevitiy
}

Here’s a look at the unit test

package com.acme.model.project;

// imports removed for brevitiy

public class ProjectTest {

	private JAXBContext jAXBContext;
	
	@Before
	public void setup() throws Exception {
		jAXBContext = JAXBContext.newInstance(Project.class);
	}

	/**
	 * This test requires an accompying Project.xml located in
	 * src/test/resources/com/acme/model/project
	 * 
	 */
	@Test
	public void testJAXBAnnotations() throws Exception {
		Resource schemaResource = new ClassPathResource("com/acme/schema/type/project/project.xsd");
		File schema = schemaResource.getFile();
		
		Unmarshaller unmarshaller = jAXBContext.createUnmarshaller();
		SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
		unmarshaller.setSchema(sf.newSchema(schema));

		Project project = (Project) unmarshaller.unmarshal(new File("src/test/resources/com/acme/model/project/Project.xml"));

		Assert.assertNotNull(project);	
	}
}

So, lets take a look at the unit test to see what’s going on. In the unit test we’re are loading the schema definition using the resource abtraction provided by the Spring Framework on lines 21 & 22. We then create an Unmarshaller and give it the schema on lines 24-26. Setting the schema effectively tells the Unmarshaller to validate the xml file; specificying a null schema disables validation. The last step is the meat of the test, which is to unmarshall a xml file. If we have any problems with our JAXB annotations they will surely show up here.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Project xmlns="http://acme.com/schema/type/project/v1" projectId="1234">
    <name>Sample Project</name>
    <number>091234</number>
    <status>Closed</status>
</Project>

Run the test.

…and this is what we get.

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://acme.com/schema/type/project/v1", local:"Project"). Expected elements are <{http://acme.com/schema/type/project/v1}project>
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:556)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:199)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:194)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:71)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:962)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:399)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:380)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.startElement(ValidatingUnmarshaller.java:74)
.
.
.
.
.

The error is barking at us saying the element is not understood by the JAXB framework. This is where i hit a wall for about two hours today, scratching my head wondering what i had wrong. Both the xsd Project element definition and root element matched, yet still i have this problem. Everything matches up except for the @XmlRootElement on the Project class. By default, JAXB uses the camelcase version of the class name as the xml element name.

A simple configuration change from @XmlRootElement to @XmlRootElement (name = “Project”) fixed the problem and now we see green bars!


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!