miércoles 29 de agosto de 2007

NameValuePair: A Java 5 generics little tutorial

One of the things I've always missed in Java is a simple class to store a couple of objects. Of course, we have HashMap, Properties, arrays and what not but they are just overkill when trying to save just a simple relationship between two objects.

With the advent of Java 5 and generics, building a ValuePair class has become a trivial task...if you can understand generics, that is. In fact, with generics we have the situation where using them is pretty simple but building classes which use them can be a nightmare. The syntax is just complex and the abstraction level they require is high. Sun offers a good tutorial on the topic (and the JDK sources are a good start as well) but may be a simple example can be of better help, and the generic ValuePair class suits the bill perfectly.

The first step is to define the interface:

public interface Couple<A, B> {
   public A getIndex();
   public B getValue();
}

The code is simple but it has subtle differences if the developer is not used to the Java 5 syntax. The first thing that has to be noticed is the use of <A, B> beside the name of the class or interface. This indicates that the class has two generic types that will need to be defined later. These types although unknown now will be available during compile time (when declaring variables). As you can see from the method declarations these types can be used along the class. Let's see an implementation:

public class ValuePair<A, B> implements Couple<A, B> {

   private A a;
   private B b;

   public ValuePair(A a, B b) {
      this.a = a;
      this.b = b;
   }

   public A getIndex() {
      return a;
   }

   public B getValue() {
      return b;
   }

}

Everything should be expected by now. The class implements a generified interface so it also includes the generic types. A couple of variables use these types as did the methods before. Things just get a little bit more interesting when subclassing our base class:

public class NameValuePair<T> extends ValuePair<String, T> {

   public NameValuePair(String a, T b) {
      super(a, b);
   }

   public String getName() {
      return getIndex();
   }

}

In the code above some of the useful features of generics are visible. First of all, only one parameter is required! The other is automatically assumed to be String, as is indicated when establishing the inheritance. Notice how the parameter (T) is the same beside the class name and beside the superclass name!

The advantages of using generified classes are shown when using them. Let's see if it has been worth the trouble with some examples:

List<Couple<Integer, Field>> fields = new ArrayList<Couple<Integer, Field>>();

Set<NameValuePair<Map<String, Date>>> setOfNamedMaps;

ValuePair<Object, Date>> = new ValuePair<Object, Date>>;

Useful, isn't it?

viernes 24 de agosto de 2007

Hibernate statistics in the Enterprise 5 world

One of the useful features of Hibernate, although a little bit hidden, is the ability to collect statistics. It applies mainly to development (staging) environments and offers a somehow complete view of the Hibernate work and performance. When looking at Hibernate statistics I'm usually interested in second level cache performance (entities and queries). Let's see how to configure everything using the new JEE5 standards:

The first step is to add cache capabilities to the JPA entities. This is quite easy using the Hibernate annotations extension

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "USERS")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Users {
   ...
}

Nothing more is needed. From now on if a second level cache manager is executing user objects will be retrieved from the cache if possible. Unfortunately, caching queries is not that easy (or should I say elegant) and you have to fallback to query hints. Of course, Hibernate has to now it should parse and use the cache annotation. Just a couple of lines in the persistence.xml files are in order:

<persistence version="1.0"...>
   <persistence-unit name="myUnit" transaction-type="JTA">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>myDS</jta-data-source>
      <properties>
         ...
         <property name="hibernate.cache.use_second_level_cache" value="true" />
         <property name="hibernate.cache.provider_class"
                                  value="org.hibernate.cache.EhCacheProvider" />
      </properties>
   </persistence-unit>
</persistence>

I have used EHCache for no particular reason here (other than being the standard in Hibernate). Choose the one that fits you most. The rest of the file is the usual configuration for a container managed usage. We are in a position where collecting statistics is interesting. To do it, we need to activate the Statistics Service. A couple of properties in the persistence.xml are added, the first one initializes the collector and the second maps the session factory to the JNDI context (so it can be retrieved later):

<property name="hibernate.generate_statistics" value="true" />
<property name="hibernate.session_factory_name" value="SessionFactory" />

Hibernate exposes the results via a JMX MBean. The easiest way to work with JMX in an application server professionally is using Spring. Spring helps with JMX in several ways (it can even start a JMX server if needed), we will leverage the exporter bean, so the Hibernate service is integrated in the server context (in this case, Weblogic 10).

<jee:jndi-lookup id="server" jndi-name="java:comp/env/jmx/runtime" />

<jee:jndi-lookup id="hibernateSessionFactory" jndi-name="SessionFactory" />

<bean id="hibernateStatistics" class="org.hibernate.jmx.StatisticsService">
   <property name="statisticsEnabled" value="true" />
   <property name="sessionFactory" ref="hibernateSessionFactory"/>
</bean>

<bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
   <property name="server" ref="server" />
   <property name="beans">
      <map>
        <entry key="Hibernate:name=statistics" value-ref="hibernateStatistics"/>
      </map>
   </property>
</bean>

Everything is done by now. A JMX console is useful to look at the values. Sun's JDK include jconsole and it should be enough. Search for the Hibernate key and the statistics node there. You should expect something like: