Thursday, 7 November 2013

Custom annotation in JPA

Entry in orm.xml

<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="com.wdpr.dataaccess.jpa.EntityAuditListener" />
<entity-listener class="com.wdpr.dataaccess.jpa.SpaceRTrimListener" />
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>

Listener class

package com.wdpr.dataaccess.jpa;

import com.wdpr.dataaccess.annotation.RTrim;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;

public class SpaceRTrimListener
{
  private static final Map<Class<?>, Set<Field>> trimProperties = new HashMap();
  private static final String EMPTY_STRING = "";
  private static final String RIGHT_TRIM_PATTERN = "\\s+$";

  @PrePersist
  @PreUpdate
  public void rTrimnSpaces(Object entity)
    throws Exception
  {
    for (Field fieldToTrim : getTrimProperties(entity.getClass()))
    {
      String propertyValue = (String)fieldToTrim.get(entity);
      if (propertyValue != null)
      {
        fieldToTrim.set(entity, rightTrim(propertyValue));
      }
    }
  }

  private String rightTrim(String propertyValue)
  {
    if ((propertyValue != null) && (!"".equals(propertyValue.trim())))
    {
      propertyValue = propertyValue.replaceAll("\\s+$", "");
    }
    return propertyValue;
  }

  private Set<Field> getTrimProperties(Class<?> entityClass) throws Exception
  {
    if (Object.class.equals(entityClass))
    {
      return Collections.emptySet();
    }
    Set propertiesToTrim = (Set)trimProperties.get(entityClass);
    if (null == propertiesToTrim)
    {
      propertiesToTrim = new HashSet();
      for (Field field : entityClass.getDeclaredFields())
      {
        if (field.getAnnotation(RTrim.class) == null)
          continue;
        if (field.getType().equals(String.class))
        {
          field.setAccessible(true);
          propertiesToTrim.add(field);
        }
        else {
          String errorMessage = "Entity : " + entityClass.getName() + " Field : " + field.getName() + " of type : " + field.getType() + " cannot use Rtrim annotation";

          throw new IllegalArgumentException(errorMessage);
        }
      }

      trimProperties.put(entityClass, propertiesToTrim);
    }
    return propertiesToTrim;
  }

}

Difference between class level and object locking and static object lock

1) Class level locking will lock entire class, so no other thread can access any of other synchronized blocks. 2) Object locking will lo...