piątek, 21 października 2011

Immutable value objects with Hibernate

Value objects are one the foundations of the Domain Driven Design. To take most of the benefits connected to them they should be immutable. This however causes some challenges when using them as an attributes of entities mapped using Hibernate.

Let's take a look at sample value object representing currency.

package com.acme;

public final class Currency implements Serializable {

 public static final Currency EUR = new Currency("EUR");  
 public static final Currency USD = new Currency("USD");  

 private final String code;
 
 public static Currency valueOf(String code) {
  if (EUR.getCode().equals(code) {
   return EUR;
  }
  if (USD.getCode().equals(code) {
   return EUR;
  }
  return new Currency(code);
 }

 private Currency(String code) {
  this.code = code;
 }
 
 public String getCode() {
  return code;
 }
 
 @Override
 public boolean equals(Object obj){
  if (!(obj instanceof Currency))
   return false;
  return code.equals(((Currency) obj).getCode()); 
 }
 
 @Override
 public int hashCode(){
  return code.hashCode();
 }
 
 @Override
 public String toString() {
  return code;
 }
}

Currency class is immutable which means that it is final, all of its fields are immutable and declared as final. Moreover it does not have any public constructor but instead it has a factory method which caches most commonly used values.

Now let's assume that we have an Order entity which has Currency as one of its attributes:

package com.acme;

import javax.persistence.Entity;

@Entity
public class Order {
 // ...
 private Currency currency;

 // ...
 public Currency getCurrency() {
  return currency;
 }

 public void setCurrency(Currency currency) {
  this.currency = currency;
 }
}

To map Order.currency attribute we need to create implementation of org.hibernate.usertype.UserType interface which will handle mapping of Currency class to VARCHAR database column.

package com.acme;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

public class CurrencyType extends AbstractImmutableType {
 
 public static final String TYPE = "com.acme.CurrencyType"; 

 private static final int[] SQL_TYPES = { 
    Types.VARCHAR 
 };
    
 public CurrencyType() {
  super();
 }

 public Object nullSafeGet(ResultSet rs, String[] names, 
    Object owner) throws SQLException {
  String value = rs.getString(names[0]);
  if (rs.wasNull()) {
   return null;
  }
  return Currency.valueOf(value);
 }

 public void nullSafeSet(PreparedStatement st, Object value, 
    int index) throws SQLException {
  if (value != null) { 
   st.setString(index, ((Currency)value).getCode());
  } else {
   st.setNull(index, SQL_TYPES[0]);
  }
 }

 public Class<?> returnedClass() {
  return Currency.class;
 }

 public int[] sqlTypes() {
  return SQL_TYPES;
 }
}

It uses AbstractImmutableType class which is defined as follows:

package com.acme;

import java.io.Serializable;

import org.hibernate.usertype.UserType;

public abstract class AbstractImmutableType 
  implements UserType {

 public AbstractImmutableType() {
  super();
 }

 public boolean isMutable() {
  return false;
 }
 
 public Serializable disassemble(Object value) {
  return (Serializable) value;
 }
 
 public Object assemble(Serializable cached, Object owner) {
  return cached;
 }

 public Object deepCopy(Object value) {
  return value;
 }

 public Object replace(Object original, Object target, 
   Object owner) {
  return original;
 }
 
 public boolean equals(Object x, Object y) {
  if (x != null && y != null) {
   return x.equals(y);
  }
  // Two nulls are equal as well
  return x == null && y == null;
 }

 public int hashCode(Object x) {
  if (x != null) {
   return x.hashCode();
  }
  return 0;
 }
}

To use CurrencyType we have to annotate Order.currency attribute with Hibernate's @Type annotation:

package com.acme;

import javax.persistence.Entity;

import org.hibernate.annotations.Type;

@Entity
public class Order {
 // ...
 private Currency currency;

 // ...
 @Type(type = CurrencyType.TYPE)
 public Currency getCurrency() {
  return currency;
 }

 public void setCurrency(Currency currency) {
  this.currency = currency;
 }
}

Mixins aka traits implementation in java

Mixins, also known as traits in some programming languages, are very useful language constructions. They cover most of the use cases where one's might want to use multi-inheritance but conceptually are much simpler. Unfortunately java does not support mixins. Nonetheless with some help from one of bytecode generation libraries like CGLib or javassit it is possible to implement simple mixins support in less then 100 lines of code.

The idea is to use java interface to define mixin methods. Additionally such interface should be marked with @Mixin annotation which will provide information about the class which implements mixin interface and acts as, possibly incomplete, mixin implementation.

@Retention(RetentionPolicy.RUNTIME)
@Target(TYPE)
public @interface Mixin {
  /** 
   * Class implementing mixin interface.
   */
  Class<?> impl();
}

The class which wants to extend mixin must be defined as abstract and must implement mixin interface. Class might extend more then one mixin.

The actual, non abstract implementation for mixin methods is build by helper class which here is called MixinBuilder.

Simple yet complete implementation of MixinBuilder using javassit library is presented below. It does not perform any kind of validation of the setup. Moreover it does not handle the case when more then one mixin defines and implement the same method or two mixins depend on each other. But all those limitations are quite easy extensions to presented code.

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;

public class MixinBuilder {
 private static Object invoke(Method method, Object target, 
    Object[] args) throws Exception {
  return target.getClass().getMethod(method.getName(),
    method.getParameterTypes()).invoke(target, args);
 }
 
 @SuppressWarnings("unchecked")
 private static <T> T newMixinInstance(final Object parent, 
    final Class<T> mixinImpl) {
  try {
   final ProxyFactory proxy = new ProxyFactory();
   proxy.setSuperclass(mixinImpl);
   return (T) proxy.create(null, null, new MethodHandler() {
    public Object invoke(Object target, Method method, 
      Method superMethod, Object[] args) 
      throws Throwable {
     // Delegate invocations of abstract methods 
     // to parent object.
     if (Modifier.isAbstract(method.getModifiers())) {
      return MixinBuilder.invoke(method, parent, args);
     }
     return superMethod.invoke(target, args);
    }
   });
  } catch (Exception e) {
   throw new IllegalArgumentException(e);
  }
 }
 
 @SuppressWarnings("unchecked")
 public static <T> T newInstance(final Class<T> mainClass) {
  try {
   final ProxyFactory proxy = new ProxyFactory();
   proxy.setSuperclass(mainClass);
   return (T) proxy.create(null, null, new MethodHandler() {
    private Map<Class<?>,Object> mixinMap = 
      new HashMap<Class<?>, Object>();
    
    public Object invoke(Object target, Method method, 
        Method superMethod, Object[] args) 
        throws Throwable {
     // Delegate invocations of abstract methods 
     // to mixin.
     if (Modifier.isAbstract(method.getModifiers())) {
      Class<?> mixinInterface = method.getDeclaringClass();
      if (!mixinMap.containsKey(mixinInterface)) {
       Mixin annotation = mixinInterface.getAnnotation(
          Mixin.class);
       final Class<?> mixinClass = annotation.impl();
       mixinMap.put(mixinInterface, 
          newMixinInstance(target, mixinClass));
      }
      Object mixin = mixinMap.get(mixinInterface);
      return MixinBuilder.invoke(method, mixin, args);
     }
     return superMethod.invoke(target, args);
    }
   });
  } catch (Exception e) {
   throw new IllegalArgumentException(e);
  }
 }

Sample usage of MixinBuilder might look like this:

@Mixin(impl = MixinAImpl.class)
 public interface MixinA {
  void a();
  void doA();
 }
 
 public abstract class MixinAImpl implements MixinA {
  public void a() {
   System.out.println("MixinAImpl.a()");
   doA();
  }
 }
 
 @Mixin(impl = MixinBImpl.class)
 public interface MixinB {
  void b();
  void doB();
 }
 
 public abstract class MixinBImpl implements MixinB {
  public void b() {
   System.out.println("MixinBImpl.b()");
   doB();
  }
 }
 
 public abstract class Test implements MixinA, MixinB {
  public void doA() {
   System.out.println("Test.doA()");
   b();
  }
  public void doB() {
   System.out.println("Test.doB()");
  }
  public void test() {
   System.out.println("Test.test()");
   a();
  }
 
  public static void main(String[] args) {
   MixinBuilder.newInstance(Test.class).test();
  }
 }

When executed it will display following output:

Test.test()
MixinAImpl.a()
Test.doA()
MixinBImpl.b()
Test.doB()

We can clearly see how execution of single method on Test class causes MixinAImpl execution which indirectly calls Test and MixinBImpl.

If you need more complete ready to use solution check out: Multiple Inheritance and Traits in Java

piątek, 25 lutego 2011

How to check if composite component's attribute is set?

Composite components are one of the nicest features of the facelets. They allow to easily bundle some parts of markup as reusable components.
One of the common problems with them is the inability to check if the actual attribute has been set on component usage. This has been partially solved in JSF 2.0 by allowing to set default value for an attribute but still it isn't perfect.
Here is my solution for this problem which is based on the observation how facelets pass values between different fragments of the markup.
Solution uses custom tag handler which will process its content only if the attribute with given name has been set for the composite component.

public class IfHasAttributeTagHandler extends TagHandler {
 private final TagAttribute name;

 public IfHasAttributeTagHandler(TagConfig config) {
  super(config);
  name = getRequiredAttribute("name");
 }

 public void apply(FaceletContext ctx, UIComponent parent)
  throws IOException, FacesException, ELException {
  if (ctx.getVariableMapper().resolveVariable(
   name.getValue(ctx)) != null) {
   nextHandler.apply(ctx, parent);
  }
 }
}

The sample usage of this component might look like this:

<c:set var="hasArg" value="false" />
<custom:ifHasAttribute name="arg">
  <c:set var="hasArg" value="true" />
</custom>

Of course in the similar way you can build component which will process its content only is the attribute hasn't been defined.

wtorek, 8 lutego 2011

HttpSession passivation and Spring Part 1

Many users of Spring framework forget about or are not aware of important requirement which states that all HttpSession attributes must be serializable if the session should be passivable.

Let's start with some simple web application which has two session beans: UserBean and EditOrderBean and two singletons: UserDAO and OrderDAO. Those beans might look like those:

public class OrderDAO { 
  // actual code is not important in this context
}

public class UserDAO { 
  // actual code is not important in this context
}

public class UserBean {
 private String login;
 // userDAO is managed by Spring
 private UserDAO userDAO;
 
 // constructor, getters and setters
}

public class EditOrderBean {
 private String item;
 private int quantity;
 // orderDAO is managed by Spring
 private OrderDAO orderDAO;
 // userBean is managed by Spring
 private UserBean userBean;
 
 // constructor, getters and setters
}

As simple as it seems it is not correct implementation and it will cause problems in distributed environment or on application server which has session passivation enabled. To fix this both UserBean and EditOrderBean bean classes must be serializable. To do so we should add Serializable interface to them and mark all non session bean references as transient.

public class UserBean implements Serializable {
 private String login;
 // userDAO is managed by Spring
 private transient UserDAO userDAO;
 
 // constructor, getters and setters
}

public class EditOrderBean implements Serializable {
 private String item;
 private int quantity;
 // orderDAO is managed by Spring
 private transient OrderDAO orderDAO;
 // userBean is managed by Spring
 private UserBean userBean;
 
 // constructor, getters and setters
}

After those changes session will passivate but unfortunately after activation both our beans will be missing references to the beans which has been marked as transient. To reset them we must use little known method from Spring's AutowireCapableBeanFactory interface called configureBean. It gets two arguments: existing bean instance and beans name and performs bean initialization.

Call to this method should be made just after session activation but before its usage. This can be achieved using HttpSessionActivationListener interface.

public class RestoreSpringSessionListener implements
  HttpSessionActivationListener {
 @Override
 public void sessionDidActivate(HttpSessionEvent sessionEvent) {
  HttpSession session = sessionEvent.getSession();
  ServletContext servletContext = session.getServletContext();
  WebApplicationContext webAppContext = WebApplicationContextUtils.
    getRequiredWebApplicationContext(servletContext);
  AutowireCapableBeanFactory autowireFactory = webAppContext.
    getAutowireCapableBeanFactory();

  // Iterate through all session attributes, check if they are 
  // Spring managed beans and if they are reconfigure them.
  Enumeration<String> names = session.getAttributeNames();
  while (names.hasMoreElements()) {
   String name = names.nextElement();

   // This checks only if the bean with given name is defined.
   // It does not check if it has session scope.
   if (webAppContext.containsBean(name)) {
    Object bean = session.getAttribute(name);

    // Reconfigure resored bean instance.
    bean = autowireFactory.configureBean(bean, name);
    session.setAttribute(name, bean);
   }
  }
 }

 @Override
 public void sessionWillPassivate(HttpSessionEvent sessionEvent) { 
 }
} 

Now you just need to register this listener in your web.xml:
<web-app ...>
  ...
  <listener>
    <listener-class>
      com.acme.RestoreSpringSessionListener
    </listener-class>
  </listener>
  ...
</web-app>

Please be aware that this solution works only with quite simple bean configurations. This means that it won't work for instance if you are using:
  • destroyable beans,
  • complex bean initialization,
  • proxies around beans,
  • aop-scoped proxies.

I will try to address at least some of those limitations in the third part of this article.

Another solution for given problem is a custom implementation of session scope. This will be presented in second part of this article.