Saturday, August 29, 2009

New Feature Import Data from Garmin Devices

Just a quick note, www.Endurotracker.com has a new feature that lets users quickly import
data from their Garmin devices.
We used the Spring Framework, Hibernate, and Garmin's excellent xml schemas to build this feature.

Wednesday, August 12, 2009

Using Spring with multiple databases Part 5, Unit Testing using JUnit 4 and Annotations

One of the great features of the Spring framework is they have create support for Unit Testing in JUnit. Also you have the ability to use Annotations to cut down on the amount of xml you need to get your test code up and running.
Here is a example that I used to test my Login Controller:


package com.endurotracker.gwt.server.web.controllers;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.util.List;

import org.apache.log4j.Logger;
import org.junit.runner.RunWith;
import org.junit.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.context.SecurityContextImpl;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.providers.dao.DaoAuthenticationProvider;
import org.springframework.security.providers.dao.cache.EhCacheBasedUserCache;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

import com.endurotracker.gwt.dao.UsersDao;
import com.endurotracker.gwt.model.ServerSideUser;
import com.endurotracker.gwt.model.Users;
import com.endurotracker.gwt.server.service.UserService;

/**
* @author David
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/applicationContext.xml","/jndi.xml","/applicationContext-acegi-security.xml" })
@TransactionConfiguration(transactionManager="jtaTransactionManager", defaultRollback=false)
@Transactional
public class LoginControllerTest {

@Autowired
private DaoAuthenticationProvider daoAuthenticationProvider;
@Autowired
private UsersDao userDetailsService;
@Autowired
private UsersDao usersDao;
@Autowired
private EhCacheBasedUserCache userCache;

@Autowired
private UserService userService;
@Autowired
LoginController loginController;

private static final Logger log = Logger.getLogger(LoginControllerTest.class);



@Test
public void testLogin()
{
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("admin","pwd");

Authentication auth = daoAuthenticationProvider.authenticate(token);

//set SecurityContext
SecurityContext context = new SecurityContextImpl();
context.setAuthentication(auth);
SecurityContextHolder.setContext(context);

Object obj = auth.getPrincipal();
String username = "";

if (obj instanceof UserDetails) {
username = ((UserDetails) obj).getUsername();
} else {
username = obj.toString();
}

//place in Cache
log.debug("loadUserByUsername " + username);

ServerSideUser serverUser = null;

boolean useCache = true;

if (useCache) {
serverUser = (ServerSideUser) userCache
.getUserFromCache(username);
}

List users;
Users u;
if (serverUser == null) {

users = usersDao.GetByProperty("username", username);
if(users.size() > 0)
{
u = users.get(0);
userCache.putUserInCache(new ServerSideUser(u));
}
else
{
u = null;
}

}

//Test if user can now be found, after being placed in cache
Users user = userService.getCurrentUser();

loginController = new LoginController(user);

assertNotNull(loginController);



}

@Test
public void testShowLogin()
{
loginController = new LoginController();
String returnViewname = loginController.showHandler();

assertEquals("showLogin",returnViewname);
}
}



Hopefully, these posts will help some people who had very little success previously finding good examples on how to setup Spring with multiple databases (datasources).
I know I did.

Using Spring with multiple databases Part 4

In your web config file (web.xml) you reference your applicationcontext.xml file and any other configuration file that you need to use.
To configure Atomikos we created a xml file called jndi.xml and reference it in our web.xml file like so:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml,
/WEB-INF/jndi.xml
</param-value>
</context-param>



Here is how we configured Atomikos Transaction Manager in our jndi.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

<bean id="userTransactionService"
class="com.atomikos.icatch.config.UserTransactionServiceImp"
init-method="init" destroy-method="shutdownForce">
<constructor-arg>
<!-- IMPORTANT: specify all Atomikos properties here -->
<props>
<prop key="com.atomikos.icatch.service">
com.atomikos.icatch.standalone.UserTransactionServiceFactory
</prop>
<prop key="com.atomikos.icatch.enable_logging">
false
</prop>
</props>
</constructor-arg>
</bean>



<!--JTA Manager-->
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">

<!--
when close is called, should we force
transactions to terminate or not?
-->
<property name="forceShutdown" value="false" />
</bean>

<!--Also use Atomikos UserTransactionImp,
needed to configure Spring-->
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>

<bean id="jndi"
class="org.apache.xbean.spring.jndi.SpringInitialContextFactory"
factory-method="makeInitialContext">
<property name="entries">
<map>
<entry key="java:comp/TransactionManager" value-ref="AtomikosTransactionManager" />
<entry key="java:comp/UserTransaction" value-ref="AtomikosUserTransaction" />
<entry key="java:comp/UserTransactionService" value-ref="AtomikosUserTransaction" />
</map>
</property>
</bean>

</beans>


In the current trunk of Spring 3.0.0, when using the Spring MVC framework , I ended up having to place @Transactional (which tells the JVM to create a transaction) in my controller classes. I would have preferred to have them on my Data Access objects, but my Unit Tests revealed that Transactions only got created in the Spring MVC world when placed on my Controller classes.
Here is a code snippet example:

@Controller
@TransactionConfiguration(transactionManager="jtaTransactionManager", defaultRollback=false)
@Transactional
public class WizardController {

private static final Logger log = Logger
.getLogger(WizardController.class);

@Autowired
UserService userService;


In part 5, I will go over how to setup unit tests using JUnit 4 and Spring's Unit Test Annotations.

Using Spring with multiple databases Part 3

In this part, we setup our SessionFactories in our applicationcontext.xml file.
In our SessionFactories we specify our datasource, our entity classes, and also our hibernate properties.
Since we are using multiple databases, in this case 2 databases, we need to create two SessionFactory configurations.
Here is our first SessionFactory config that we place in applicationcontext.xml:

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.endurotracker.gwt.model.Users</value>

</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.isolation">3</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">com.endurotracker.gwt.transaction.AtomikosJTATransactionFactory</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
</props>
</property>
</bean>




Here is our second SessionFactory config that we place in applicationcontext.xml:

<!--Hibernate SessionFactory2-->
<bean id="sessionFactory2"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource2" />
<property name="annotatedClasses">
<list>
<value>com.endurotracker.gwt.model.Activitytype</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.isolation">3</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">com.endurotracker.gwt.transaction.AtomikosJTATransactionFactory</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
</props>
</property>
</bean>


You will notice that we have 2 hibernate properties related to transactions:
hibernate.transaction.factory_class and hibernate.transaction.manager_lookup_class.
Due to a Hibernate bug ( bug HHH-3110), we had to create the following class which we reference as com.endurotracker.gwt.transaction.AtomikosJTATransactionFactory, so you can take this code and create your own class as well and update this property to your class name:

public class AtomikosJTATransactionFactory extends JTATransactionFactory{
UserTransaction userTransaction;

@Override
protected UserTransaction getUserTransaction() {
if (this.userTransaction == null)
{
this.userTransaction = new UserTransactionImp();
}

return this.userTransaction;

}

}


In Part 4, we will configure our Atomikos Transaction Manager via Atomikos' Transaction beans, and talk about how to use @Transactional Annotations in our Data Access layer and Controller layer. In Part 5, we will setup some unit tests using JUnit 4 and Spring's unit testing Annotations.

Using Spring with multiple databases Part 2

If you want to debug the Spring and Hibernate source code, using your SVN client of choice download the prerequisites (or if you use Maven you can update your pom.xml to reference the applicable jar files).
For Spring the version is 3.0.0.Build-SNAPSHOT.
Since, we are using the Trunk (the bleeding edge), it is probably best to be able to debug their code, so I suggest you download the source code. Additionally, you will be able to more easily contribute patches if you like.

Spring 3.0 Framework Source Control Repository (SVN): https://src.springframework.org/svn/spring-framework/trunk

Hibernate Trunk SVN: http://anonsvn.jboss.org/repos/hibernate/core/trunk

To download Atomikos, go to http://www.atomikos.com/Main/TransactionsEssentials

Atomikos is open source but they have you register prior to downloading the code.

When developing web applications in Java, you can end up with a lot of lines of xml code in your config files. To alleviate the number of lines of xml configuration code, Spring introduced Annotations which allow you to add Annotations or configuration settings within your classes. The key Annotation that we will be using is @Transactional which tells the JVM to create a transaction for this class or method. Spring also has Annotations like @Controller that tells the JVM that this class is a Controller. This allows developers to cut down on the amount of xml configurations that they need to specify. Unfortunately, we still to have some xml configuration, so let's setup our datasources xml in our applicationcontext.xml file.

Here is the top section of our xml (applicationcontext.xml) file:


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">


In order to the Atomikos Transaction Manager, our datasources need to be configured
using Atomikos datasource classes. Using other datasources class types won't work.
Here is an example of how to configure the datasources:

<!-- using Atomikos DataSources -->
<bean id="dataSource" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean">
<property name="uniqueResourceName"><value>NONXADBMS</value></property>
<property name="user"><value>admin</value></property>
<property name="password"><value>password</value></property>
<property name="url"><value>jdbc:postgresql://localhost/usersdb</value></property>
<property name="driverClassName"><value>org.postgresql.Driver</value></property>
<property name="poolSize"><value>1</value></property>
<property name="borrowConnectionTimeout"><value>60</value></property>
</bean>

<bean id="dataSource2" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean">
<property name="uniqueResourceName"><value>NONXADBMS2</value></property>
<property name="user"><value>admin</value></property>
<property name="password"><value>password</value></property>
<property name="url"><value>jdbc:postgresql://localhost/accountingdb</value></property>
<property name="driverClassName"><value>org.postgresql.Driver</value></property>
<property name="poolSize"><value>1</value></property>
<property name="borrowConnectionTimeout"><value>60</value></property>
</bean>


In part 3, we will setup our SessionFactories.

Tuesday, August 11, 2009

Using Spring with multiple databases Part 1

This series of articles is about how to use the Spring framework within your application to reference multiple databases or in Java parlance datasources.
In a previous project, I used NHibernate and ActiveRecord and I was able to relatively painlessly use multiple databases. In Spring, to use multiple databases it took longer since my googling came up with some examples , but not complete enough that when tested gave me what I needed. In the Spring framework world and in the Java world in general there all several database persistences technologies. There is plain vanilla Hibernate, there is JPA via Hibernate, there is JPA via TopLink, there is Spring's HibernateTemplating, and plenty more.
To setup Spring with multiple databases, we are going to do the following:
Prerequisite:
Download and setup SpringFramework 3.0 from the Trunk.
Download and setup Hibernate 3.5 from the Trunk.
Download and setup Atomikos Transaction Manager. (optional download sources)
1) Setup our datasources in our applicationcontext.xml
2) Setup SessionFactory configurations in our applicationcontext.xml
3) Setup JTATransactionManager configurations in our applicationcontext.xml
4) Create a custom JTATransactionFactory class to deal with Hibernate bug: HHH-3110
5) Configure Atomikos (turn off logging on Atomikos)
6) Configure Dao and Controllers with @Transactional annotation
Editors Note: Need @Transactional annotation in Controller , having @Transactional in Dao did not always create a Transaction.
7) Create Unit Tests
8) Take a break!

In part 2, we will setup our datasources. In part 3, we will setup our SessionFactories.