Monday, May 30, 2005

Tranql and XAPool

Geronimo uses an interesting project to transform a jdbc driver into a resource adapter. This project is called Tranql. Its home page is http://tranql.codehaus.org/.

This page doesn't show a lot of informations and it is preferable to go to look at directly in the cvs ;-). The cvs is hosted by codehaus (cvs.tranql.codehaus.org) and the cvs root is /home/projects/tranql/scm.

The project only wrap JDBC driver and doesn't add support to convert a no-xa driver into an xa driver... An interested approach is to develop an integration between Tranql and XAPool. So you can easily create an XA DataSource from a simple DataSource and manage its connections with a JCA connection manager.

For example, with Tranql, you can configure a pool of connections with JCA in this way (using the Spring JCA support of Spring):


<bean id="tranqlManagedConnectionFactory"
class="org.tranql.connector.jdbc.XADriverMCF">
<property name="driverName">
<value>org.hsqldb.jdbcDriver</value>
</property>
<property name="url">
<value>jdbc:hsqldb:hsql://localhost:9002</value>
</property>
<property name="user">
<value>sa</value>
</property>
<property name="password">
<value></value>
</property>
</bean>


So, to transform this DataSource in a XA compliant one, you only need to change the implementation of the ManagedConnectionManager. This XAPoolDataSourceMCF one integrates XAPool and use its StandardXADataSource class.
The configuration is now:


<bean id="tranqlManagedConnectionFactory"
class="org.tranql.connector.jdbc.XAPoolDataSourceMCF ">
<property name="driverName">
<value>org.hsqldb.jdbcDriver</value>
</property>
<property name="url">
<value>jdbc:hsqldb:hsql://localhost:9002</value>
</property>
<property name="user">
<value>sa</value>
</property>
<property name="password">
<value></value>
</property>
</bean>


Note: A big problem is that XAPool internally manages the enlistment/delistment of XAResource. So you need to patch this tool to remove the call of enlist and delist on the current transaction.

Here is a sample implementation of XAPoolDataSourceMCF:


package org.tranql.connector.jdbc;

import java.sql.SQLException;

import javax.sql.XAConnection;
import javax.sql.XADataSource;

import org.enhydra.jdbc.standard.StandardXADataSource;
import org.tranql.connector.AllExceptionsAreFatalSorter;

public class XAPoolDataSourceMCF extends AbstractXADataSourceMCF {

public XAPoolDataSourceMCF() {
super(new StandardXADataSource(),new AllExceptionsAreFatalSorter());
}

public String getUserName() {
return ((StandardXADataSource)xaDataSource).getUser();
}

public String getPassword() {
return ((StandardXADataSource)xaDataSource).getPassword();
}

public void setDriverName(String driverName) {
try {
((StandardXADataSource)xaDataSource).setDriverName(driverName);
} catch (SQLException ex) { ex.printStackTrace(); }
}

public void setUrl(String url) {
((StandardXADataSource)xaDataSource).setUrl(url);
}

public void setUser(String user) {
((StandardXADataSource)xaDataSource).setUser(user);
}

public void setPassword(String password) {
((StandardXADataSource)xaDataSource).setPassword(password);
}

}


The latest ManagedConnectionFactory implementation supports XA transactions!

Friday, May 20, 2005

Spring JCA support is out

The JCA CCI support is now integrated in the Spring framework 1.2.
You can view the corresponding org.springframework.jca package in the Spring CVS of at the following url:

http://cvs.sourceforge.net/viewcvs.py/springframework/spring/src/org/springframework/jca/

Thursday, January 13, 2005

Using of Ant in Eclipse

In order to use the javac task of ant when you launch ant in Eclipse, you need to configure a system property to use the Eclipse compiler.
To do this, you can use a system property for the ant process (-D).

-Dbuild.compiler=org.eclipse.jdt.core.JDTCompilerAdapter


or a task in ant to initialize it. This task you must be called before every other tasks.

<project name="spring-core" default="traduction" basedir=".">

<target name="eclipse" if="eclipse.running">
<property name="build.compiler"
value="org.eclipse.jdt.core.JDTCompilerAdapter" />
</target>

<target name="page-preface" depends="eclipse" description="overview">
...
</target>

...
</project>

Tuesday, December 21, 2004

Datasources selection with Spring

The aim is to permit to an application (and the user) to select a specific datasource to use, so a user can choose a specific database and datas to access. We can use the same mechanism than Acegi: a filter to get the datasource name and place it in known holder ( based on a thread local ) and a specific datasource ( proxy on datasources ) to get this name in order to select the datasource to use.

- Datasource name context: it's in fact a class to store the name of the DataSource et a class (a simple ThreadLocal) to hold it (the known place).
Here is an example of these two classes and interfaces:


public class DataSourceContextHolder {
private static ThreadLocal contextHolder = new ThreadLocal();

public static void setContext(DataSourceContext context) {
contextHolder.set(context);
}

public static DataSourceContext getContext() {
return (DataSourceContext) contextHolder.get();
}
}


public interface DataSourceContext {
public void setId(String id);
public String getId();
}


public class DataSourceContextImpl implements DataSourceContext {
private String id;

public void setId(String id) {
this.id=id;
}

public String getId() {
return id;
}
}


- Filter to detect context: the filter look for an datasource id in the session and put it in the context holder. The filter might be enhanced to have the feature to select the id and block this change when a user is authenticated on a database.

- Datasource selector: thanks to Spring, there is a datasource abstraction so we can put a proxy between our datasource and application. Our datasource proxy could select another datasource configure in Spring at runtime using the datasource context.
Here is an example of this proxy:


public class DataSourceSelector extends AbstractDataSource
implements BeanFactoryAware {
private BeanFactory beanFactory;

public void setBeanFactory(BeanFactory beanFactory)
throws BeansException {
this.beanFactory=beanFactory;
}

public Connection getConnection() throws SQLException {
DataSourceContext context=DataSourceContextHolder.getContext();
DataSource datasource=(DataSource)beanFactory.getBean(
context.getId());
return datasource.getConnection();
}

public Connection getConnection(String login,String password)
throws SQLException {
DataSourceContext context=DataSourceContextHolder.getContext();
DataSource datasource=(DataSource)beanFactory.getBean(
context.getId());
return datasource.getConnection(arg0,arg1);
}
}


This mechanism is independant of the application (Spring offers this
facility!) but we must be carefull to not permit to access a database
without be authenticated. The order of filter (with use of security filter such Acegi's) could be dangerous... The solution is not to permit to switch from
a datasource to another when a user is authenticated.