Adding manpower to a late software project makes it later
Filed under: guice,java — Tags: , , , — Michael Glauche @ 17:05

After getting angry at the java.util.logger once again i was thinking how to replace it with the SLF4J logger. Although Guice provides a very nice internal binding to java.util.logger, slf4j does offer a much nicer syntax.
The devil is in the detail, as allways … if you want your logger to be initialized with the current class you can’t simply inject the logger … But .. there is a nice tutorial on the guice wiki about injecting a log4j logger. SLF4J works the same.

First you need a new annotiation, like InjectLogger:

import static java.lang.annotation.ElementType.FIELD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectLogger {
}

next is a TypeListener, that listenes to org.slf4j.Logger classes with the annotiation InjectLogger:

import java.lang.reflect.Field;

import org.slf4j.Logger;

import com.google.inject.TypeLiteral;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;

public class Slf4jTypeListener implements TypeListener {

	public <I> void hear(TypeLiteral<I> aTypeLiteral, TypeEncounter<I> aTypeEncounter) {

		for (Field field : aTypeLiteral.getRawType().getDeclaredFields()) {
			if (field.getType() == Logger.class
	            && field.isAnnotationPresent(InjectLogger.class)) {
	        	aTypeEncounter.register(new Slf4jMembersInjector<I>(field));
	        }
	      }
	}
}

Finally, you need the Slf4jMembersInjector, which does the actual injection:

import java.lang.reflect.Field;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.MembersInjector;

public class Slf4jMembersInjector<T>  implements MembersInjector<T> {
	private final Field field;
    private final Logger logger;

    Slf4jMembersInjector(Field aField) {
    	field = aField;
    	logger = LoggerFactory.getLogger(field.getDeclaringClass());
    	field.setAccessible(true);
    }

	public void injectMembers(T anArg0) {
		try {
			field.set(anArg0, logger);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}
}

Now you just need to bind your TypeListener inside your module class:

   bindListener(Matchers.any(), new Slf4jTypeListener());

The actual usage is simple, but instead of @Inject we need to use @InjectLogger :

    @InjectLogger Logger logger;

Filed under: aop,guice,java — Tags: , , , — Michael Glauche @ 10:34

Aop has many uses, from doing transaction handling to authorisation. With the powerfull Guice framework it is suprisingly easy.

In this example we mark methods from a class with a Annotiation marker use Guice to intercept them.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD)
public @interface InjectedTransaction {

}

Now, we mark a method of some class with it:

public class BasicDummyService {

 @InjectedTransaction
 public void testService() {
 System.out.println("doing testService");
 }
}

Now, we need an Interceptor, which will be called as a proxy instead of the real service:

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AopInterceptor implements MethodInterceptor {
 public Object invoke(MethodInvocation invocation) throws Throwable {
 System.out.println("Interceptor: before");
 Object o =  invocation.proceed();
 System.out.println("Interceptor: Done !");
 return o;
 }
}

Finally, we need to use Guice’s Module to configure the binding:

import com.google.inject.AbstractModule;
import com.google.inject.matcher.Matchers;

public class AopModule extends AbstractModule {

 @Override
 protected void configure() {
 bind(BasicDummyService.class);
 bindInterceptor(Matchers.any(),Matchers.annotatedWith(InjectedTransaction.class),new AopInterceptor());
 }
}

Thats it ! Now, when you call the testService() method from a guice injected class, you’ll get the following:

Injector injector = Guice.createInjector(new AopModule());
 BasicDummyService test = injector.getInstance(BasicDummyService.class);
 test.testService();

Result: 

Interceptor: before
doing testService
Interceptor: Done !

The Guice Wiki also has a nice article about AOP with Guice.

16 queries. 0.499 seconds. Powered by WordPress

Home