About

Jadira is the home for Sousan and Chris Pheby's open source projects. These are reusable open source Java modules that provide first class solutions using the most effective current JEE technologies.

Search
Tag Cloud
...
Login
Tuesday
May042010

Maven Sites and Sourceforge

The Maven site for the User Type project is now online. This site makes use of the excellent Fluido Skin which gives a cleaner, crisper look in comparison to the standard skin.

There's a huge amount of metrics and reporting plugged into the site generation, but some of the features are of particular interest.

Class diagram visualisations can be found throughout the Javadocs. These are generated using the UML Graph doclet, using the following example configuration (suitable for Java 5):

			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-javadoc-plugin</artifactId>
 				<version>2.6.1</version>
 				<configuration>
 					<linksource>true</linksource>
 					<links>
 						<link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
 					</links>
 					<encoding>UTF-8</encoding>
 					<executions>
 						<execution>
 							<id>attach-javadocs</id>
 							<phase>package</phase>
 							<goals>
 								<goal>jar</goal>
 							</goals>
 						</execution>
 					</executions>
 					<aggregate>true</aggregate>
 					<doclet>gr.spinellis.umlgraph.doclet.UmlGraphDoc</doclet>
 					<docletArtifact>
 						<groupId>gr.spinellis</groupId>
 						<artifactId>UmlGraph</artifactId>
 						<version>4.6</version>
 					</docletArtifact>
 					<additionalparam>-attributes -enumconstants -enumerations -operations -types -visibility -inferrel -inferdep -hide (java.*)|(org.hibernate.*)|(org.joda.*)</additionalparam>
 				</configuration>
 			</plugin>

The enforcer plugin is being used to require Java 5, and Maven 2.2.1 - to help guarantee that builds are reproducible. Together with these requirements, the use of commons-logging is prohibited. This is a great practice which helps ensure all logging is performed using SLF4J:

 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-enforcer-plugin</artifactId>
 				<version>1.0-beta-1</version>
 				<executions>
 					<execution>
 						<id>enforce-versions</id>
 						<goals>
 							<goal>enforce</goal>
 						</goals>
 						<configuration>
 							<rules>
 								<requireMavenVersion>
 									<version>2.2.1</version>
 								</requireMavenVersion>
 								<requireJavaVersion>
 									<version>1.5.0</version>
 								</requireJavaVersion>
 								<bannedDependencies>
 									<excludes>
 										<exclude>commons-logging:*</exclude>
 									</excludes>
 								</bannedDependencies>
 								<requirePluginVersions>
 									<banLatest>true</banLatest>
 									<banRelease>true</banRelease>
 									<banSnapshots>true</banSnapshots>
 									<unCheckedPluginList></unCheckedPluginList>
 								</requirePluginVersions>
 							</rules>
 						</configuration>
 					</execution>
 				</executions>
 			</plugin>

You will also note that enforcer requires that exact versions are required for all utilised plugins. Again, this guarantees the reproducibility of builds.

Another point of interest is the use of toolchains. Toolchains allows you to externalise the JDK under which Maven runs from the JDK used for building. This would be particularly relevant for a project using recent builds of Maven which require Java 5, but needing to build using an older JDK.

			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-toolchains-plugin</artifactId>
 				<version>1.0</version>
 				<executions>
 					<execution>
 						<phase>validate</phase>
 						<goals>
 							<goal>toolchain</goal>
 						</goals>
 					</execution>
 				</executions>
 				<configuration>
 					<toolchains>
 						<jdk>
 							<version>5.0</version>
 							<vendor>sun</vendor>
 						</jdk>
 					</toolchains>
 			 	 </configuration>
 			</plugin>

Setting up a Maven site is surprisingly straightforward. A good howto guide is available on CommunityMapBuilder, and the Maven documentation describes the steps that need to performed to enable a shell which can be used with mvn site-deploy. You must display the Sourceforge logo on your Maven site, which can be achieved by including a 'poweredBy' entry in the site.xml file:

    <poweredBy>
        <logo name="Hosted by SourceForge" href="http://www.sourceforge.net/" img="http://sourceforge.net/sflogo.php?group_id=16035&amp;type=1" />
        ...
    </poweredBy>

			<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.6.1</version>
<configuration>
<linksource>true</linksource>
<links>
<link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
</links>
<encoding>UTF-8</encoding>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<aggregate>true</aggregate>
<doclet>gr.spinellis.umlgraph.doclet.UmlGraphDoc</doclet>
<docletArtifact>
<groupId>gr.spinellis</groupId>
<artifactId>UmlGraph</artifactId>
<version>4.6</version>
</docletArtifact>
<additionalparam>-attributes -enumconstants -enumerations -operations -types -visibility -inferrel -inferdep -hide (java.*)|(org.hibernate.*)|(org.joda.*)</additionalparam>
</configuration>
</plugin>
Sunday
May022010

Configuring Open Source JTA Transaction Managers with Spring

This blog post records in one place the Spring configuration required for each of the four most commonly used open source standalone transaction managers:

For Arjuna / JBossTS, apply the following configuration.:

<bean id="jbossTS"  class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple"  />
<bean id="jbossUserTransaction"  
    class="com.arjuna.ats.internal.jta.transaction.arjunacore.UserTransactionImple"  />

<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="jbossTS" />
    <property name="userTransaction" ref="jbossUserTransaction"  />
</bean>    

For JOTM, apply the following:

<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" />
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="userTransaction" ref="jotm" />
    <property name="allowCustomIsolationLevels" value="true" />
</bean>

For Atomikos, the following configuration can be used:

<bean id="atomikos" class="com.atomikos.icatch.jta.UserTransactionManager"  
    init-method="init" destroy-method="close">
   <property name="forceShutdown" value="false" />
</bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
   <property name="transactionTimeout" value="300" />
</bean>

<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
   <property name="transactionManager" ref="atomikos" />
   <property name="userTransaction" ref="AtomikosUserTransaction" />
</bean>

Finally, for Bitronix you can use the following:

<bean id="bitronixConfig" factory-method="getConfiguration" 
    class="bitronix.tm.TransactionManagerServices">
    <property name="serverId" value="spring-btm" />
</bean>
<bean id="bitronix" factory-method="getTransactionManager"
    class="bitronix.tm.TransactionManagerServices" depends-on="bitronixConfig" 
    destroy-method="shutdown" />
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="bitronix" />
    <property name="userTransaction" ref="bitronix" />
</bean>
Saturday
May012010

java.sql.Date Type(s) and the Offsetting Problem

Release 1.1 of User Type attempts to address the offsetting problem for java.sql.Date, Time, Timestamp, as well as the Joda Time and JSR 310 types. For example, here is how the problem is approached for Joda Time and JSR 310 Timestamp types:

    @Override
    public LocalTime fromNonNullValue(Timestamp value) {
        return LOCAL_DATETIME_FORMATTER.parseDateTime(value.toString()).toLocalTime();
    }

    @Override
    public Timestamp toNonNullValue(LocalTime value) {

        String formattedTimestamp = LOCAL_DATETIME_FORMATTER.print(value);
        ...
        final Timestamp timestamp = Timestamp.valueOf(formattedTimestamp);
        return timestamp;
    }

The remainder of this article discusses what the offsetting problem is and why User Type has been implemented to provide an approach for addressing it when using Hibernate with Joda Time or JSR 310.

JDBC's support for Timezones in Date, Time and Timestamp types was added in JDBC 2.1 released in 1999 (over a decade ago at the time of writing). The specification describes the rationale:

The JDBC API follows the Java platform’s approach of representing dates and times as a millisecond value relative to January 1, 1970 00:00:00 GMT. Since most databases don’t support the notion of a time zone, the JDBC 2.1 core API adds new methods to allow a JDBC driver to get/set Date, Time, and Timestamp values for a particular time zone using a Calendar.

For example,
ResultSet rs;
...
Date date1 = rs.getDate(1);

returns a Date object that wraps a millisecond value which denotes a particular date, like January 3, 1999, and a normalized time 00:00:00 in the default time zone. The time component of the Date is set to zero in the default time zone since SQL DATE values don’t have a time component. Since a Calendar was not supplied explicitly to getDate(), the default time zone (really the default Calendar) is used by the JDBC driver internally to create the appropriate millisecond value assuming that the underlying database doesn’t store time zone information.


The following example retrieves a date value in GMT—Greenwich Mean Time.

ResultSet rs;
...
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
Calendar cal = Calendar.getInstance();
Date date2 = rs.getDate(1, cal);

In the example above, a Calendar is passed explicitly to getDate() to inform the JDBC driver how to calculate the appropriate millisecond value. Note that the same result could have been achieved by simply changing the default time zone, and not passing the Calendar explicitly since the JDBC driver will use the default time zone by default.

...

from 10.5 Date, Time, and Timestamp, p47, JDBC 2.1 API Version 1.1, Seth White and Mark Hapner. October 5, 1999 4:39 pm

The rationale for this behaviour seems sensible enough, but unfortunately there is a gap between this typical behaviour and practical real-life needs. The problem lies in the use of the default zone. Many databases serve many clients, and these are not always located in the same zone as the database. In fact, it is quite comment for clients to be running in a variety of different zones.

What this results in is unexpected behaviour when reading and writing from the database. For example, suppose my database is configured using UTC but I am interacting with the database from a client whose default zone is British Summer Time - what kind of behaviour can I expect?

Well, supposing a SQL Timestamp row contains 2010-08-01T10:10:10.111Z, then when I read this data from the database, it will unmarshal into a java.sql.Timestamp with the following literal value: 2010-08-01T09:10:10.111Z. This is the same actual timestamp but rendered in the BST zone. Similar behaviour occurs when I write values.

In itself, this behaviour could actually be appropriate, after all these Java types have both a millisecond value and a zone. Nevertheless, this behaviour can be surprising at the best of times. The availability of new Java date and time APIs has made this behaviour even more desirable. Joda Time and JSR 310 model types including combinations of dates, times with and without zones, millisecond instances, and periods of elapsed time. In the case local dates, times and datetimes - that is points in time without zone information, the desired behaviour is to be able to persist the value as literally supplied.

This problem is not new. It is discussed in some detail in the Hibernate forums, JSR 310 mailing list, Stackoverflow:

For more information on User Type visit the Sourceforge Project page.

Sunday
Apr252010

Testing Classes using java.util.Date with JMockit

A great article on LShift Ltd's blog discusses using JMockit to mock out System.currentTimeMillis():

@MockClass(realClass = System.class)
public class MockSystem {
    private Calendar now = null;

    public MockSystem(Calendar now) {
        this.now = now;
    }

    @Mock
    public long currentTimeMillis() {
        return now.getTimeInMillis();
    }
}
Thursday
Apr222010

Release: User Type for JSR 310 Version 1.0

Announcing User Type, our Apache 2.0 licensed library of additional capabilities for working with Hibernate, Relase 1.0 of which contains User Types for use with Hibernate and JSR 310. These have been tested, where relevant to ensure you can read data written by Joda Time Hibernate using this library.

To download the release and to find out more, visit http://usertype.sourceforge.net/