Tuesday, October 21, 2008

Best way to check for all alphabetic, alphanumeric or numeric strings

The best way of checking whether the string is a pure alphabetic, alphanumeric or numeric is to use the String class's matches method by using the regex pattern as a parameter.
  if ("!abc123".matches("[a-zA-Z]*")) {
      System.out.println("Pure alphabetic string");
  } else {
      System.out.println("Not pure alphabets");
  }

Sunday, October 5, 2008

Auto Injection of a Logger into Spring beans

Dependency injection using Spring provides an easy way of injecting logging implementations to beans configured using Spring. Spring inherently use (JCL) Jakarta Commons Logging which may cause class loading issues.
Refer to this post http://www.qos.ch/logging/classloader.jsp .
After searching for a while I found out that we can replace JCL with SLF4j by just replacing the commons-logging.jar with the SLF4j provided jcl-over-slf4j.x.x.x.jar implementation (Please add the required dependencies). SLF4j provides a lot of good features over good old logging implementation.
Please refer to http://www.slf4j.org.
Not going into further details lets start with our implementation of
Logger. The first step is to create a Logger annotation. The Logger annotation is shown below.

/**
* Indicates Logger of appropriate type to
* be supplied at runtime to the annotated field.
*
* The injected logger is an appropriate implementation
* of org.slf4j.Logger.
*/
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(FIELD)
@Documented
public @interface Logger {
}
Now lets define a class that actually does the job of injecting the logger implementation.
/**
 * Auto injects the underlying implementation of logger into the bean with field
 * having annotation Logger.
 * 
 */
import java.lang.reflect.Field;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.ReflectionUtils;

import static org.springframework.util.ReflectionUtils.FieldCallback;

public class LoggerInjector implements BeanPostProcessor {

 public Object postProcessAfterInitialization(Object bean, String beanName)
   throws BeansException {
  return bean;
 }

 public Object postProcessBeforeInitialization(final Object bean,
   String beanName) throws BeansException {
  ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
   public void doWith(Field field) throws IllegalArgumentException,
     IllegalAccessException {
    // make the field accessible if defined private
    ReflectionUtils.makeAccessible(field);
    if (field.getAnnotation(Logger.class) != null) {
     Log log = LogFactory.getLog(bean.getClass());
     field.set(bean, log);
    }
   }
  });
  return bean;
 }
}
Using it is even simpler. Just add the Logger annotation created above to the Log field in the required class. The class DemoBean below shows a field annotated this way. The import class Log is actually present in the jcl-over-slf4j.x.x.x.jar and does not depend on the JCL anymore.
import org.apache.commons.logging.Log;

public class DemoBean {

 @Logger
 private Log log;

 public void doSomething() {
  log.info("message");
  log.error("Lets see how the error message looks...");
 }
}
Just define the above bean in your spring application context defition. (I used XML configuration). Also you need to define a bean using the class LoggerInjector. Application contexts can auto-detect BeanPostProcessor beans in their bean definitions and apply them before any other beans get created.